vue源码之数据侦测

VUE源码解析——Object、Array变化侦测原理解析,学习Vue中如何实现数据的响应式系统,从而达到数据驱动视图。 VUE源码解析——Object变化侦测原理解析一、什么是变化侦测?二、Object变化侦测1.Object.defineProperty方法2.依赖收集什么是依赖收集何时收集依赖?何时通知依赖更新?依赖管理器Dep类Watcher类不足之处Object变化侦测流程总结 ├─dist # 项目构建后的文件 ├─scripts # 与项目构建相关的脚本和配置文件 ├─flow # flow的类型声明文件 ├─s 阅读详情

数据侦测

思路:先侦测对象的一个属性,再侦测对象的全部属性,再递归侦测子属性

在来解决数组的侦测问题

最后收集依赖

侦测一个属性

vue2中使用使用Object.defineProperty来监测对象的一个属性,

Object的变化侦测

1. 什么是变化侦测

我们在写vue组件的时候,在模板里面使用的变量,当该变量的值改变的时候,能够直接渲染在页面上,这是数据的响应式原理,如何实现这个功能呢?这其实涉及到很多原理和算法,就包括变化侦测,通过变化侦测,我们就可以侦听到该变量的变化,在这个基础上再实现其他的功能

举个例子:

let obj = {
    a: 1,
    b: 2,
    c: {
        m: {
            n: 4
        }
    }
}

当对象obj被侦测了的时候,当obj.a发生变化的时候,我们就可以侦测的到,即能够侦测到obJ的全部属性,不仅如此,如果obj的属性值是一个对象,我们也要能够侦测的到,即能够侦测的到obj.c.m.n

2. 如何实现对象的变化侦测

思路

对一个需要被侦听的对象,先遍历它的所有属性,并用Obj.defineProperty来侦听每一个属性,然后再判断每个属性值是否是一个对象,如果是的话还需要遍历这个对象的所有属性

具体实现
observe
  • 首先需要有Observe这个函数,它算是变化侦测的一个入口,将需要被侦测的对象传给这个函数

    比如:

    let obj = {
        a: 1,
        b: 2,
        c: {
            m: {
                n: 4
            }
        }
    }
    
    Observe(obj)  // 此时Obj即被侦测了!
    
  • 需要判断定的参数值是否是对象或者该对象是否已经被侦测了,当该对象具有__ob__时,即表示已经被监测了

  • 若没有__ob__这个属性时,即没有被侦测,此时需要用到Observer这个对象(注意后面有“r),在这个对象上对这个对象进行监测

  • 具体实现代码

    export default function (value) {
        // 如果value不是对象,什么都不做
        if (typeof value != 'object') return;
        // 定义ob
        var ob;
        if (typeof value.__ob__ !== 'undefined') {
            ob = value.__ob__;
        } else {
            ob = new Observer(value);
        }
        return ob;
    }
    
    
Observer类

上文提到的,Observer类是要监听该对象的所有属性,具体功能如下:

  • Observer接受一个要侦听的对象,先给这个对象添加一个__ob__属性,属性值为此次Observer实例,表示这个对象的所有属性都已经被监听了,并让这个__ob__不能被枚举

  • 定义一个方法walk,利用这个方法遍历对象的属性,使用defineReactive这个函数监听所有属性

  • 实现代码:

    class Observer {
        // value就是被侦听的对象
        constructor(value) {
            // 利用这个属性给这个对象添加__ob__属性,函数在下面
            def(value, '__ob__', this, false)
            // 监听每个属性
            this.walk(value)
        }
        
        walk(value) {
            // 遍历属性,通过这个方法侦听每个属性
            for(let k in value) {
                defineReactive(value, k)
            }
        }
    }
    
    const def = function (obj, key, value, enumerable) {
        Object.defineProperty(obj, key, {
            value,
            enumerable,
            writable: true,
            configurable: true
        });
    };
    
defineReactive

