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 为 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 会多快给出应答。
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 缓存中加载),也能避免服务端渲染出的标记与之产生不一致。