【Vue】响应式与数据劫持

目录

响应式原理

Vue.js 的响应式原理是基于数据驱动的,它的核心是将数据和视图进行关联,并且在数据发生变化时更新视图。Vue.js 通过数据劫持技术实现了响应式原理。

所谓数据劫持,就是通过一些手段来劫持 JavaScript 对象的访问和修改,以便在数据发生变化时能够自动更新视图。

Vue.js 中的响应式原理流程如下:

1. Vue 组件中有一个 data 属性,它是一个对象。

2. Vue 在初始化组件时,会通过 Object.defineProperty() 方法将 data 中的所有属性都转化成 getter 和 setter。

3. 当访问或者修改这些属性时,会触发对应的 getter 和 setter 方法。

4. 在 setter 方法中,Vue 会通知相关的 Watcher(一个观察者对象)去更新视图。

5. 当组件中的 data 发生变化时,会触发对应属性的 setter 方法,然后通知相关的 Watcher 更新视图。

下面我们将详细介绍 Vue.js 中的数据劫持技术。

数据劫持

数据劫持是 Vue.js 实现响应式的核心技术之一,它主要通过 Object.defineProperty() 方法来实现。

下面是一个简单的示例,我们将使用 Object.defineProperty() 方法来实现一个响应式对象:

响应式实现

我们先来看一个简单的示例,下面是一个 Vue 组件的代码:

在这个代码中,我们定义了三个函数:defineReactive()、observe() 和 Vue()。

* defineReactive():这个函数用来给对象添加 getter 和 setter,实现数据劫持。

* observe():这个函数会递归遍历对象中的所有属性,将其转化为 getter 和 setter。

* Vue():这个函数用来初始化 Vue 组件,其中 options.data 属性就是我们要响应式的数据。

例子:

数据更新

数据劫持的目的是为了在数据发生变化时,能够自动更新视图。在 Vue.js 中,当数据发生变化时,会触发相应的 getter 和 setter 方法,然后通知相关的 Watcher 更新视图。


Vue.js 是一个渐进式的 JavaScript 框架,其中最重要的一个特性就是响应式(Reactivity)。Vue 借助数据劫持(Data Observation)技术实现了对数据的响应式更新,当数据发生变化时,它会自动重新渲染视图,这使得构建复杂的用户界面变得更加容易。在本文中,我们将介绍 Vue.js 中的响应式原理和数据劫持机制,让你了解 Vue.js 是如何通过监听数据变化来实现视图更新。

响应式原理

Vue.js 的响应式原理是基于数据驱动的,它的核心是将数据和视图进行关联,并且在数据发生变化时更新视图。Vue.js 通过数据劫持技术实现了响应式原理。

所谓数据劫持,就是通过一些手段来劫持 JavaScript 对象的访问和修改,以便在数据发生变化时能够自动更新视图。

Vue.js 中的响应式原理流程如下:

1. Vue 组件中有一个 data 属性,它是一个对象。
2. Vue 在初始化组件时,会通过 Object.defineProperty() 方法将 data 中的所有属性都转化成 getter 和 setter。
3. 当访问或者修改这些属性时,会触发对应的 getter 和 setter 方法。
4. 在 setter 方法中,Vue 会通知相关的 Watcher(一个观察者对象)去更新视图。
5. 当组件中的 data 发生变化时,会触发对应属性的 setter 方法,然后通知相关的 Watcher 更新视图。

下面我们将详细介绍 Vue.js 中的数据劫持技术。

数据劫持

数据劫持是 Vue.js 实现响应式的核心技术之一,它主要通过 Object.defineProperty() 方法来实现。

Object.defineProperty() 方法是 JavaScript 原生提供的 API,它可以用来定义对象上的属性。这个方法有三个参数: 

Object.defineProperty(obj, prop, descriptor)

* obj:要定义属性的对象。
* prop:要定义或修改的属性的名称。
* descriptor:要定义或修改的属性的描述符。