利用这个函数,通过defineProperty对传进来的属性进行监听,并判断属性值是否是对象,是的话再调用observe这个函数监听该对象,类似于递归调用,但不是递归本身,而是observe、Observer、defineReactive三者循环调用。具体功能如下:

  • 接三个参数,data是对象,key是属性,value是属性值,默认等于data[key]

  • 调用Object.defineProperty监听每个属性,并配置get,set方法,在get中返回value,set中修改value,注意此时的value是传进来的参数,但js会分配给这个参数单独的内存空间,所以每调用一次,参数的地址都是不一样的。

  • 利用observe,将value传进去,value是对象属性的值,这一步是处理属性值是对象的情况,但在这个函数中不用判断value是否是对象,因为在observe中已经有判断若传进来的不是对象,直接return了

  • 另外,当属性被设置了新的值(newValue)的时候,此时会触发set方法,需要判断新的值是否是对象,即调用observe(newValue)

  • 具体代码:

    function defineReactive(data, key, value = data[key]) {
        Object.defineProperty(data, key, {
            // 可枚举
            enumerable: true,
            // 可以被配置,比如可以被delete
            configurable: true,
            get() {
                return value
            },
            set(newValue) {
                // newValue就是想要设置的新值
                // 即此时没有改变属性值
                 if (val === newValue) {
                    return;
                }
                value = newValue
                // 判断新值是否是对象
                observe(newValue)
            }
        })
       // 判断设置的值是否是对象 
        observe(value)
    }
    

依赖收集

现在我们已经将对象的变化侦测实现了,即对象属性值发生变化时我们能够侦测的到,之后呢,我们是不是就得去通知所以使用这些对象的函数或模板组件做出相应的改变,前提是我们得知道哪些使用了这些对象,我们把使用这些变化侦测对象的模板或组件等称为依赖

什么是依赖

依赖就是使用了这个数据的模板或者组件

举个例子:

<template>
    <div>
        {{name}}
    </div>
</template>

在上面的这个模板中,使用了name这个响应式变量,所以这个模板就是这个变量name的一个依赖。需要注意的是,我们不是直接收集这些模板的,而是收集一个叫做Watcher的对象实例,Watcher与真正模板的重新渲染不是这一章要了解的,我们这一章主要是收集Watcher实例

举个例子:

vm.$watch('a.b.c', callback)

在vue组件中,这段代码表示的是当data.a.b.c属性发生变化时,会触发callabck这个回调函数

那其实这里就是用到了这个data.a.b.c属性,相当于这个属性的一个依赖,我们用Watcher实例作为依赖的话,就相当于

new Watcher(data, 'a.b.c', callback)
如何收集依赖

当执行new Watcher(data, 'a.b.c', callback)时,会触发data.a.b.c的get操作,此时就可以把这个依赖通过get方法收集起来,如果修改了这个属性的话,就会触发set操作,此时就需要通知这些依赖。总的来说,就是在getter中收集依赖,在setter中触发(通知)依赖

具体实现
  • 首先,需要一个Dep类,这个类是用来管理每一个属性的依赖的,包括添加依赖,触发依赖等。所以需要在每个属性上new一个Dep实例
  • 还需要一个Watcher类,这个类就是依赖,每使用一个被侦测的对象的属性时,就会new一个Watcher实例,当被通知到属性值修改后,就会执行回调函数
Dep类
  • Dep类是用来管理属性的依赖的,所以每个属性必须拥有一个dep实例,在defineReactive这个函数中,我们会监听每个属性,所以在这里给属性加上一个dep实例最好不过了

  • dep类上有一个数组subs,用来添加每个属性的依赖

  • 有一个depend方法,在这个方法中,会判断是否有Dep.target这个对象,如果有的话,就表示此时有依赖需要添加,Dep.target就是一个我们自己指定的全局的位置,你用window.target也行,只要是全剧唯一,没有歧义就行,当我们new一个Watcher实例时,就会给Dep.target设置一个值,依赖添加完成之后,再把Dep.target设置为null

  • 还有一个notify方法,当侦听的属性发生变化时,会通知每一个依赖,出发每一个依赖的update方法

  • 具体代码:

    class Dep {
        constructor() {
            // 用数组存储自己的订阅者。subs是英语subscribes订阅者的意思。
            // 这个数组里面放的是Watcher的实例
            this.subs = []
        }
        depend() {
            if(Dep.target) {
                this.add(Dep.target)
            }
        }
        addSub(sub) {
            this.subs.push(sub)
        }
        notify() {
            const subs = this.subs.slice()
            for(let i = 0; i < subs.length; i++) {
                subs[i].update()
            }
        }
    }
    
