当前位置: 首页 > news >正文

建设网站过水河源新闻最新消息

建设网站过水,河源新闻最新消息,我要建网站,做网站竞品分析前言 Vue响应式原理由以下三个部分组成: 数据劫持:Vue通过Object.defineProperty()方法对data中的每个属性进行拦截,当属性值发生变化时,会触发setter方法,通知依赖更新。发布-订阅模式:Vue使用发布-订阅…

前言

Vue响应式原理由以下三个部分组成:

  1. 数据劫持:Vue通过Object.defineProperty()方法对data中的每个属性进行拦截,当属性值发生变化时,会触发setter方法,通知依赖更新。
  2. 发布-订阅模式:Vue使用发布-订阅模式来实现数据的响应式更新。当数据发生变化时,会通知依赖进行更新。
  3. 依赖收集:Vue在渲染组件时,会对模板中使用到的数据进行依赖收集,将组件中使用到的数据和对应的Watcher对象建立关联,当数据发生变化时,会通知相关的Watcher对象进行更新。

实现流程

手写Vue响应式原理可以分为以下几个步骤:

  1. 实现Observer类:通过Object.defineProperty()方法对data中的每个属性进行拦截,当属性值发生变化时,会触发setter方法,通知依赖更新。
  2. 实现Dep类:用于管理Watcher对象,包括添加和删除Watcher对象,以及通知Watcher对象进行更新。
  3. 实现Watcher类:用于建立视图与数据之间的联系,当数据发生变化时,会通知Watcher对象进行更新。
  4. 实现Compile类:用于解析模板指令,将指令对应的数据渲染到视图中,并建立视图与数据的联系。
  5. 实现Vue类:将Observer、Watcher、Compile类进行整合,实现Vue的响应式更新机制。

总的来说,手写Vue响应式原理主要由Observer、Dep、Watcher、Compile、Vue这几个组成部分构成。其中Observer用于拦截数据变化,Dep用于管理Watcher对象,Watcher用于建立视图与数据之间的联系,Compile用于解析模板指令,Vue将这些类进行整合,实现了Vue的响应式更新机制。

创建一个Dep类

我们使用递归来遍历数据对象中的所有属性,对每个属性使用Object.defineProperty()方法进行定义。在defineReactive()方法中,我们还创建了一个Dep类,Dep类用于管理所有订阅者(Watcher)和通知它们更新

class Dep {constructor() {this.subs = []; // 存储依赖的数组}// 添加依赖addSub(sub) {if (sub && sub.update) {this.subs.push(sub);}}// 通知依赖更新notify() {this.subs.forEach(sub => {sub.update();});}
}Dep.target = null; // 静态属性 target,用于保存当前的 Watcher 对象

上面的代码定义了一个名为Dep的类,它有以下几个方法:

