Vue源码解析:数据双向绑定(响应式)原理

本文深入探讨Vue的响应式原理,从数据的侦测和依赖收集两个方面展开,包括对象和数组的可观察实现,以及依赖管理器在getter和setter中的角色。通过重写数组方法实现拦截器,确保数据变化时能被正确侦测和更新视图。
摘要由CSDN通过智能技术生成

vue的双向数据绑定(响应式)原理到底是什么呢?这还是得从vue的源码说起:

我们知道vue的一大特点是数据驱动视图,如何理解数据驱动视图这六个字呢?

数据:state;

驱动:render函数;

视图:页面的UI;

这样说来,其实我们可以得到这样一个公式:UI = render(state),state的变化直接导致UI的变化,而始终不变的是render,vue就是扮演了render的角色。那么vue是如何知道state变化的呢?有个词叫变化侦测,因为在当前的主流技术栈,vue,react,angular中都有提到,也就是状态追宗,一旦数据变化,就去更新视图。我们先从对象的变化侦测说起。

所谓变化侦测,就是我们能够知道数据什么时候被读取了或数据什么时候被改写了。

数据的侦测

1、实现对象的侦测(可观察)

对象的侦测是借助Object.defineProperty()这个方法。

首先定义一个对象animal:


let animal = {
    name: 'dog',
    age: 3

那么这个animal的对象的属性被修改的时候,我们是如何知道的呢,且看下面的操作:


let name = 'cat'
Object.defineProperty(animal, 'name', {
    configrable: true,    //    描述属性是否配置,以及可否删除
    enumerable: true,     //    描述属性是否会出现在for in 或者 Object.keys()的遍历中
    writable: true,       //    属性的值是否可以被重写
    get () {
        //    这里读取了name的值
        return name
    },
    set (value) {
        //    这里设置了name的值
        name = value
    }

这样一来,当name的值被改成cat的时候,就会变的可观测,可被侦测。但是这只是做到了对象的某一个属性被侦测,但是对象的属性往往不是一个,多个的时候又该怎么办呢?其实也很简单,对,没错,就是你想说的递归。直接上代码:

//    源码位置:src/core/observer/index.js
export class Observer {
    constructor (value) {
        this.value = value
        def(value,'__ob__',this)
        if (Array.isArray(value)) {
              // 当value为数组时的逻辑
        } else {
              this.walk(value)
        }
    }
 
    walk (obj: Object) {
        const keys = Object.keys(obj)
        for (let i = 0; i < keys.length; i++) {
              defineReactive(obj, keys[i])
        }
    }
}
function defineReactive (obj,key,val) {
      if (arguments.length === 2) {
            val = obj[key]
      }
      if(typeof val === 'object'){
          new Observer(val)
      }
      Object.defineProperty(obj, key, {
          enumerable: true,
          configurable: true,
          get(){
              console.log(`${key}属性被读取了`);
              return val;
          },
          set(newVal){
              if(val === newVal){
                  return
              }
              console.log(`${key}属性被修改了`);
              val = newVal;
          }
      })
}

我们声明一个Observer类,用于将对象的所有属性都转变为可侦测,并且,我们要给每一个可侦测的对象添加一个__ob__属性,值为value的Observer的实例,这就相当于给每一个value设置了标识,表示这个value是响应式的了。那么当value是一个对象的时候,我们拿到他的所有的key,循环遍历调用Object.defineProperty()的方法,调用get/set方法来侦测,当发现传入的是一个Object的时候,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值