descriptor 是一个包含属性的特性的对象,它具有以下几个属性:

 * configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能够被删除,默认为 false。

* enumerable:当且仅当该属性的 enumerable 为 true 时,该属性才会出现在对象的枚举属性中,默认为 false。
* value:该属性对应的值,默认为 undefined。

* writable:当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变,默认为 false。
* get:表示该属性的 getter 函数,默认为 undefined。
 

* set:表示该属性的 setter 函数,默认为 undefined。

通过 Object.defineProperty() 方法,可以给对象的属性设置 getter 和 setter。这样一来,我们就可以在属性被访问或者修改时,触发对应的 getter 和 setter 方法,达到数据劫持的目的。 

 在 Vue.js 中,当初始化组件时,Vue.js 会对组件中所有的 data 属性使用 Object.defineProperty() 方法将其转化为 getter 和 setter。这样一来,当组件中的 data 属性被访问或者修改时,Vue.js 就能够捕获到这些操作,并在内部执行相应的逻辑。这就实现了 Vue.js 中的响应式机制。

下面是一个简单的示例,我们将使用 Object.defineProperty() 方法来实现一个响应式对象:
var obj = {};
 
Object.defineProperty(obj, "name", {
  get: function() {
    console.log("访问了属性 name");
    return this._name;
  },
  set: function(value) {
    console.log("修改了属性 name,新值为:" + value);
    this._name = value;
  }
});
 
obj.name = "Vue.js";
console.log(obj.name);

 在这个示例中,我们使用 Object.defineProperty() 方法定义了一个对象 obj 的属性 name。在 getter 和 setter 中,我们分别输出了访问和修改属性的操作,并打印出了属性的值。。当我们执行 obj.name = "Vue.js" 时,会触发 setter 方法,并输出修改操作的信息。当我们访问 obj.name 时,会触发 getter 方法,并输出访问操作的信息。

响应式实现

在了解了数据劫持的原理之后,我们来看看 Vue.js 是如何实现响应式的。

我们先来看一个简单的示例,下面是一个 Vue 组件的代码:
<div id="app">
  <p>{
   
   { message }}</p>
</div>
<script>
new Vue({
  el: "#app",
  data: {
    message: "Hello, Vue.js!"
  }
});
</script>

在这个组件中,我们使用了 Vue.js 的数据绑定语法 { { message }} 来显示 data 中的 message 属性。在初始化时,Vue.js 会将组件中的 data 属性转化为 getter 和 setter,代码如下:

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get: function() {
      console.log("访问了属性 " + key);
      return val;
    },
    set: function(newVal) {
      console.log("修改了属性 " + key + ",新值为:" + newVal);
      val = newVal;
    }
  });
}
 
function observe(obj) {
  if (!obj || typeof obj !== "object") {
    return;
  }
  Object.keys(obj).forEach(function(key) {
    defineReactive(obj, key, obj[key]);
  });
}
 
function Vue(options) {
  this._data = options.data;
  observe(this._data);
}
在这个代码中,我们定义了三个函数:defineReactive()、observe() 和 Vue()。
* defineReactive():这个函数用来给对象添加 getter 和 setter,实现数据劫持。
* observe():这个函数会递归遍历对象中的所有属性,将其转化为 getter 和 setter。

* Vue():这个函数用来初始化 Vue 组件,其中 options.data 属性就是我们要响应式的数据。

我们在 Vue() 函数中调用了 observe(),将 data 属性转化为 getter 和 setter。在efineReactive() 函数中,我们调用了 Object.defineProperty() 方法,将 data 中的每个属性都转化为 getter 和 setter。这样一来,当我们访问或者修改组件中的 data 属性时,就会触发相应的 getter 和 setter 方法,打印出访问或者修改属性的信息。

