vue2的数据双向绑定

  1. 首先,当创建Vue实例时,传入的data选项会被转换为响应式对象。每个属性都被转换为"getter/setter",并被添加到Vue的响应式系统中。
var vm = new Vue({
  data: {
    message: 'Hello Vue!'
  }
});
  1. 在模板中,将message属性与输入框进行双向绑定,使用v-model指令。
<input type="text" v-model="message">
<p>{{ message }}</p>

这里,v-model="message"告诉Vue将输入框的值与message属性进行双向绑定。

  1. 当用户在输入框中输入内容时,触发了输入事件。Vue会捕获这个事件,并自动更新message属性。

  2. 通过实现"getter/setter",Vue能够在message属性被读取或修改时进行依赖追踪。

// 转化后的data对象
{
  message: 'Hello Vue!',
  // 生成的getter/setter
  get message() {
    // 依赖追踪:如果有相关的视图依赖该属性,则将其添加到依赖列表中
    /* ... */
    return this._data.message;
  },
  set message(value) {
    // 响应变化:在属性被修改时,触发视图更新
    /* ... */
    this._data.message = value;
  }
}
  1. message属性被更新时,Vue的响应式系统会通知相关的视图进行更新。

在上述代码中,当用户在输入框中输入内容时,message属性会自动更新,并且对应的{{ message }}表达式也会实时更新显示最新的值。

这就是Vue.js的数据双向绑定原理:通过响应式系统追踪数据变化,并利用指令建立数据与视图之间的关联,从而实现数据和视图的双向同步。

Vue的双向数据绑定是通过数据劫持和发布-订阅模式来实现的。

具体来说,当Vue实例创建时,它会遍历所有的属性,并使用Object.defineProperty()方法将这些属性转换成getter/setter。这样,当数据发生变化时,Vue能够检测到变化并通知所有相关的组件。

在一个双向绑定的场景中,当用户修改视图中的数据时,这些修改会触发Vue的setter方法,setter方法会通知所有相关的组件,然后更新视图。反过来,如果数据在Vue实例中发生了变化,getter方法会被调用,这会触发更新视图的操作。

这种数据劫持的方式可以实现响应式的数据绑定,因为Vue能够监测数据的变化并立即更新相关的组件。同时,Vue还使用发布-订阅模式来管理组件之间的通信,确保所有组件都能接收到更新的通知并及时响应变化。
 

Vue 在创建实例时会调用 Observer 方法来遍历 data 中的数据并进行数据劫持。以下是一个简单的示例代码:

function Observer(data) {
  this.data = data;
  this.walk(data);
}
 
Observer.prototype = {
  walk: function(data) {
    var self = this;
    Object.keys(data).forEach(function(key) {
      self.defineReactive(data, key, data[key]);
    });
  },
  defineReactive: function(data, key, val) {
    var dep = new Dep();
    Object.defineProperty(data, key, {
      enumerable: true,
      configurable: true,
      get: function() {
        if (Dep.target) {
          dep.addSub(Dep.target);
        }
        return val;
      },
      set: function(newVal) {
        if (val === newVal) {
          return;
        }
        val = newVal;
        dep.notify();
      }
    });
  }
};
 
function observe(data) {
  if (!data || typeof data !== 'object') {
    return;
  }
  return new Observer(data);
}
 
function Dep() {
  this.subs = [];
}
 
Dep.prototype = {
  addSub: function(sub) {
    this.subs.push(sub);
  },
  notify: function() {
    this.subs.forEach(function(sub) {
      sub.update();
    });
  }
};
 
Dep.target = null;

上面的代码中,Observer 方法遍历 data 中的所有属性并为每个属性添加了 getter setter 方法,这样当这个属性被读取或被赋值时,就能触发 getter setter 方法中的相关逻辑。这里使用了 Object.defineProperty 方法来实现数据劫持。

defineReactive 方法中,我们使用了一个数组 subs 来保存所有订阅该属性的 watcher 对象,当属性值变化时,set 方法会遍历 subs 数组并调用每个 watcher 对象的 update 方法,从而更新视图。

同时,我们还定义了一个 Dep 类来管理 watcher 对象,并实现了一个全局变量 Dep.target 用来临时存储当前的 watcher 对象。在 get 方法中,我们判断 Dep.target 是否存在,如果存在则将当前的 watcher 对象添加到 subs 数组中,从而实现了订阅者模式。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值