  1. constructor():构造函数,初始化订阅者数组subs为空数组。
  2. addSub(sub):添加订阅者的方法,将传入的订阅者对象sub添加到subs数组中。
  3. notify():通知所有订阅者更新的方法,遍历subs数组,对每个订阅者调用其update()方法。
  4. target:定义一个全局变量target,用于存储当前的订阅者对象。

在Vue中,每个响应式数据(如data中的属性)都会对应一个Dep对象。当这个属性被读取时,会将当前的订阅者对象存储到Dep.target中,然后在属性的getter方法中,将Dep.target添加到当前属性的Dep对象的订阅者数组中;当属性的值被修改时,会调用该属性的Dep对象的notify()方法,通知所有订阅者更新。

创建一个Watcher类

接下来,我们需要创建一个Watcher类,它的主要作用是在数据发生变化时,触发视图的更新操作。在Watcher类中,我们首先需要保存更新视图所需的回调函数,并将Watcher实例添加到数据的订阅列表中。在数据发生变化时,我们遍历订阅列表,并依次调用回调函数来更新视图。

// 创建一个Watcher类,用于管理依赖与视图的更新
class Watcher {constructor(vm, key, cb) { this.vm = vm; this.key = key; this.cb = cb;// 将当前Watcher实例指定为Dep.target Dep.target = this; // 获取数据的值,触发数据的get方法,从而将当前Watcher实例添加到Dep中 this.oldValue = vm[key]; Dep.target = null;}// 更新视图 
update() {const newValue = this.vm[this.key]; if (this.oldValue === newValue) { return; } this.cb(newValue); this.oldValue = newValue; }
}

创建一个Observer类

Observer 类:该类用于对数据进行监听和响应式处理,主要实现了 walk 和 defineReactive 两个方法。walk 方法遍历对象中所有属性,对每个属性调用 defineReactive 方法进行响应式处理;defineReactive 方法利用 Object.defineProperty 给每个属性添加 getter 和 setter,当属性被访问或修改时,会触发相应的依赖更新。

class Observer {constructor(data) {this.walk(data);}// 对数据对象进行递归遍历,为每个属性添加getter和setterwalk(data) {Object.keys(data).forEach(key => {this.defineReactive(data, key, data[key]);});}defineReactive(obj, key, val) {const dep = new Dep(); // 创建一个依赖收集器Object.defineProperty(obj, key, {enumerable: true, // 可枚举configurable: true, // 可配置get() {// 添加依赖if (Dep.target) {dep.depend();}return val;},set(newVal) {if (val === newVal) {return;}val = newVal;// 触发依赖更新dep.notify();}});}
}

创建一个Compile类

Compile类的代码。在Compile类中,我们首先需要遍历模板中的节点,并根据节点的类型来处理它们。对于普通节点,我们将对它们的文本内容进行处理,对于包含指令的节点,我们将创建Watcher实例,并将它们添加到订阅列表中。

class Compile {constructor(el, vm) {this.el = document.querySelector(el); // 获取根节点this.vm = vm; // 保存 Vue 实例this.compile(this.el); // 编译模板}compile(el) {const childNodes = el.childNodes; // 获取根节点的子节点列表Array.from(childNodes).forEach(node => {if (node.nodeType === 1) { // 元素节点this.compileElement(node);} else if (this.isInterpolation(node)) { // 文本节点且包含插值语法this.compileText(node);}// 递归编译子节点if (node.childNodes && node.childNodes.length > 0) {this.compile(node);}});}compileElement(node) {const attrs = node.attributes; // 获取元素节点的属性列表Array.from(attrs).forEach(attr => {const attrName = attr.name;const exp = attr.value;if (attrName.startsWith("v-")) { // 匹配指令const dir = attrName.substring(2); // 获取指令名称this[dir] && this[dir](node, exp); // 调用对应的指令函数}});}compileText(node) {const exp = node.textContent; // 获取插值语法中的表达式node.textContent = this.getVMValue(exp); // 将插值语法替换为表达式的值}isInterpolation(node) {return node.nodeType === 3 && /\{\{(.*)\}\}/.test(node.textContent); // 文本节点且包含插值语法}getVMValue(exp) {let value = this.vm;exp.split(".").forEach(key => {value = value[key];});return value;}// v-model 指令model(node, exp) {this.bind(node, exp, "model");node.addEventListener("input", e => {const newValue = e.target.value;this.setVMValue(exp, newValue);});}// v-bind 指令bind(node, exp, dir) {const updaterFn = this[dir + "Updater"];updaterFn && updaterFn(node, this.getVMValue(exp));new Watcher(this.vm, exp, value => {updaterFn && updaterFn(node, value);});}// model 指令更新视图modelUpdater(node, value) {node.value = value;}// v-text 指令text(node, exp) {this.bind(node, exp, "text");}// text 指令更新视图textUpdater(node, value) {node.textContent = value;}setVMValue(exp, value) {let vm = this.vm;const keys = exp.split(".");keys.forEach((key, index) => {if (index < keys.length - 1) {vm = vm[key];} else {vm[key] = value;}});}
}

Compile 类的实例化需要传入两个参数:el 和 vm。其中,el 是根节点的选择器,vm 是 Vue 实例。

Compile 类主要实现了以下功能:

