IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue数据双向绑定原理 ( Vue.version = 2.6.14 ) -> 正文阅读

[JavaScript知识库]Vue数据双向绑定原理 ( Vue.version = 2.6.14 )

Vue数据双向绑定原理 ( Vue.version = 2.6.14 )

分析主要代码

1. 监测Object的变化

vue.commone.dev.js文件中,Vue在defineReactive$$1方法中监听对象的属性变化。

/**
 * defineReactive$$1
 */
function defineReactive$$1 (
  obj,
  key,
  val,监测
  customSetter,
  shallow
) {

  // 创建Dep实例
  const dep = new Dep();

  // 获取属性默认的 getter/setter ,防止重新定义getter/setter 的时候覆盖默认行为
  const descriptor = Object.getOwnPropertyDescriptor(obj, key);
  const getter = descriptor && descriptor.get;
  const setter = descriptor && descriptor.set;

  if ((!getter || setter) && arguments.length === 2) {
    val = obj[key];
  }

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function() {
      const value = getter ? getter.call(obj) : val;
      if (Dep.target) {

        /**
         * 1. 调用Dep.prototype.depend
         * 2. 在Dep.prototype.depend中调用Watcher.prototype.addDep
         * 3. Watcher.prototype.addDep中将Dep实例保存到Watcher实例的newDepIds、newDeps属性上,再将Watcher实例保存到Dep实例的subs属性上
         */
        dep.depend();
      }
      return value;
    },
    set: function(newVal) {
      const value = getter ? getter.call(obj) : val;

      // 设置新的值
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }

      /**
       * 1. 调用Dep.prototype.notify
       * 2. 在Dep.prototype.notify中遍历Dep实例上的subs属性 ( getter中保存的Watcher实例 )
       * 3. 调用Watcher.prototype.update更新视图 ( 具体update中做了什么,下次单独分析 )
       */
      dep.notify(); 
    }
  })
}

整体流程:

① 通过observer,使用Object.definePropertydata的获取、变化能够被监测

② 获取data时,触发getter, 将依赖添加到watcher中,将wacher添加到依赖subs ( 订阅? )

③ 更新data时,触发setter,通知依赖遍历subs,并调用watcherupdate方法更新视图 ( 其实最终调用的是Vue实例_render方法 )

疑问:

watcher是在何时创建的?

initComputed阶段创建watcher,并且watcher的vm属性指向Vue实例,将watcher保存到Vue实例的_watchers

不足:

  • 向对象中添加或删除属性时,无法监测到变化
  • 无法监测数组的变化
2. 监测Array的变化

定义拦截器,在调用修改数组的方法时,触发拦截器。

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);

// 能够改变数组自身的7个方法
const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
];

// 遍历methodsToPatch并修改arrayMethods上对应名称的方法
methodsToPatch.forEach(method => {
  Object.defineProperty(
    arrayMethods,
    method,
    {
      value: function() {

        /**
         * clone参数
         */
        const args = [];
        let len = arguments.length;
        while (len--) {
          args[len] = arguments[len];
        }

        // 调用原生的方法
        const result = arrayProto[method].apply(this, args);

        /**
         * 调用 push/unshift/splice时若添加/更新 了新元素
         * 则调用observe观察该元素
         */
        const ob = this.__ob__;
        let inserted;
        switch (method) {
          case 'push':
          case 'unshift':
            inserted = args;
            break;
          case 'splice':
            inserted = args.slice(2);
            break;
          default:
            break;
        }
        if (inserted) {
          ob.observeArray(inserted);
        }

        // 通知依赖更新
        ob.dep.notify();

        return result;
      }
    }
  )
})

整体流程:

① 给Array.prototype上能改变数组本身的方法添加拦截器

② 在Observer的构造器中Array实例的__proto__指向arrayMethods

③ 调用这些方法时,通知依赖更新

不足:

  • 通过索引修改数组时,无法监测到数组的变化
3. Vue对以上不足的解决方案

增加了两个全局API:Vue.setVue.delete

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:20:01  更:2022-03-08 22:22:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:45:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码