vue 框架实现

1. 原理

1.1 defineReactive简单版

利用Object.defineProperty() 实现数据的响应,注意需要用一个temp把 值存起来


let temp; 
let obj = {a:1}
defineReactive(obj,"a")
function defineReactive(obj,key) {
    Object.defineProperty(obj,key,{
        get () {
            console.log("调用get方法,temp",temp)
            // console.log("obj[key]",obj[key]) //为什么不直接用 obj[key] 因为又会死循环重复调用get 
            return temp
        },
        set (val) {
            console.log("调用set方法,val",val)
            temp = val
            return 
        }
    })
}

obj.a
obj.a = 2
obj.a

//调用get方法,temp undefined
//调用set方法,val 2
//调用get方法,temp 2
复制代码

1.2 defineReactive闭包版

方法参数再方法体内被返回,形成闭包

let obj = {}
defineReactive(obj,"a",'1')
function defineReactive(obj,key,val) {
    Object.defineProperty(obj,key,{
        get () {
            console.log("调用get方法,val",val) 
            return val //直接返回 参数val 形成闭包
        },
        set (newVal) {
            console.log("调用set方法,newVal",newVal)
            if(val === newVal) {
                return
            }
            val = newVal
            return 
        }
    })
}

obj.a
obj.a = 2
obj.a

// 调用get方法,val 1
// 调用set方法,newVal 2
// 调用get方法,val 2
复制代码

1.3. 简单的页面响应

简单html定时自动数据响应刷新

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">

    </div>
    
    <script> 
let obj = {}
defineReactive(obj,"a",'1')
function defineReactive(obj,key,val) {
    Object.defineProperty(obj,key,{
        get () {
            console.log("调用get方法,val",val) 
            return val //直接返回 参数val 形成闭包
        },
        set (newVal) {
            if(val === newVal) {
                return
            }
            console.log("调用set方法,newVal",newVal)
            val = newVal
            updateFn()
        }
    })
}

let app = document.getElementById("app")
function updateFn() { 
    app.innerHTML = obj.a
}
setInterval(() => {
    obj.a = new Date().toLocaleTimeString();
}, 1000);
    </script>
</body>
</html>
复制代码

1.4. 遍历所有属性

//观察方法
function observe(obj) {
    if (typeof obj !== "object" || obj == null) {
        return 
    }
    Object.keys(obj).forEach( k => { 
        defineReactive(obj,key,obj[key])
    })
}
复制代码

1.5. 遍历所有属性

//观察方法
function observe(obj) {
    if (typeof obj !== "object" || obj == null) {
        return 
    }
    Object.keys(obj).forEach( key => { 
        defineReactive(obj,key,obj[key])
    })
}
复制代码

1.6. 解决嵌套对象问题

function defineReactive(obj, key, val) {
    observe(val) //判断值是不是也是对象 递归调用
}
复制代码

1.7. 插入值是对象处理

set(newVal) {
    if (newVal !== val) {
        observe(newVal) // 赋值的时候也调用一下 
        ...
     }
 }

// vue的set方法就是这个原理
function set(obj, key, val) {
    defineReactive(obj, key, val) 
}
复制代码

2. 实战

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享