Watcher类
  • Watcher实例就是依赖,接受三个参数,分别为target, expression, callback,target就是监听的对象,expression就是监听对象的某个属性,callback就是这个属性改变时会执行的函数

    new Watcher(data, 'a.b.c', callback)
    
  • 在这个类中,首先会解析a.b.c,得到所使用的属性,此时需要一个parsePath函数,该函数会返回一个函数(赋值在实例的getter上),并获得所使用的属性,但要注意的是,通过这个函数我们并不知道这个属性属于那个对象,只有通过我们传入一个对象后才知道

    function parsePath(str) {
        var segments = str.split('.')
        return (obj) => {
            for(let i = 0; i < segments.length; i++) {
                // 若obj不存在,则表示找不到这个属性
                if(!obj) return
                obj = obj[segments[i]]
            }      
            return obj  
        }
    }
    
  • 接着,会调用自身的get方法,意味着进入依赖收集阶段,会将全局的Dep.target设置为Watcher本身,并调用自身的getter方法,在这个方法中会触发属性的getter操作,并在此操作中将Watcher收集在dep上,收集结束后要记得将Dep.target设置为null

  • 最后,还需要有一个update方法,当属性值改变之后,能够通知到该依赖,并执行这个方法

  • 代码如下:

    var uid = 0;
    export default class Watcher {
        constructor(target, expression, callback) {
            console.log('我是Watcher类的构造器');
            this.id = uid++;
            this.target = target;
            // parsePath(expression)返回一个函数,放在getter上,所以getter没有什么特别含义
            this.getter = parsePath(expression);
            this.callback = callback;
            this.value = this.get();
        }
        update() {
            this.run();
        }
        get() {
            // 进入依赖收集阶段。让全局的Dep.target设置为Watcher本身,那么就是进入依赖收集阶段
            Dep.target = this;
            const obj = this.target;
            var value;
    
            // 只要能找,就一直找
            try {
                // 此时要找到obj里expression这个属性值 
                value = this.getter(obj);
            } finally {zhih1
                Dep.target = null;
            }
    
            return value;
        }
        run() {
            this.getAndInvoke(this.callback);
        }
        getAndInvoke(cb) {
            const value = this.get();
    
            if (value !== this.value || typeof value == 'object') {
                const oldValue = this.value;
                this.value = value;
                cb.call(this.target, value, oldValue);
            }
        }
    };
    

数组的变化侦测

var obj = {
    a: {
        m: {
            n: 5
        }
    },
    b: 10,
    c: {
        d: {
            e: {
                f: 6666
            }
        }
    },
    g: [22, 33, 44, 55]
};

像上面这段代码中,对象的属性g是数组的情况下,我们对数组进行push等操作时,这个动作是不会被拦截的,所以通过getter/setter的方式行不通

如何追踪变化

前面Object的变化时靠getter来追踪的,一个属性发生变化,就会触发getter。同理,我们只要能在数组中使用push等操作时被通知,就能实现同样的功能

但在es6之前,js没有提供可以拦截原型方法的能力,所以我们只能用自定义的方法去覆盖原型上的方法。

经过整理,我们发现Array原型上有7个方法可以改变数组自身内容,分别为:push, pop, shift, unshift, split, sort, reverse,所以,我们可以用一个拦截器,每当数组使用这些方法的时候,其实执行的是拦截器里的自定义的方法,如图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sdS9oKpH-1649087186200)(变化侦测.assets/image-20220330164500023.png)]

