来一波原生的观察者模式 | MutationObserver

MutationObserver

Mutation Observer API 用来监视DOM变动。DOM的任何变动,比如节点的增删、属性的变动、文本内容的变化,这个API都可以得到通知。

首先这个API归属于微任务,也就是说是异步的,这样设计也是为了应付Dom变动频繁的特点,防止频繁变动占用js执行栈造成页面卡顿。比如说:如果不是异步当DOM变动触发观察者的回调函数执行,就会堵塞后续代码的执行;是异步的话,在响应时间内比如说插入1000个p元素,那么MutationObserver会把这些响应合并成一次。

MutationObserver有以下特点:
  1. 异步执行
  2. 把异步时间内的DOM变动记录封装成一个数组处理,可以以数组的长度判断页面加载何时Dom跳跃大。
  3. 它既可以观察DOM的所有类型变动,也可以指定只观察某一类类型的变动。
MutationObserver构造函数

早期的Firefox和Chrome版本中需要带有前缀。

var MutationObserver = window.MutationObserver || window.WebkitMutationObserver || window.MozMutationObserver;
复制代码

首先使用MutationObserver构造函数实例化一个MutationObserver对象,同时指定这个实例的回调函数。

const observer = new MutationObserver(()=>{})
复制代码

构造函数可以接受两个参数:

  • 第一个参数为变动记录数据。
  • 第二个参数为观察者实例。
const observer = new MutationObserver((mutations,observer) => {
    console.log(muatation,observer);
})
复制代码
MutationObserver实例

构造函数调用MutationObserver得到MutationObserver实例。实例有以下方法。

observe

observe方法用来监听Dom变化,接受两个参数:

  • 第一个参数是所要观察的Dom节点
  • 第二个对象是一个配置对象,指定所要观察的变动类型
observer.observe(document.documentElement,{
    
})
复制代码

Dom的变动类型一共有三种:

  • childList : 子节点变动(指新增、删除、修改)。
  • attributes :属性的变动
  • characterData : 节点内容或节点文本的变动。

当变动类型为true的时候为监听状态,默认为不监听。

需要注意的是:必须同时指定三种变动类型中的一种或者多种,否则会报错。

除了三种变动类型外,对象属性还可以设置其他值:

  • subtree : 布尔值,表示是否将观察者应用于该节点的后代所有节点。
  • attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。
  • characterDataOldValue:布尔值,表示观察characterData变动时,是否需要记录变动前的值。
  • attributeFilter:数组,表示需要观察的特定属性(比如说['class','src']);
observer.observe(document.documentElement,{
    childList : true,
    attributes : true,
    characterData : true,
    subtree : true,
    attributeOldValue: true,
    characterDataOldValue: true,
})
复制代码
taskRecoreds

taskRecoreds方法用于清楚变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。

const changes = observer.taskRecords();
console.log(changes);
复制代码
disconnect

disconnect方法用来停止观察。调用该方法后,DOM再发生变动,也不会触发观察者对象。

observer.disconnect();
复制代码
MutationRecord对象

DOM每次发生变化,就会生成一条变动记录(MutationRecord实例)。该实例包含了与变动相关的所有信息。MutationObserver处理的就是一个个MutationRecord实例组成的数组。

MutationRecord包含了Dom的有关信息,有以下属性:

  • type:观察变动的类型(attribute、characterData或者childList)
  • target : 发生变动的DOM节点
  • addedNodes :新增的DOM节点
  • removedNodes : 删除的DOM节点。
  • previousSibling : 前一个同级节点,如果没有则返回null。
  • nextSibling : 下一个同级的节点,如果没有则返回null。
  • attributeName:发生变动的属性名,如果设置了attributeFilter,则只返回attributeFilter中的属性值。
  • oldValue:这个属性只对attribute和characterData变动生效,如果发生childList变动,则返回null。

总结

MutationObserver是异步操作,属于微任务,在Vue源码中实现nextTick的调度机制使用到了这个。

Vue中主要起到一个实现异步操作的调度机制,并没有真正体现到监听Dom变化的特点。

我个人这个东西在监听Dom变化上还是有大作用的。我们在做性能监控的时候,通常会检测一些性能指标,例如:FP、FCP、FMP这些性能指标。FMP的标准定义不明确,通常是指Dom活动最大的时刻。所以说FMP比较难检测,通常采用body前后打mark的方式检测。使用这个API的话,可以检测哪个时间段Dom到文本中最多,也就可以说成活动最大。

最后