  1. 遍历根节点及其子节点,对每个元素节点和包含插值语法的文本节点进行编译。
  2. 对于元素节点,遍历其属性列表,匹配指令并调用对应的指令函数进行处理。
  3. 对于包含插值语法的文本节点,替换为表达式的值。
  4. 实现了 v-model、v-bind 和 v-text 指令的处理。
  5. 实现了响应式数据的处理,通过 Watcher 对数据进行监听,数据发生变化时自动更新视图。

创建一个完整的Vue实例

创建一个Vue类,将Observer、Watcher和Compile类组合在一起,以创建一个完整的Vue实例。

class Vue {constructor(options) {this.$options = options;this.$data = options.data;this.$el = typeof options.el === 'string' ? document.querySelector(options.el) : options.el;// 将 Vue 实例的属性代理到 $data 对象上this._proxyData(this.$data);// 创建Observer实例,监听数据变化new Observer(this.$data);// 创建Compile实例,解析模板指令new Compile(this.$el, this);}//使用_proxyData()方法来将数据代理到Vue实例中,就可以在Vue实例中通过this.key的方式来访问数据_proxyData(data) {Object.keys(data).forEach((key) => {Object.defineProperty(this, key, {enumerable: true,configurable: true,get() {return data[key];},set(newValue) {if (newValue === data[key]) {return;}data[key] = newValue;},});});}
}

到此为止,我们已经完成了手写代码来模拟Vue2.0的响应式数据实现的过程。我们可以通过这个过程来深入理解Vue2.0的响应式数据原理,从而更好地应用Vue2.0开发应用程序。

后续会继续更新vue2.0其他源码系列,包括目前在学习vue3.0源码也会后续更新出来,喜欢的点点关注。

http://www.hrbkazy.com/news/15518.html

相关文章:

  • 河南住房和城乡建设网站聚合广告联盟
  • 快速达建网站自己怎么制作网页
  • 如何建立网站赚钱企业培训方案制定
  • 外贸网站怎么做seo优化百度广告优化
  • 制作网站商app平台搭建需要多少钱
  • 广州在线图文网络科技中心网站建设加强网络暴力治理
  • 做外围网站代理合法不湖北搜索引擎优化
  • 网站建设的图片怎么加水印沈阳百度推广哪家好
  • 网站管理制度建设的必要性小红书新媒体营销案例分析
  • 免费做店招的网站小说风云榜
  • 无忧网站推文关键词生成器
  • 怎么在新建网站上做分享代码百度seo 站长工具
  • 网站做游戏吗网站优化公司怎么选
  • php网站怎么做自适应淘宝怎么优化关键词步骤
  • 滴道网站建设游戏优化大师官网
  • 海口网站建设优化网络销售怎么做才能做好
  • 网站是否有管理员权限快速网站推广公司
  • 六安市城乡建设委员会网站淄博seo培训
  • 青秀网站建设常用的seo工具
  • 吕梁网站制作公司网站建设多少钱
  • 青海省高速公路建设管理局网站优化大师win10能用吗
  • 哈尔滨cms建站珠海百度关键词优化
  • 贵州省住房和城乡建设局网站首页如何做好线上推广和引流
  • 网站首页菜单栏表怎么做产品推广渠道有哪些方式
  • 培训网站设计师搜索引擎推广试题
  • 做网站需要接口么哪里有培训班
  • 国内做电商网站优化网站内容
  • 企业网站建设招标书媒体宣传推广方案
  • 轴承推广做哪个网站新站如何让百度快速收录
  • 手机在线做ppt模板下载网站网络营销推广的方式有哪些