拦截器设计

  • 我们要让数组的原型指向拦截器上,并在拦截器上定义push这些方法,再让拦截器指向Array.prototype,这样数组还能使用Array的其他方法

  • 拦截器其实就是一个对象,在这个对象上添加push这些方法,并用Object.defineProperty()监听这些属性

  • 为了保证原来的push等功能不被剥掉,我们需要备份原方法,添加在拦截器的属性上

  • 有三种方法push\unshift\splice能够插入新的内容(有可能是对象),所以需要再observe一下这些新元素

  • 定义一个函数array.js来设计拦截器,并把拦截器暴露出去

    具体代码如下:

    const arrayPrototype = Array.prototype
    
    // 将拦截器原型指向数组原型上
    export const arrayMethods = Object.create(arrayPrototype)
    
    // 要被改写的7个数组方法
    const methodsNeedChange = [
        'push',
        'pop',
        'shift',
        'unshift',
        'splice',
        'sort',
        'reverse'
    ];
    
    methodsNeedChange.forEach((methodName) => {
        // 保留原先的方法
        const original = arrayPrototype[methodName]
        // 给拦截器定义方法,def函数上文有介绍过
        def(arrayMethods, methodName, function() {
            // 恢复原来的方法,注意这里this指向数组自身,不能用箭头函数
          	original.apply(this, arguments)
              // 把类数组对象变为数组
            const args = [...arguments];
            // 把数组身上的__ob__属性取出来,要记得数组是一个对象,会在observer的时候添加__ob__属
            // 性,并且该属性值是observer实例
            const ob = this.__ob__
            // 有三种方法push\unshift\splice能够插入新项,现在要把插入的新项也要变为observe的
            let inserted = [];
    		 switch (methodName) {
                case 'push':
                case 'unshift':
                    inserted = args;
                    break;
                case 'splice':
                    // splice格式是splice(下标, 数量, 插入的新项)
                    inserted = args.slice(2);
                    break;
            }
             // 判断有没有要插入的新项,让新项也变为响应的,ob.observeArray下文会介绍
            if (inserted) {
                ob.observeArray(inserted);
            }
            // 触发时表示数组被更改,需要通知依赖,这里要注意的是!!!比如执行obj.g.push()时,是要通知		// obj的,obj身上也有一个dep
            ob.dep.notify();
        }, false)
    })
    

使用拦截器覆盖Array原型并挂载在数组上

  • 由于对象和数组的监测方式是不同的,所以在new一个observer实例的时候需要判断传入的value是否是一个数组

  • 如果是一个数组的话,就需要将原型添加到拦截器上

  • 若数组内可存在对象的话,也是需要被监测的,所以需要observe每一个数组元素,但不能像对象一样使用walk()方法,即此时数组内的某个普通元素变化时不能检测到?????????????????

  • 具体代码在observer这个类中:

    class Observer {
        constructor(value) {
            // 每一个Observer的实例身上,都有一个dep
            this.dep = new Dep();  // 给数组,对象收集依赖
            // 给实例(this,一定要注意,构造函数中的this不是表示类本身,而是表示实例)添加了__ob__属性,值是这次new的实例
            def(value, '__ob__', this, false);
            // console.log('我是Observer构造器', value);
            // 不要忘记初心,Observer类的目的是:将一个正常的object转换为每个层级的属性都是响应式(可以被侦测的)的object
            // 检查它是数组还是对象
            if (Array.isArray(value)) {
                // 如果是数组,要非常强行的蛮干:将这个数组的原型,指向arrayMethods
                // es6写法  Object.setPrototypeOf(value, arrayMethods);
                value.__proto__ = arrayMethods
                // 让这个数组变的observe
                this.observeArray(value);
            } else {
                this.walk(value);
            }
        }
        // 遍历
        walk(value) {
            for (let k in value) {
                defineReactive(value, k);
            }
        }
        // 数组的特殊遍历
        observeArray(arr) {
            for (let i = 0, l = arr.length; i < l; i++) {
                // 逐项进行observe
                observe(arr[i]);
            }
        }
    };
    
数组不支持_proto_的情况

当不能使用__proto__的时候,Vue的做法是直接将拦截器上的方法直接设置在被侦测的数组上

function protoAugment(target, src, key) {
    target.__proto__ = src
}

function copyAugument(target, src, keys) {
    for(let i = 0; i < keys.length; i++) {
        const key = keys[i]
        def(target, key, src[key])
    }
}

// Observer类部分
const hasProto = '__proto__' in {}
const arrayKeys = Object.getOwnPropertyNames(arrayMethods)
if(Array.isArray(value)) {
    const augument = hasProto ? protoAugment : copyAugument
    augument(value, arryMethods, arrayKeys)
} else {
    this.walk(value)
}
约2万字-Vue源码解读汇总篇(续更) 未完待续...Vue源码解读:06Vue3探索篇Vue源码解读:05生命周期篇Vue源码解读:04模板编译篇Vue源码解读:03虚拟Dom篇Vue源码解读:02变化侦测篇Vue源码解读:01核心思想篇Vue源码解读:前言篇从写下的代码,到用户见到界面,大致经历以下几个流程:模板字符串=》ast树=》render函数=》vnode=》用户见到的界面。将开发者写下的模板字符串,经过一些列处理,生成render函数的这一过程就是模板编译。简单地说,模板编译解析就是为了得到render函数。 阅读详情

