手写发布订阅模式实现数据响应

教程来源于黑马的柴柴老师:https://cp_fe.gitee.io/course-advance/#/
现在还没时间完善步骤,先把代码贴上

<!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>手写发布订阅</title>
</head>
<body>
    <div id="app">
        <p v-text="name"></p>
        <p v-text="age"></p>
        <p v-text="name"></p>
    </div>
    <script>
        let data = {
            name: '区泽熙',
            age: 22,
            height: 176
        }
        // 遍历每一个属性
        Object.keys(data).forEach((key)=>{
            // key 属性名
            // data[key] 属性值
            // data 源对象
            defineReactive(data,key,data[key])
        })
        function defineReactive(data,key,value){
            Object.defineProperty(data,key,{
                get(){
                    return value
                },
                set(newValue){
                    // 数据发生变化,操作dom进行更新
                    if(newValue === value) return
                    value = newValue
                    // 再次编译要放到新值已经变化之后只更新当前的key
                    dep.trigger(key)   
                    console.log(dep)
                }
            })
        }
        // 增加dep对象,用来收集依赖和触发依赖
        const dep = {
            map: Object.create(null),
            // 收集
            collect(dataProp, updateFn){
                if(!this.map[dataProp]) this.map[dataProp] = []
                this.map[dataProp].push(updateFn)
            },
            // 触发
            trigger(dataProp){
                this.map[dataProp] && this.map[dataProp].forEach(updateFn => updateFn())
            }
        }
        // 编译函数
        function compile(){
            let app = document.getElementById('app')
            // 拿到app下所有的子元素
            const nodes = app.childNodes // [text, p, text, p, text, p, text]
            // 遍历所有的子元素
            nodes.forEach(node => {
                // nodeType为1是元素节点,3是文本结点
                if(node.nodeType === 1){
                    const attrs = node.attributes
                    // 遍历所有的attributes找到 v-text
                    Array.from(attrs).forEach(attr => {
                        const dirName = attr.nodeName
                        const dataProp = attr.nodeValue
                        console.log(dirName,dataProp)
                        if(dirName === 'v-text'){
                            console.log(`更新了${dirName}指令,需要更新的属性为${dataProp}`);
                            node.innerText = data[dataProp]
                            // 收集更新函数
                            dep.collect(dataProp,()=>{
                                node.innerText = data[dataProp]
                            })
                        }
                    })
                }
            })
        }
        compile()
    </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值