返回

彻底洞悉Vue数据响应式原理,不再是源码小白!

前端

<p style=text-align:center;></p>

<p style=text-align:center;></p>

<p style=text-align:center;></p>

>**Vue源码学习(一):你不知道的数据响应式原理** 

**前言** 

当今的前端面试,越来越注重源码这一块了。而且就算没有面试,我想,每一个vue的使用者,在使用了一段时间的vue框架之后,也应该自觉去思考,这个框架是怎么实现的,他怎么就能这么方便呢?当然,这也不需要立马开始就读源码。Vue框架对于我们的初级工程师来说有点重量级。但是,如果你要进阶,你避不开源码。

所以,为了帮助大家更好的理解Vue框架,我决定开一个系列的文章,来详细介绍Vue的源码。本文是该系列的第一篇,主要内容是Vue的数据响应式原理。

**一、数据响应式原理概述** 

数据响应式原理,是Vue框架的核心之一。它使得Vue能够自动侦听数据的变化,并在数据变化时自动更新视图。

**二、Vue如何实现数据响应式** 

Vue实现数据响应式有两种方式:

* **利用ES6的Proxy特性** 
* **通过Object.defineProperty()方法** 

Vue主要使用的是第二种方式。

**三、Object.defineProperty()方法实现数据响应式原理** 

```javascript
Object.defineProperty(data, key, {
  enumerable: true,
  configurable: true,
  get: function() {
    console.log('你访问了' + key + '属性!');
    return value;
  },
  set: function(newValue) {
    console.log('你设置了' + key + '属性的值!');
    value = newValue;
    updateView();  // 更新视图
  }
});

四、Vue源码实现数据响应式原理

在Vue源码中,数据响应式原理是通过defineReactive()函数实现的。

export function defineReactive (
  obj: object,
  key: string,
  val: any,
  customSetter?: Function
): void {
  const dep = new Dep()
  // 创建Dep实例,用来收集依赖
  const property = Object.getOwnPropertyDescriptor(obj, key)
  // 取出属性符
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  const getter = property && property.get
  const setter = property && property.set
  if ((!getter || setter) && arguments.length === 2) {
    val = obj[key]
  }
  // 收集依赖

  let childOb = !isPrimitive(val) && observe(val)
  // 递归实现响应式
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      // 依赖收集
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          // 如果是嵌套对象,递归进行依赖收集
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      // set操作,判断新值和旧值是否相等,不相等则触发更新
      if (customSetter) {
        customSetter()
      }
      // 调用getter触发依赖收集
      const oldVal = val
      val = newVal
      dep.notify()
      // 触发依赖更新
      if (childOb) {
        childOb.dep.notify()
        // 如果是嵌套对象,递归触发依赖更新
      }
    }
  })
}

五、总结

本文详细介绍了Vue数据响应式原理,从基本概念到核心实现,深入浅出,循序渐进,希望能够帮助您彻底理解Vue数据响应式原理。

如果您对Vue源码感兴趣,欢迎继续阅读我的系列文章。下一篇,我们将介绍Vue的虚拟DOM。