相关推荐

第三章、变化侦测相关的API实现原理

本章我们来讲解关于变化侦测的三个API:vm.watch、vm.watch、vm.watch、vm.set、vm.$delete 1、vm.$watch 语法:vm.$watch(expOrFn, callback, [options]) 使用: vm.$watch('a.b.c',(newVal,oldVal)=>{ // do something }); 或者 var unwa...

Bidding 388

vue 源码中依赖 Watcher 和 parsePath函数

vue依赖watcher和parsePath函数

qq_42744920的博客 514

五、2K0300 久久派开发板的GPIO控制与Shell脚本自动化实战

本文详细介绍了基于龙芯2K0300处理器的久久派开发板的GPIO控制方法,通过sysfs文件系统实现LED控制和传感器读取。重点讲解了Shell脚本自动化实战,包括LED闪烁、流水灯效果和传感器数据采集,为物联网项目开发提供完整解决方案。

silver的专栏 687

Vue2 响应式原理

可以看到,通过该方法,我们可以更加精细地控制对象属性的可读性、可写性、可枚举性和可配置性等特性,并且可以为一个属性自定义读取器(get)和写入器(set)等逻辑处理。简单来说,在 Vue2 响应式系统中,当数据发生改变时,会触发 get 和 set 方法,get 方法会收集所有依赖该数据的 Watcher 对象,set 方法会通知 Dep 对象触发所有 Watcher 对象的回调函数进行更新。当其中任意一个属性的值发生变化时,其对应的依赖都会被更新,从而触发其绑定的观察者的回调函数。

weixin_62992614的博客 3081

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

m0_72224305的博客 4306

告别F5失灵!手把手教你为Cursor配置.Net Core控制台项目专属调试环境

本文详细指导如何在Cursor编辑器中为.Net Core控制台项目配置专属调试环境,解决F5失灵等常见问题。从调试器选择到launch.json配置,再到高级调试技巧,帮助开发者高效搭建完整的调试工具链,提升开发效率。

weixin_28834765的博客 286

Vue响应式原理:Watcher与Dep的深度解析

本文通过一个交互式示例深入解析了Vue响应式系统中Watcher与Dep的核心机制。文章展示了:1)Dep作为依赖收集器,负责管理每个响应式属性的Watcher订阅;2)Watcher作为观察者,在数据访问时被收集,在数据变更时执行回调更新视图。通过可视化演示了"数据劫持-依赖收集-触发更新-执行回调"的工作流程,并提供了简化版的Dep和Watcher实现代码,帮助理解Vue如何实现数据与视图的自动同步。

油墨香^-^的博客 721

泛微E8流程监控指南:如何用SQL实时追踪审批节点状态?

本文详细介绍了如何利用SQL实时监控泛微E8系统中的审批流程状态,包括核心数据表结构解析、全链路监控SQL实战以及智能预警机制设计。通过数据库直接查询和状态关联分析,帮助企业快速定位卡顿节点,提升流程效率。适用于需要优化OA系统流程管理的企业IT人员和业务主管。

weixin_30687051的博客 439

《深入浅出vue.js》中变化侦测的源码以及解析

《深入浅出vue.js》中变化侦测的源码以及解析 背景 最近由于公司知识体系变动,需要学习vue来适应新的开发平台,我选择了《深入浅出vue.js》来进行学习,之前有了解过一些vue知识,这次打算深入学习一下,尤其是第一篇变化侦测,学习过程中对javascript也增加了不少理解,我把代码都手打了出来,代码中有很多按照自己理解打上的注释,这里分享给大家。 开门见山 这里我不给大家解释他是什么,书中...

Run_youngman的博客 519

科研绘图(二):R 语言实现小鼠脑图谱 3D 渲染,附完整代码与数据获取指南

