vue2.0,vue3.0原理解读

数据响应式原理机制

1、vue2.0 - Object.defineProperty

原理:利用递归把对象所有属性通过es5 中(Object.defineProperty) 方法绑定get 、set方法。所以数组需要特殊处理数据进行绑定。
1.1 对象拦截方法

function observer(target){
    // 如果不是对象数据类型直接返回即可
    if(typeof target !== 'object'){
        return target
    }
    // 重新定义key
    for(let key in target){
        defineReactive(target,key,target[key])
    }
}
function update(){
    console.log('update view')
}
function defineReactive(obj,key,value){
    observer(value); // 有可能对象类型是多层,递归劫持
    Object.defineProperty(obj,key,{
        get(){
            // 在get 方法中收集依赖
            return value
        },
        set(newVal){
            if(newVal !== value){
                observer(value);
                update(); // 在set方法中触发更新
            }
        }
    })
}
let obj = {name:'youxuan'}
observer(obj);
obj.name = 'webyouxuan';

1.2 数组拦截方法

let oldProtoMehtods = Array.prototype; // 1、首页获取数组的原型属性
 //2、将proto 的原型指向Array.prototype
let proto = Object.create(oldProtoMehtods);
// 3、重写数组的这7个方法
['push','pop','shift','unshift','splice','sort','reverse'].forEach(method=>{
    Object.defineProperty(proto,method,{
        get(){
            update();
            oldProtoMehtods[method].call(this,...arguments)
        }
    })
})
function observer(target){
    if(typeof target !== 'object'){
        return target
    }
    // 如果不是对象数据类型直接返回即可
    if(Array.isArray(target)){
        Object.setPrototypeOf(target,proto);
        // 给数组中的每一项进行observr
        for(let i = 0 ; i < target.length;i++){
            observer(target[i])
        }
        return
    };
    // 重新定义key
    for(let key in target){
        defineReactive(target,key,target[key])
    }
}

测试

let obj = {hobby:[{name:'youxuan'},'喝']}
observer(obj)
obj.hobby[0].name = 'webyouxuan'; // 更改数组中的对象也会触发试图更新
console.log(obj)

Object.defineProperty缺点

  • 无法监听数组的变化
  • 需要深度遍历,浪费内存

2、Vue3.0 - Proxy

在学习Vue3.0之前,你必须要先熟练掌握ES6中的 Proxy、Reflect 及 ES6中为我们提供的 Map、Set两种数据结构

先应用再说原理:

let p = Vue.reactive({name:'youxuan'});
Vue.effect(()=>{ // effect方法会立即被触发
    console.log(p.name);
})
p.name = 'webyouxuan';; // 修改属性后会再次触发effect方法

源码是采用 ts 编写,为了便于大家理解原理,这里我们采用js来从0编写,之后再看源码就非常的轻松啦!

2.1 reactive方法实现
通过proxy 自定义获取、增加、删除等行为

function reactive(target){
    // 创建响应式对象
    return createReactiveObject(target);
}
function isObject(target){
    return typeof target === 'object' && target!== null;
}
function createReactiveObject(target){
    // 判断target是不是对象,不是对象不必继续
    if(!isObject(target)){
        return target;
    }
    const handlers = {
        get(target,key,receiver){ // 取值
            console.log('获取')
            let res = Reflect.get(target,key,receiver);
            return res;
        },
        set(target,key,value,receiver){ // 更改 、 新增属性
            console.log('设置')
            let result = Reflect.set(target,key,value,receiver);
            return result;
        },
        deleteProperty(target,key){ // 删除属性
            console.log('删除')
            const result = Reflect.deleteProperty(target,key);
            return result;
        }
    }
    // 开始代理
    observed = new Proxy(target,handlers);
    return observed;
}
let p = reactive({name:'youxuan'});
console.log(p.name); // 获取
p.name = 'webyouxuan'; // 设置
delete p.name; // 删除

我们继续考虑多层对象如何实现代理

let p = reactive({ name: "youxuan", age: { num: 10 } });
p.age.num = 11

由于我们只代理了第一层对象,所以对age对象进行更改是不会触发set方法的,但是却触发了get方法,这是由于 p.age会造成 get操作

get(target, key, receiver) {
      // 取值
    console.log("获取");
    let res = Reflect.get(target, key, receiver);
    return isObject(res) ? reactive(res) : res; // 懒代理,只有当取值时再次做代理,vue2.0中一上来就会全部递归增加getter,setter
}

这里我们将p.age取到的对象再次进行代理,这样在去更改值即可触发set方法

我们继续考虑数组问题
我们可以发现Proxy默认可以支持数组,包括数组的长度变化以及索引值的变化

let p = reactive([1,2,3,4]);
p.push(5);

但是这样会触发两次set方法,第一次更新的是数组中的第4项,第二次更新的是数组的length

我们来屏蔽掉多次触发,更新操作

set(target, key, value, receiver) {
    // 更改、新增属性
    let oldValue = target[key]; // 获取上次的值
    let hadKey = target.hasOwnProperty(key); // 看这个属性是否存在
    let result = Reflect.set(target, key, value, receiver);
    if(!hadKey){ // 新增属性
        console.log('更新 添加')
    }else if(oldValue !== value){ // 修改存在的属性
        console.log('更新 修改')
    }
    // 当调用push 方法第一次修改时数组长度已经发生变化
    // 如果这次的值和上次的值一样则不触发更新
    return result;
}

