vue3-reactive的实现原理

实现reactive的数据劫持功能

项目结构
vue3-reactive的实现原理_第1张图片

vue3/index.js

import {
     reactive} from './vue3/reactivity'
const state = reactive({
     
    title: '零三',
    numArr: [1,2,3],
    strArr: ['vue','react','html'],
    objArr: [
        {
     
            name: 'mike',
            hobby: ['足球','篮球','code'],
            skill: [
                {
     
                    text: '吹牛皮',
                    lv: 3
                },
                {
     
                    text: '撩妹',
                    lv: 0
                }
            ]
        }
    ]
})
// 直接获取
// console.log('-----state.title-----')
// console.log(state.title)

// 先获取state.objArr再取值[0]获取hobby
// console.log('-----state.objArr[0].hobby-----')
// console.log(state.objArr[0].hobby)

// 先获取state.objArr再取值[0]获取hobby[0]
// console.log('-----state.objArr[0].hobby[0]-----')
// console.log(state.objArr[0].hobby[0])

// push不会出发设置
// console.log('-----state.objArr[0].skill.push( {\n' +
//     '    text: \'吃吃吃\',\n' +
//     '    lv: 6\n' +
//     '})-----')
// state.objArr[0].skill.push( {
     
//     text: '吃吃吃',
//     lv: 6
// })
// console.log(state)

//数组方法不会触发设置
// console.log('-----state.objArr[0].skill.splice(1,0)-----')
// console.log(state.objArr[0].skill.splice( 1,1))
// console.log(state.objArr[0].skill)


// 直接设置 触发修改
// console.log('-----state.title=零零三-----')
// state.title = '零零三'

// 设置一个不存在的对象,触发新增
console.log('-----state.title=零零三-----')
state.url = 'web03.cn'
// 触发修改 被新增的也是响应式的
state.url = 'https://web03.cn'

// 设置相同的基本类型数据 不会触发新增和修改
console.log('-----state.title=零零三-----')
state.title = '零三'

vue3/reactivity/index.js

import {
     reactive} from './reactive'
export {
     
    reactive
}

vue3/reactivity/reactive.js

import {
     isObject} from "./shared/utils";
import {
     mutableHandle} from  './mutableHandle'
function reactive(target) {
     
    return createReactiveObject(target, mutableHandle)
}
function createReactiveObject(target,baseHandler) {
     
    if (!isObject(target)){
     
        return target;
    }
    return new Proxy(target, baseHandler);
}
export {
     
    reactive
}

vue3/reactivity/mutableHandle.js

import {
     isObject, hasOwnProperty, isEqual} from "./shared/utils";
import {
     reactive} from './reactive'
const get = createGetter();
const set = createSetter();
function createGetter() {
     
    return function get(target, key, receiver) {
     
        const res = Reflect.get(target,key,receiver);
        console.log('响应式获取',target[key])
        // 如果还是obj,继续进行响应式设置
        if (isObject(res)){
     
            reactive(res)
        }
        return res;
    }
}
function createSetter() {
     
    return function set(target, key, value, receiver) {
     
        const isKeyExist = hasOwnProperty(target,key),
            oldValue = target[key],
            res = Reflect.set(target, key, value, receiver);
        // 是否存在 新老value是否一样
        if (!isKeyExist){
     
            // 新增
            console.log('响应式新增','value='+value);
        } else if (!isEqual(value,oldValue)){
     
            // 修改
            console.log('响应式修改','key='+key,'value='+value);
        }
        return res;
    }
}
const mutableHandle =  {
     
    get,
    set
}
export {
     
    mutableHandle
}

vue3/reactivity/shared/utils.js

function isObject(value) {
     
    return typeof value === 'object' && value !== null;
}
// 判断是否存在
function hasOwnProperty(target,key) {
     
    return Object.prototype.hasOwnProperty.call(target,key);
}
// 是否相等
function isEqual(newValue,oldValue) {
     
    return newValue === oldValue;
}
export {
     
    isObject,
    hasOwnProperty,
    isEqual
}

实现原理和vue2的数据劫持相差不大,vue2使用Object.defineProperty需要处理数组方法,vue使用Proxy和Reflect,省去了很多不必要的操作

流程图

vue3-reactive的实现原理_第2张图片

你可能感兴趣的:(笔记,vue3)