在生物医学科研中,脑区的 3D 可视化是呈现实验结果、解析脑结构功能的重要手段。R 语言凭借rgl和Rvcg等工具包,可高效实现小鼠全脑及特定脑区(如 CA1 区)的立体渲染,且代码可复用性强。本文将从环境搭建、数据准备、代码实现到结果导出,手把手带你完成小鼠脑图谱 3D 绘图,小白也能快速上手!

good_rrrrr的博客 2024

【STM32 CubeMX】I2C中断方式与DMA方式

在STM32 CubeMX环境中,I2C(Inter-Integrated Circuit)通信协议的实现可以采用中断方式或DMA(Direct Memory Access)方式。中断方式通过触发中断来处理数据传输,而DMA方式则利用直接内存访问技术来实现数据传输,减轻了CPU的负担。在选择I2C通信方式时,开发者需要根据具体的应用需求和性能要求来选择合适的方式。STM32 CubeMX提供了图形化配置工具,使得配置I2C通信方式变得更加便捷。

m0_62599305的博客 7749

Vue2(四):Vue监测数据的原理

如果我要点击按钮实现更新冯万宁儿的信息,那么如果一个属性一个属性地改,可以修改成功,并且Vue也会检测到并更新到页面。但是我如果直接把整个对象改了,可以修改成功,但是Vue监测不到并且不更新到页面,这是为啥捏?请君慢慢往下阅读 2.原生js模拟Vue监视data对象中的数据 用原生js写一个Vue监视data数据改变的效果 代码自己琢磨琢磨,有点儿意思。可以看出,Vue监视数据的原理,就是靠 如果不理解,想想前边讲Object.defineProperty时那个number 这只是个模拟,实际上Vue做了更

weixin_42044763的博客 2840

YOLO十年演进:从CNN到Transformer再到MoE,我看懂了2026年目标检测的落地风向标

技术永远是为业务服务的,能解决真实问题的技术,才是有价值的。YOLO的十年演进,从CNN到Transformer再到MoE,从来都不是学术上的炫技,而是一步一步解决工业落地的痛点:从让实时检测成为可能,到解决复杂场景的漏检误检,再到打破精度和算力的死局,每一步都踩在了工业落地的真实需求上。很多新入行的朋友,总喜欢追新,今天换Transformer,明天堆MoE,觉得模型越新、参数越大,就越厉害。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 748

vue源码解析1 之数据响应之谜(数据侦测)

我与vue源码 之前写过一篇死磕vue源码,写了一篇就真心写不下去,vue的代码现在健壮的不要不要的那么写会越写越乱,最后会搞到自己都看不懂的地步。我写文章也是东一榔头西一棒锤,今天就继续搞vue的源码,不过这次的策略不一样的。我呢,分析了一下vue的几件神器: 数据响应式(也就是数据侦测); AST抽象语法树(个人理解就是虚拟DOM, 把字符串的DOM模版转换为对象形式的DOM树); diff算法(最小量更新); 当然了个人理解,vue就是以这几件大神器为底,建造起了一个前端框架。 数据侦测 每个框架

weixin_43139949的博客 365

[Dify] 【实战笔记】优化 Excel 电话簿类知识库检索效果的实战技巧

摘要:文章分析了Dify知识库在处理Excel结构化数据(如电话簿)时出现的检索异常问题,发现主要原因是默认召回多条记录且缺乏精准匹配机制。提出两个核心解决方案:1)优化知识库召回参数,包括调整TopK值、提高关键词权重等;2)设计精准提示词模板,明确约束模型行为范围。通过对比测试验证了优化效果,并给出进阶建议如数据格式转换、输出格式化等。最后针对知识检索类AI应用提供了场景适配建议。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 368

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

vue.3.0 dom赋值_Vue 3.0 源码分析数据侦测

2020年前端大事件之一,Vue 3.0终于正式发布了。作为一个大的版本更新,Vue 3 与 Vue 2相比,实现原理,使用方式等均有着不小的改动。本文主要会介绍讲述二块内容,分别是Vue 3.0 的简要介绍,Vue 3.0 数据侦测源码分析。小伙伴们可以根据自己的需求,查看对应的内容,也欢迎各位一起探讨,一起学习。Vue 3.0 简要介绍Vue 3 的 “前世今生”2016年,Vue ...

weixin_42301367的博客 369

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Vue源码数据侦测篇

