• 作者:老汪软件技巧
  • 发表时间:2024-10-14 21:02
  • 浏览量:

Vue 2 双向绑定详解

Vue 2 使用 Object.defineProperty 来实现响应式数据。当一个对象成为响应式后,它的属性就会被转换成 getter 和 setter,从而可以在属性被访问或修改时进行拦截。

数据劫持

在 Vue 2 中,当你创建一个新的 Vue 实例时,Vue 会使用一个名为 Observer 的类来遍历 data 对象的所有属性,并将它们转换为 getter 和 setter。例如:

Javascript
深色版本
function observe(value) {
  if (!value || typeof value !== 'object') {
    return;
  }
  new Observer(value);
}
var Observer = function Observer(value) {
  this.value = value;
  this.walk(value);
};
Observer.prototype.walk = function walk(obj) {
  var keys = Object.keys(obj);
  for (var i = 0; i < keys.length; i++) {
    defineReactive(obj, keys[i]);
  }
};
function defineReactive(obj, key, val) {
  var dep = new Dep();
  var childOb = !Vue.isPlainObject(val) ? null : observer(val);
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      if (Dep.target) {
        dep.addSub(Dep.target);
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val || (newVal !== newVal && val !== val)) {
        return;
      }
      val = newVal;
      dep.notify();
    }
  });
}

上面的代码展示了如何使用 Object.defineProperty 来创建 getter 和 setter。每当访问或设置属性时,都会触发相应的函数。如果访问时有活跃的依赖(即 Dep.target 存在),则将其添加到依赖列表中;如果设置时属性的值发生了变化,则通知所有依赖更新。

示例代码

Javascript
深色版本
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue 2!'
  },
  created() {
    // 模拟输入事件,改变message
    this.message = 'Changed!';
    console.log(this.$el.querySelector('p').textContent); // 输出 "Changed!"
  }
});

Html
深色版本
<div id="app">
  <input type="text" v-model="message">
  <p>{{ message }}p>
div>

双向绑定和vuex是否冲突__双向绑定原理vue

Vue 3 双向绑定详解

Vue 3 使用了 Proxy 来实现响应式数据。相比 Vue 2 的 Object.defineProperty,Proxy 提供了一种更简洁的方式来拦截对象的访问和修改。

响应式系统

在 Vue 3 中,响应式系统由 reactivity 包提供,其中 ref 和 reactive 是两个主要的工具函数。ref 创建一个响应式引用类型,而 reactive 则直接使一个对象变成响应式的。

Javascript
深色版本
import { ref, reactive } from 'vue';
const state = reactive({ count: 0 });
state.count++; // 触发依赖更新
// 或者使用 ref
const count = ref(0);
count.value++; // 触发依赖更新

示例代码

Javascript
深色版本
import { ref } from 'vue';
export default {
  setup() {
    const message = ref('Hello Vue 3!');
    
    // 模拟输入事件,改变message
    message.value = 'Changed!';
    console.log(message.value); // 输出 "Changed!"
    return {
      message
    };
  }
};

Html
深色版本
<template>
  <div id="app">
    <input type="text" v-model="message">
    <p>{{ message }}p>
  div>
template>

总结

Vue 2 使用 Object.defineProperty 来监听数据变化,而 Vue 3 则使用了 Proxy,这是一种更现代的方法,能够更自然地处理数据变化。两种方法的核心目标都是为了让数据变化能够自动反映到视图上,但 Vue 3 的实现更加简洁并且功能更加强大。