解决重复使用reactive情况

// 情况1.多次代理同一个对象
let arr = [1,2,3,4];
let p = reactive(arr);
reactive(arr);

// 情况2.将代理后的结果继续代理
let p = reactive([1,2,3,4]);
reactive(p);

这边我测试了一下,没有重复打印 那解决方案就不在这里写了,遇到的朋友可以去下面链接,原文查看,我这边根据下面的文章做了整理。为了更好的理解和学习把!

到这里reactive方法基本实现完毕,接下来就是与Vue2中的逻辑一样实现依赖收集和触发更新

在这里插入图片描述

本文参考原文
https://www.cnblogs.com/fs0196/p/12691407.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 尚硅谷是国内知名的IT培训机构,他们提供了关于Vue2.0和3.0的全套教程。Vue是一种流行的JavaScript框架,用于构建用户界面。2.0版本是Vue的早期版本,而3.0版本是最新的更新版本。 2.0版本的教程主要介绍了Vue的基础知识和核心概念,包括组件、指令、过滤器等。学习者可以了解如何使用Vue来构建单页应用程序,处理数据绑定、事件处理和路由等功能。此外,教程还涉及Vue的工具和生态系统,如Vue Router和Vuex,它们可以扩展Vue的功能。 而3.0版本的教程则更加深入地介绍了Vue的新特性和改进。其中最重要的特性是使用了新的响应式系统,可以提高性能和开发效率。教程还包括Vue 3中的虚拟DOM、组合API、静态类型检查等内容。学习者通过这些教程可以了解如何迁移现有的Vue 2项目到Vue 3,并且可以利用新特性来构建更高效、可靠的Web应用程序。 尚硅谷的教程以系统性和实战性为核心,学习者不仅可以理论上了解Vue的各种概念和技术,还可以通过实际案例和项目实践来巩固所学知识。此外,教程提供了丰富的练习和实践任务,帮助学习者深入理解和应用所学内容。 总体而言,尚硅谷的Vue 2.0和3.0全套教程提供了全面的学习资源,使学习者能够系统地学习和掌握Vue的开发技能,从而在前端开发领域取得更大的成就。 ### 回答2: 尚硅谷是一家知名的IT教育机构,他们提供了一套完整的Vue2.0Vue3.0教程系列。 Vue是一种流行的JavaScript前端框架,它以其简洁易用和高效的特性而受到广泛的欢迎。尚硅谷的Vue教程从基础开始,逐步深入,涵盖了从Vue2.0Vue3.0的全套内容。 对于Vue初学者来说,尚硅谷的教程非常适合。他们从Vue的核心概念开始讲解,例如组件、指令、生命周期等,帮助学习者建立起对Vue的基础理论。然后他们会引导学习者通过实践项目来锻炼自己,这些项目包括购物车、社交媒体应用等。 在Vue2.0部分,尚硅谷详细介绍了Vue的基本语法、Vue组件、路由、状态管理等方面的内容。他们通过一步一步的演示和实践指导,帮助学习者掌握Vue的使用技巧和开发经验。 而在Vue3.0部分,尚硅谷更新了教程内容,包括了对Vue3.0新特性的解释和应用实例。他们介绍了Vue3.0相对于2.0的改进,例如Composition API和响应式系统的改进。通过学习Vue3.0,学习者可以更好地理解和应用最新的Vue技术。 总的来说,尚硅谷的Vue2.0Vue3.0全套教程是一套系统完备的学习材料,适合初学者和有一定经验的开发者。通过学习这些教程,学习者可以全面掌握Vue的核心知识和应用技巧,进一步提升自己在前端开发领域的能力。 ### 回答3: 尚硅谷提供了全套的Vue2.0Vue3.0教程,帮助学习者全面了解和掌握Vue的相关知识和技能。 Vue2.0教程涵盖了Vue基础知识、组件化开发、路由、状态管理、Vue-cli的使用等内容。学习者可以通过该教程了解Vue的基本概念、指令、组件以及如何构建单页应用等。在Vue2.0教程中,尚硅谷以清晰的讲解和示例代码,帮助学习者逐步掌握Vue的开发技巧和最佳实践。 而Vue3.0教程则介绍了Vue3.0的全新特性与改进,如响应式、组合式API、Teleport等。学习者可以通过该教程了解Vue3.0相较于Vue2.0的重大改变和优势,以及如何从Vue2.0迁移到Vue3.0。此外,尚硅谷还会通过实际项目案例和实践演练,帮助学习者更好地理解和应用Vue3.0的新特性。 尚硅谷的教程内容通常包括视频教学、教学文档、示例代码和练习题等资源,学习者可以通过这些资源系统地学习Vue的相关知识。此外,尚硅谷还提供在线答疑和讨论交流的平台,学习者可以在学习过程中随时获得帮助与指导。 总之,尚硅谷的Vue2.0Vue3.0全套教程是一门系统且综合的学习课程,通过学习这些教程,学员可以全面了解和掌握Vue的开发技术,并能够应用到实际项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值