Skip to page content

App Network
v2.34+

AppNetwork 插件会持续维护一份对浏览器所处网络的响应式描述。它封装了 Navigator.onLine 属性,配合 online/offline 事件;并且在浏览器暴露了 Network Information API 的地方,也会一并利用它。

用法

// outside of a Vue file
import { AppNetwork } from 'quasar'
AppNetwork.online // Boolean

// inside of a Vue file
import { useQuasar } from 'quasar'
setup () {
  const $q = useQuasar()
  // now use $q.network.online (Boolean)
}

下面这个示例演示了如何读取插件暴露的各项网络信息,并在联网状态变化时记录事件日志(切换网络连接或用浏览器 DevTools 限速,即可看到这些值发生变化):

<template>
  <div class="q-pa-md">
    <div>
      Toggle your network connection (or throttle it from the browser's
      DevTools) to see the values change.
    </div>

    <q-markup-table class="q-mt-md" flat bordered>
      <tbody>
        <tr>
          <td>online</td>
          <td>{{ $q.network.online }}</td>
        </tr>
        <tr>
          <td>hasConnectionInfo</td>
          <td>{{ $q.network.hasConnectionInfo }}</td>
        </tr>
        <tr>
          <td>effectiveType</td>
          <td>{{
            $q.network.effectiveType ?? 'not exposed by this browser'
          }}</td>
        </tr>
        <tr>
          <td>downlink</td>
          <td>{{ $q.network.downlink ?? 'not exposed by this browser' }}</td>
        </tr>
        <tr>
          <td>rtt</td>
          <td>{{ $q.network.rtt ?? 'not exposed by this browser' }}</td>
        </tr>
        <tr>
          <td>saveData</td>
          <td>{{ $q.network.saveData ?? 'not exposed by this browser' }}</td>
        </tr>
      </tbody>
    </q-markup-table>

    <q-markup-table v-if="eventList.length > 0" class="q-mt-md" flat bordered>
      <tbody>
        <tr v-for="evt in eventList" :key="evt.timestamp">
          <td>{{ evt.timestamp }}</td>
          <td>{{ evt.label }}</td>
        </tr>
      </tbody>
    </q-markup-table>
  </div>
</template>

<script setup>
import { useQuasar } from 'quasar'
import { ref, watch } from 'vue'

function pad(number) {
  return (number < 10 ? '0' : '') + number
}

const $q = useQuasar()
const eventList = ref([])

watch(
  () => $q.network.online,
  state => {
    const date = new Date()
    eventList.value.unshift({
      timestamp:
        pad(date.getHours()) +
        ':' +
        pad(date.getMinutes()) +
        ':' +
        pad(date.getSeconds()) +
        '.' +
        date.getMilliseconds(),
      label: state ? 'Back online' : 'Went offline'
    })
  }
)
</script>
“online” 究竟意味着什么

online 为 false 是可靠的:这说明浏览器确知自己没有网络。而 online 为 true 只告诉你「存在某种网络」。强制门户(captive portal)、一台没有上行链路的路由器、一条已经断开的 Wi-Fi 链路,都仍会上报 true,所以请把它当作一个「提示」,让你真实的请求来给出最终结论。

连接详情

基于 Chromium 的浏览器(Chrome、Edge、Opera、Samsung Internet、Android WebView)还额外暴露了 Network Information API,插件会把它映射为 effectiveType、downlink、rtt 和 saveData。Firefox 和 Safari 并未实现它,因此在这些浏览器上,这四个属性会保持 undefined,且 hasConnectionInfo 为 false。

<template>
  <q-banner v-if="$q.network.saveData" class="bg-grey-3">
    Data Saver is on, so images load at a lower quality.
  </q-banner>
</template>

这些值是浏览器自己给出的估算,且被有意做了取整处理(它们是一种指纹追踪向量);它们描述的是「链路」,而非「对端」:一个 4g 的 effective type 并不能说明你的 API 会多快给出应答。

混合应用(Hybrid apps)

Capacitor 和 Cordova 应用还可以额外依赖它们各自的原生网络插件,那些插件了解设备的无线电(radio)状态。而 AppNetwork 依旧是 Web 侧的答案,因此它同样能在 WebView 内、Electron 上以及作为 PWA 运行。

监听状态变化

<template>...</template>

<script setup>
  import { useQuasar } from 'quasar'
  import { watch } from 'vue'

  const $q = useQuasar()

  watch(
    () => $q.network.online,
    val => {
      console.log(val ? 'Back online' : 'Went offline')
    }
  )
</script>

SSR 与 SSG

在服务端没有网络可供观测,因此 $q.network.online 为 true,hasConnectionInfo 为 false,各连接属性均为 undefined。在客户端,插件只有在 hydration 完成之后才会填入真实的值,这样即便页面是在离线状态下加载的(例如从 PWA 缓存中加载),也能避免服务端渲染出的标记与之产生不一致。