我们来运行一下这个示例,在控制台中可以查看到输出的信息:
访问了属性 message
Hello, Vue.js!
修改了属性 message,新值为:Hello, Vue.js!
访问了属性 message
Hello, Vue.js!
 

在这个示例中,我们成功地将组件中的 data 属性转化为了响应式的数据。当我们访问或者修改属性时,都会触发对应的 getter 和 setter 方法,并输出相应的信息。 

例子:

在 Vue 中,响应式系统是通过使用数据劫持(Data Observation)来实现的。Vue 使用了一种名为“响应式数据绑定”的技术,使得数据的变化能够自动响应到视图上,以及使视图的变化能够自动更新到数据上。

数据劫持是指 Vue 内部利用了 JavaScript 对象的 Object.defineProperty() 方法来劫持(或拦截)对象的属性的访问和修改过程。当你把一个普通的 JavaScript 对象传递给 Vue 实例作为 data 选项时,Vue 将会遍历这个对象的所有属性,并使用 Object.defineProperty() 把这些属性全部转化为 getter 和 setter。

通过这种方式,当数据被访问或修改时,Vue 就能够检测到,并触发相应的更新操作,确保视图与数据保持同步。

下面是一个简单的 Vue 示例,演示了如何使用响应式数据:

<div id="app">
  <p>{
   
   { message }}</p>
  <button @click="updateMessage">Update Message</button>
</div>

<script>
  var app = new Vue({
    el: '#app',
    data: {
      message: 'Hello, Vue!'
    },
    methods: {
      updateMessage: function() {
        this.message = 'Updated message!';
      }
    }
  });
</script>

在这个例子中,data 选项里的 message 属性被 Vue 劫持,当点击按钮时,updateMessage 方法被调用,修改了 message 的值,由于数据的变化是响应式的,所以页面上相应使用了 { { message }} 的地方也会自动更新显示最新的值。

数据劫持是 Vue 实现响应式的重要机制之一,它能够让开发者更加便捷地处理数据变化,并实现数据驱动的视图更新。

数据更新

数据劫持的目的是为了在数据发生变化时,能够自动更新视图。在 Vue.js 中,当数据发生变化时,会触发相应的 getter 和 setter 方法,然后通知相关的 Watcher 更新视图。

Watcher 是 Vue.js 中核心的观察者对象,它可以监听数据的变化,当数据发生变化时,会触发更新视图的操作。

当一个 Vue 组件被创建时,会创建一个渲染 Watcher,它会监听组件中的模板(template)和 data 数据。当组件中的 data 数据发生变化时,渲染 Watcher 就会重新渲染组件。 

当我们在组件中访问 data 数据时,就会触发一次 getter 方法,并将当前的 Watcher 添加到一个全局的栈中。这个栈叫做 Dep(依赖),它会保存当前的 Watcher 实例。 

当 data 数据发生变化时,会触发对应的 setter 方法,并通知 Dep 中保存的所有 Watcher 实例进行更新操作。 

在更新时,渲染 Watcher 会先将组件的 VNode(虚拟 DOM)重新渲染,然后再将新的 VNode 与旧的 VNode 进行比对,找出需要更新的部分,最后将差异更新到真实的 DOM 上。 

总结 

Vue.js 的响应式原理是基于数据驱动的,它通过数据劫持技术实现了对数据的响应式更新。当数据发生变化时,会自动重新渲染视图。

 Vue.js 的数据劫持技术是通过 Object.defineProperty() 方法来实现的,这个方法可以定义对象上的属性,并给属性设置 getter 和 setter,达到数据劫持的目的。

在 Vue.js 中,当组件中的 data 数据发生变化时,会触发对应的 setter 方法,并通知相关的 Watcher 更新视图。

在更新视图时,Vue.js 会先重新渲染 VNode,然后进行差异比对,更新差异部分到真实的 DOM 上。

猜你喜欢

转载自blog.csdn.net/m0_64590669/article/details/135002551
今日推荐