这是Can I Use上的MutationObserver API的支持度。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 将一个完整的Vue项目转换为原生HTML模式的方法: 1.先确保Vue项目的所有依赖项被正确安装 2.创建一个新的HTML页面并添加必要的插件和库,如Vue.js和Vue Router 3.将Vue项目的组件和路由信息导入到新的HTML页面中,并使用Vue.js的语法将它们添加到页面中 4.为每个组件创建相应的HTML元素和CSS样式,以确保其正常显示和功能 5.添加JS代码以调用Vue.js的实例和组件,以确保整个页面可以正确地响应和更新 6.进行必要的测试和调试,确保转换后的HTML页面的功能和性能与原始Vue项目相当或更好。 ### 回答2: 将一个完整的Vue项目转换成原生HTML模式可能需要一定的时间和努力,因为Vue项目是基于Vue框架开发的,而原生HTML则是使用HTML标签和属性的基本编码。这里将提供一些步骤来帮助您完成这个过程。 1.将Vue组件分解成HTML文件和CSS文件: 首先,将Vue项目中的所有组件分解成HTML文件和CSS文件。将组件标签替换为HTML标签并添加相应的属性。对于像v-for、v-if等Vue指令,可以使用JavaScript代码块来替换它们。 2.导入外部CSS文件 在Vue项目中,可以使用Vue的单文件组件(SFC)语法在同一文件中包含模板、CSS、JavaScript等内容。但在HTML模式下,必须将CSS文件提取到单独的文件中,然后使用<link>标签将其导入到HTML文件中。 3.使用jQuery或JavaScript 在Vue项目中,Vue框架自动管理DOM元素。但在HTML模式下,需要使用jQuery或JavaScript手动处理DOM元素。您可以使用这些库来操作DOM元素并与后端接口通信。 4.添加跨域支持 Vue项目中使用的Ajax或axios请求可能涉及到跨域问题。因此,在将Vue项目转换为HTML模式时,还需要添加跨域支持。可以使用Cors或JSONP来解决这个问题。 总结 将Vue项目转换成HTML模式需要手动处理组件、CSS、JavaScript和DOM元素,并添加跨域支持。这需要一定的时间和努力,但可以在一定程度上减少对Vue框架的依赖。在完成这个过程之后,您可以在不使用Vue框架时将应用程序部署到Web服务器上。 ### 回答3: Vue 是一个流行的 JavaScript 框架,通常用于开发大型的单页应用程序。但是有时候,我们可能需要将一个完整的 Vue 项目转换成原生 HTML 模式,例如在某些情况下不需要使用 Vue 时,或是需要将 Vue 项目嵌入到其他应用程序中。本文将提供一些方法和技巧来实现这个目标。 1. 前期准备 在进行 Vue 项目转换之前,需要先完成一些前期准备工作。首先需要确保项目中所有相关的依赖都已经安装完毕,可以执行以下命令来安装: ``` npm install ``` 然后,需要使用以下命令来编译 Vue 项目: ``` npm run build ``` 这将生成一个优化后的、可运行的 Vue 程序,以用于部署和生产环境中的使用。 2. 分离 Vue 组件 Vue 项目中的组件是单独构建的,需要将其首先分离出来。可以将每个组件转换成一个单独的 HTML 文件,然后将它们添加到你的 HTML 页面或其他应用程序中。 为了实现这一目标,首先需要在 Vue 项目中创建一个新的目录,来存放分离出的组件。例如: ``` mkdir components ``` 然后,需要找到 Vue 项目中的组件定义,它们通常位于 components 目录下。将每个组件的定义从 Vue 中提取出来,保存为一个独立的 HTML 文件。这样,就可以将每个组件单独使用,而不需要依赖整个 Vue 应用程序。 3. 移除 Vue.js 在完成组件分离后,需要将 Vue.js 本身从应用程序中移除掉。可以将需要使用的 Vue 组件直接插入到 HTML 页面中,或是通过 AJAX 从服务器获取。 为了移除 Vue.js,首先需要在 HTML 页面中删除引用: ``` <!-- 移除引用的 Vue.js --> <script src=”/resources/vue.js"></script> ``` 同时,需要在 Vue 项目中删除不必要的依赖和代码,确保整个应用程序不再依赖 Vue.js。 4. 替换 Vue 事件和指令 Vue 的事件和指令(例如 v-bind 和 v-on)是 Vue.js 模板语言的核心组成部分,需要将其替换为纯粹的 JavaScript 代码和 HTML 标签。 例如,假设有一个这样的 Vue 事件: ``` <button v-on:click="doSomething">Click me</button> ``` 需要将这个事件替换成原生JavaScript 代码: ``` <button onclick="doSomething()">Click me</button> ``` 同样的,Vue 指令也需要替换成原生的 HTML 标签和 JavaScript 代码。例如: ``` <div v-bind:class="{ 'red': isRed }"></div> ``` 需要替换成: ``` <div class="{red:isRed}"></div> ``` 5. 简化 Vue 过滤器和计算属性 Vue.js 允许定义过滤器和计算属性来处理数据。这些功能可以通过 JavaScript 来实现,因此需要将它们简化或删除。 比如,计算属性可以使用简单的 JavaScript 函数来实现。例如,下面的 Vue.js 代码: ``` computed: { total: function () { return this.items.reduce(function(a, b) { return a + b.price; }, 0); } } ``` 简化为以下的 JavaScript 代码: ``` function calculateTotal() { var items = […]; var sum = 0; for (var i = 0; i < items.length; i++) { sum += items[i].price; } return sum; } ``` 同样的,过滤器可以通过一些简单的 JavaScript 函数来实现,例如: ``` filter: { toLowerCase: function (value) { return value.toLowerCase(); } } ``` 需要替换成: ``` function toLowerCase(value) { return value.toLowerCase(); } ``` 6. 编写样式和 JavaScript 最终步骤是编写样式和 JavaScript,以实现应用程序的功能和外观。这可以通过编写纯粹的 HTML、CSS 和 JavaScript 代码来完成,然后将其插入到 Vue.js 项目中。 需要注意的是,Vue.js 项目中的 CSS 和 JavaScript 文件可能会包含 Vue.js 特定的代码,需要删除这些内容。同时,需要编写一些自定义的 JavaScript 代码来处理 Vue.js 项目中的数据和事件。 总结 将一个完整的 Vue.js 项目转换成原生 HTML 模式需要以下几个步骤: 1. 分离 Vue.js 组件 2. 移除 Vue.js 3. 替换 Vue.js 事件和指令 4. 简化 Vue.js 过滤器和计算属性 5. 编写样式和 JavaScript。 最终,你会得到一个轻量级的 HTML 应用程序,它仅使用原生的 HTML、CSS 和 JavaScript 编写而成,不再依赖 Vue.js。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值