# 笔记
# 2022 年 4 月 1 日
# 统计网站在线时长思考
常规方法:通过监听 beforeUnload
方法,判断用户退出或关闭页面的操作,但会有以下几点问题
- 当直接关闭浏览器或关闭电脑时,无法监听
beforeUnload
事件 beforeUnload
事件兼容性问题,各个浏览器的表现行为不一致
其他方法:开启一个定时器,每隔一段时间(1/5/10min
)记录结束时间 endTime
到 localstorage
,进入平台记录开始时间 startTime
,当可以正常监听到 beforeUnload
事件时,可以通过 sendBeacon
方法提交到后端;若页面非正常关闭时,可以在下一次访问页面时再提交这个访问时间
存在优势:
- 能够保证非正常关闭页面情况下数据不丢失
- 数据误差较小(
1/5/10min
)
存在劣势:
- 非正常关闭页面情况下,需要下一次访问才能将上一次的访问时间发送给后端
- 在同时打开多页面的情况下,会产生重复数据,难以去重
onvisibilitychange
兼容性研究
鼠标点击 tab 切换 | alt+tab 切换程序 | 点击-缩小浏览器 | win+D 缩小浏览器 | × 关闭浏览器 | alt+F4 关闭浏览器 | 刷新 | |
---|---|---|---|---|---|---|---|
Chrome | √ | √ | √ | √ | √ | √ | √ |
火狐 | √ | × | √ | √ | √ | √ | √ |
Edge | √ | √ | √ | √ | √ | √ | √ |
Opera | √ | √ | √ | √ | √ | √ | √ |
360 | √ | × | √ | √ | √ | √ | √ |
# 2022 年 4 月 2 日
# JS 保存快捷方式思考
pc 端保存当前页面到桌面,参考代码如下(来源于百度),利用桌面快捷方式为 .url
后缀的文件,模拟点击事件生成这么一个文件而达到“桌面快捷方式”的目的
function urlDownload(content, fileName) {
const eleLink = document.createElement("a")
eleLink.download = fileName
eleLink.style.display = "none"
const blob = new Blob([content])
eleLink.href = URL.createObjectURL(blob)
document.body.appendChild(eleLink)
eleLink.click()
document.body.removeChild(eleLink)
}
const title = document.title
const { protocol, href, hostname } = location
const content = `[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=${href}
IconFile=${protocol}//${hostname}/favicon.ico
IconIndex=1`
移动端 JavaScript
应该没有提供这个能力,需要在桌面生成快捷方式(原子组件),应该是属于 APP
的能力,而 JavaScript
(非 node
) 只是基于浏览器运行的,没有那么高的权限来操作系统
谷歌了之后发现 PWA
也有这个能力,是基于 A2HS (opens new window) 实现的能力(PC
端也可以下载,但展示形式有点不太一样)
# 2022 年 4 月 3 日
# unknown 类型
TypeScript 3.0
引入了一个顶级的 unknown
类型。 对照于 any
,unknown
是类型安全的。 任何值都可以赋给 unknown
,但是当没有类型断言或基于控制流的类型细化时 unknown
不可以赋值给其它类型,除了它自己和 any
外。 同样地,在 unknown
没有被断言或细化到一个确切类型之前,是不允许在其上进行任何操作的。
const getDogName = () => {
let x: unknown;
return x;
};
const dogName = getDogName();
console.log((dogName as string).toLowerCase());
参考文档地址:https://www.tslang.cn/docs/release-notes/typescript-3.0.html (opens new window)
# 2022 年 4 月 4 日
# js 判断 360 系浏览器
遇到过的都说苦,这流氓 360 害人不浅
以下代码为网上参考代码,来源:https://juejin.cn/post/6844903504968957965 (opens new window)
function checkIeFor360() {
return (
(navigator.msPointerEnabled == undefined ? true : navigator.msPointerEnabled) &&
(navigator.msDoNotTrack == 1 || window.doNotTrack == 1) &&
((Number(window.screenX) ? window.screenLeft - window.screenX != 8 : false) ||
((navigator.userAgent.indexOf("MSIE 7.0") != -1 ||
navigator.userAgent.indexOf("MSIE 8.0") != -1) &&
console.count == undefined))
)
}
// 检测极速内核下的360浏览器
function checkChromeFor360() {
var uas = navigator.userAgent.split(" "),
result = false
// 排除ua自带标志的双核浏览器, 余下chrome,chromium及360浏览器
if (uas[uas.length - 1].indexOf("Safari") == -1) {
return result
}
for (var key in navigator.plugins) {
// np-mswmp.dll文件在chromium及chrome未查询到
if (navigator.plugins[key].filename == "np-mswmp.dll") {
return !result
}
}
return result
}
if (navigator.userAgent.indexOf("Safari") != -1) {
document.writeln(checkChromeFor360())
} else {
document.writeln(checkIeFor360())
}
# 2022 年 4 月 5 日
# 自动化生成骨架屏思考
参考地址:https://github.com/Jocs/jocs.github.io/issues/22 (opens new window)
# 2022 年 4 月 6 日
# vuex 阅后感 -- 注入
vuex
也是一种 vue plugin
,通过暴露 install
方法,再由 Vue
全局引入
从 3.x
版本的代码上看,还存在一些兼容代码,当 vue
版本在 2.0
以下时是直接挂载到 vue
原型上,而 2.x
和 3.x
则是通过 mixin
的方式注入到每一个实例的初始化(beforeCreate
)钩子中
if (version >= 2) {
Vue.mixin({ beforeCreate: vuexInit })
} else {
const _init = Vue.prototype._init
Vue.prototype._init = function(options = {}) {
options.init = options.init ? [vuexInit].concat(options.init) : vuexInit
_init.call(this, options)
}
}
但从最新的代码(4.x
)来看,好像已经摒弃了兼容代码,直接使用全局注入的方式,将 store
注入到每一个实例
install (app, injectKey) {
app.provide(injectKey || storeKey, this)
app.config.globalProperties.$store = this
const useDevtools = this._devtools !== undefined
? this._devtools
: __DEV__ || __VUE_PROD_DEVTOOLS__
if (useDevtools) {
addDevtools(app, this)
}
}