Skip to content

埋点SDK

pv(page viwe)

同一用户对同一页面的访问次数

uv

独立用户访问次数,根据IP区分访客数

收集用户的隐私信息,优化性能体验,进行A/B业务决策

vite与webpack区别

  • webpack npm run dev 先打包一次 webpack 入口文件 js
  • vite npm run dev no bundle模式 启动不需要打包 入口文件是html 原生esm
  • vite esbuild开发模式 rollDown rust版本的 速度非常快

type="moudle"

  1. 模块化 可以使用import export
  2. 静态解析
  3. 异步加载
  4. 顶级await 作用域隔离

nevigator.sendBeacon

navigator.sendBeacon() 方法可用于通过 HTTP POST 将少量数据 异步 传输到 Web 服务器。

url

url 参数表明 data 将要被发送到的网络地址。

data 可选

data 参数是将要发送的 ArrayBuffer、ArrayBufferView、Blob、DOMString、FormData 或 URLSearchParams 类型的数据。
js
document.addEventListener("visibilitychange", function logData() {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/log", analyticsData);
  }
});
  1. 关闭页面时也能发送请求,相较于ajax,fetch,xhr等方法,sendBeacon不会阻塞页面的卸载,也不会在页面关闭时停止发送
  2. 但是不支持跨域 不支持json

nevigator.userAgent

  1. userAgent 是一个只读的属性,返回一个字符串,包含了用户代理头的值。
  2. navigator.userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。

手写vite plugin

js
import type { Plugin } from "vite"
const plugin = ():Plugin =>{
    return {
        name:'vite-plugin-tracker',
        transform(code,id){
            // console.log(code,id)
        }
    }
}

API Element.getBoundingClientRect()

Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。

getBoundingClientRect()

返回值是一个 DOMRect 对象,是包含整个元素的最小矩形(包括 padding 和 border-width)。该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

getBoundingClientRect

API getAttribute()

getAttribute() 返回元素上一个指定的属性值。如果指定的属性不存在,则返回 null 或 "" (空字符串)

API MutationObserver

MutationObserver 接口提供了监视对DOM树所做更改的能力。

js
// 选择需要观察变动的节点
const targetNode = document.getElementById("some-id");

// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };

// 当观察到变动时执行的回调函数
const callback = function (mutationsList, observer) {
  // Use traditional 'for loops' for IE 11
  for (let mutation of mutationsList) {
    if (mutation.type === "childList") {
      console.log("A child node has been added or removed.");
    } else if (mutation.type === "attributes") {
      console.log("The " + mutation.attributeName + " attribute was modified.");
    }
  }
};

// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);

// 以上述配置开始观察目标节点
observer.observe(targetNode, config);

// 之后,可停止观察
observer.disconnect();

EventTarget.addEventListener()

EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。

error 事件在资源加载失败,如 无法加载时触发。

  • e.lineno 行数
  • e.colno 列数
  • e.filename 文件名
  • e.message 错误信息

Vue 路由模式 history和hash

hash

  • hash模式下,url中的hash值是不会被包含在HTTP请求中的,所以改变hash不会重新加载页面
  • hash模式下,hash值改变会触发hashchange事件
  • hash模式下,hash值改变会在浏览器的访问历史中增加一个记录,点击后退按钮会导航到前一个记录
js
    window.addEventListener('hashchange',function(e){
        send({
            type:'pv-hash',
            data:{
                oldur:e.oldURL,
                newurl:e.newURL
            },
            text:'pv-hash'
        })
        
    })

history

  • popstate 事件在使用 history.pushState() 或 history.replaceState() 方法时,通过浏览器的前进或后退按钮触发。(每当激活同一文档中不同的历史记录条目时,popstate 事件就会在对应的 window 对象上触发。
  • pushstate不支持直接监听 需要重写

pushstate

  1. 导航到新页面:当用户点击一个链接或按钮时,你可以使用 pushState 方法来更新 URL,并加载新页面的内容,而无需重新加载整个页面。
  2. 动态加载内容:在单页应用中,当你通过 AJAX 请求加载新内容时,可以使用 pushState 方法来更新 URL,以便用户可以通过浏览器的前进和后退按钮导航。
  3. 表单提交:在处理表单提交时,可以使用 pushState 方法来更新 URL,而不重新加载页面。
js
    //手写pushState
    const pushstate = history.pushState

    window.history.pushState = function(state:any,title:string,url?:string | null){
        const res = pushstate.call(this,arguments)
        const e = new Event('pushState')
        window.dispatchEvent(e)
        return res
    }

    window.addEventListener('pushState',function(e){
        send({
            type:'pv-pushState',
            data:{
                href:location.href
                },
            text:'pv-pushState'
        })
        
    })

ajax fetch 监听

需要重写XMLHttpRequest.prototype.open/send/fetch方法

js
export default function request(send:send){
    //重写ajax
    const OriginOpen = XMLHttpRequest.prototype.open
    const OriginSend = XMLHttpRequest.prototype.send
    
    XMLHttpRequest.prototype.open = function(method:string, url:string | URL, async:boolean = true, user?:string | null, password?:string | null){
        send({
            type:'ajax',
            data:{
                method,
                url,
                async,
                user,
                password
            },
            text:'ajax'
        })
        OriginOpen.call(this,method,url,async,user,password)
    }
    XMLHttpRequest.prototype.send = function(data:any){
        send({
            type:'ajax',
            data,
            text:'ajax'
        })


        OriginSend.call(this,data)
    }

    const OrginFetch = window.fetch
    window.fetch = function(...args:any[]): Promise<Response> {
        send({
            type:'fetch',
            data:args,
            text:'fetch'
        })
        return OrginFetch.apply(this, args)
    }
}