vue中watcher数据双向绑定原理

发布时间:2021-08-23 10:43:22 作者:chen
来源:亿速云 阅读:182
# Vue中Watcher数据双向绑定原理

## 一、前言

Vue.js作为一款渐进式前端框架,其核心特性之一就是**响应式数据系统**。而实现这一特性的关键机制正是`Watcher`与数据双向绑定系统。本文将深入剖析Vue 2.x中Watcher的工作原理及其在数据双向绑定中的实现机制。

## 二、响应式系统基础

### 2.1 数据劫持(Data Hijacking)

Vue通过`Object.defineProperty`实现数据劫持:

```javascript
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      console.log(`读取属性 ${key}`);
      return val;
    },
    set: function reactiveSetter(newVal) {
      console.log(`设置属性 ${key}`);
      val = newVal;
    }
  });
}

2.2 依赖收集与派发更新

Vue的响应式系统基于发布-订阅模式: - Dep(Dependency):作为依赖管理器 - Watcher:作为订阅者

三、Watcher的核心实现

3.1 Watcher类定义

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm;
    this.getter = parsePath(expOrFn);
    this.cb = cb;
    this.value = this.get();
  }

  get() {
    Dep.target = this; // 设置当前Watcher
    const value = this.getter.call(this.vm, this.vm);
    Dep.target = null; // 收集完成后清除
    return value;
  }

  update() {
    const oldValue = this.value;
    this.value = this.get();
    this.cb.call(this.vm, this.value, oldValue);
  }
}

3.2 Dep类的实现

class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

四、完整的响应式流程

4.1 数据劫持升级版

function defineReactive(obj, key, val) {
  const dep = new Dep();
  
  Object.defineProperty(obj, key, {
    get: function() {
      if (Dep.target) {
        dep.addSub(Dep.target); // 收集依赖
      }
      return val;
    },
    set: function(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // 通知更新
    }
  });
}

4.2 流程图示

  +-------------------+       +-----------------+
  |   Data Property   | <---> |     Getter      |
  +-------------------+       +--------+--------+
         ^                             |
         |                             v
  +------+--------+            +-------+-------+
  |     Setter     |            |     Dep      |
  +------+--------+            +-------+-------+
         ^                             |
         |                             v
  +------+--------+            +-------+-------+
  |  Value Change |            |    Watcher    |
  +---------------+            +---------------+

五、双向绑定实现原理

5.1 v-model的实现

// 指令解析器
function model(node, vm, exp) {
  node.value = vm[exp]; // 初始化
  
  new Watcher(vm, exp, function(value) {
    node.value = value; // 数据变化更新视图
  });
  
  node.addEventListener('input', function(e) {
    vm[exp] = e.target.value; // 视图变化更新数据
  });
}

5.2 完整示例

<div id="app">
  <input v-model="message">
  <p>{{ message }}</p>
</div>

<script>
class Vue {
  constructor(options) {
    this.$data = options.data;
    observe(this.$data);
    new Watcher(this, 'message', () => {
      console.log('Message changed!');
    });
    compile(options.el, this);
  }
}
</script>

六、性能优化策略

6.1 异步更新队列

// 简化版nextTick实现
const callbacks = [];
let pending = false;

function nextTick(cb) {
  callbacks.push(cb);
  if (!pending) {
    pending = true;
    setTimeout(flushCallbacks, 0);
  }
}

function flushCallbacks() {
  pending = false;
  const copies = callbacks.slice(0);
  callbacks.length = 0;
  copies.forEach(cb => cb());
}

6.2 计算属性缓存

class ComputedWatcher extends Watcher {
  constructor(vm, getter, cb) {
    super(vm, getter, cb);
    this.dirty = true;
  }
  
  evaluate() {
    if (this.dirty) {
      this.value = this.get();
      this.dirty = false;
    }
    return this.value;
  }
  
  depend() {
    // 特殊的依赖收集逻辑
  }
}

七、Vue 3的改进

7.1 Proxy的优势

const observed = new Proxy(data, {
  get(target, key) {
    track(target, key); // 依赖收集
    return Reflect.get(target, key);
  },
  set(target, key, value) {
    const result = Reflect.set(target, key, value);
    trigger(target, key); // 触发更新
    return result;
  }
});

7.2 性能对比

特性 Vue 2 (defineProperty) Vue 3 (Proxy)
检测数组变化 需要hack处理 原生支持
新增属性响应 需要Vue.set 自动支持
性能 相对较慢 更快

八、总结

Vue的Watcher机制通过: 1. 数据劫持实现属性监听 2. 依赖收集建立数据与视图的关联 3. 发布-订阅模式实现高效更新

这种设计使得开发者可以专注于业务逻辑,而无需手动处理DOM更新,极大提高了开发效率。


延伸思考
如何结合Virtual DOM的diff算法与响应式系统,实现更高效的视图更新?
(字数统计:约3200字) “`

这篇文章从基本原理到具体实现,详细解析了Vue中Watcher的工作机制,包含: 1. 核心代码实现 2. 流程图解 3. 性能优化策略 4. Vue 3的改进对比 5. 完整的双向绑定示例

可根据需要进一步扩展具体章节内容或添加更多代码示例。

推荐阅读:
  1. vue的双向绑定原理及实现
  2. vue数据双向绑定原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue

上一篇:windows服务器怎么安装apache和php的环境

下一篇:在pytorch中如何对非叶节点的变量进行梯度计算

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》