Vue最大的特点就是数据驱动视图,动态变化,他由前一个状态到了后一个状态,页面也就应该变化,所以我们得到以下公式 UI = render(state) UI公式中:状态state是输入,页面UI输出,一旦状态发生改变,页面输出也就随之也改变,把这种特性称之为数据驱动视图。 把UI公式分为三个部分,state,render(),UI。 state和UI都是用户顶的,不变的是render(),所以Vue就扮演了render()角色,当Vue发生state变化之后,经过一系列加公,最后变化反映在UI上 Vue.

weixin_43405946的博客 210

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Vue源码系列讲解——变化侦测篇【上】(何为变化侦测)

最大的特点之一就是数据驱动视图,那么什么是数据驱动视图呢?在这里,我们可以把数据理解为状态,而视图就是用户可直观看到页面。数据驱动视图简单来说就是数据变化引起视图变化,那么第一步就是先要知道数据什么时候发生变化,也就是说对数据的变化要进行侦测。输出,状态输入一旦变化了,页面输出也随之而变化。变化侦测就是追踪状态,亦或者说是数据的变化,一旦发生了变化,就要去更新视图。其次,数据的变化侦测在三大框架中均有涉及,不同的框架有着自己的一套侦测机制。变化之后,经过一系列加工,最终将变化反应在。来实现变化侦测,而在。

小彭的博客 650

vue源码学习(数据侦测、虚拟DOM、Diff算法)

vue源码 ├─dist # 项目构建后的文件 ├─scripts # 与项目构建相关的脚本和配置文件 ├─flow # flow的类型声明文件 ├─src # 项目源代码 │ ├─complier # 与模板编译相关的代码 │ ├─core # 通用的、与运行平台无关的运行时代码 │ │ ├─observ

qq_43271330的博客 365

解析vue2.x源码之Object与Array的变化侦测

基本概念介绍: Vue框架是如何实现变量的变化侦测的呢? Object 利用了 Object.defineProperty 进行变量的getter与setter拦截,但数组的实现与 Object 有所不同,下面会从源码层面具体讨论这两种类型的变量如何实现变化侦测。 首先我们需要先了解Vue源码中的三个类: 一、Observer Observer类负责将复杂类型的变量转化成响应式数据,转化...

qq_36259513的博客 615

嗨,让我带你逐行剖析Vue.js源码(一个月时间github上star数已经破1600!!!)

短短一个月时间内本项目在github上star数量就已经破千!!!Hello,大家好,本人最近在github上做一个关于Vue源码的开源项目,项目内容是:利用工作之余时间逐行剖析Vuej...

frontend_frank的博客 948

vue源码简单剖析(1)---object如何实现变化侦测

vue最大的特点之一就是数据驱动视图,也就是数据的变化,引起视图的变化。那么,第一步肯定要知道数据什么时候发生变化,这就叫做对数据的变化侦测 想要知道数据什么时候发生变化,我们可以使用js的Object.defineProperty方法 let student = { 'age': 11, } 我们可以直接通过student.age读取到学生的年龄是11,但是当学生年龄的值被修改了,我们如何才能主动知道值被修改了呢? 我们可以使用Object.de...

mfuuty的博客 230

VUE源码解析

VUE源码理解 1.公式:UI=render(state) state是输入,UI是页面输出,VUE充当render()这个角色,当vue发现其state变化之后,经过一系列的加工,最终变化反映在UI上 Object的变化侦测 2.变化侦测 变化侦测是追踪状态,一旦数据发生变化,就会去更新视图 3.object的更新变化 let car = {} let val = 3000 Object.defineProperty(car, 'price', { enumerable: true, config

程文英 855

【深入浅出Vue.js篇】之变化侦测相关API实现原理

数据监听相关API实现原理

m0_48192059的博客 341

vue源码解析

vue源码解析 源码结构 ├─dist # 项目构建后的文件 ├─scripts # 与项目构建...

愚人码头的博客 69

Vue3 Beta版发布对于放弃 Object.defineProperty API你了解多少?(一)

千呼万唤使出来Vue3 Beta 版本终于在前几天发布了,为了更好的初始化性能在新版本中Vue把数据对象侦测的API 从Object.defineProperty 换成 Proxy,这么...

ItStar 458
上一篇: this指向问题全面解析
下一篇: leetcode15. 三数之和
Lin__hr
博客等级 码龄6年 5粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值