Vue的响应式原理

vue响应式原理的关键技术

1,通过Object.defineProperty()监听data中的数据变化(Observer),在vue3中使用的ES6的proxy
2,使用发布者订阅模式,Dep(发布者)存放Watcher对象,Watcher(订阅者)
3,对html中{{}}命令进行解析(Compiler)

创建vue之后执行的操作

1, data被传入Observer中进行keyvalue解析出来,使用defineProperty监听value的改变,如果改变执行Dep中的notify方法,把观察者(Watcher)全部更新,如果是获取,就把每个相对应的Watcher放入Dep.subs中
2, el会被传入Compiler中,进行命令的解析,并创建每个命令对应的Watcher

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<style>

</style>
<body>
    <div id="app">
        <input type="text" name="" v-model='message'>
        {{message}}
    </div>
<script>
    class Vue {
        constructor(options) {
            //保存传入的数据
            this.$options = options
            this.$data = options.data
            this.$el = options.el

            //进行数据的监听改变
            new Observer(this.$data,this.$el)

            //进行html中{{}}解析命令
            new Compiler(this.$el,this)
        }
    }

    //data数据监听改变类
    class Observer {
        constructor(data,el) {
            this.data = data
            this.el = document.querySelector(el)
            // let child = this.el.firstChild

            //循环拿所有key和value
            Object.keys(this.data).forEach(key => {
                //进行监听
                this.defineReactive(this.data,key,this.data[key])
            })
        }
        defineReactive(data,key,val) {
            const dep = new Dep()
            Object.defineProperty(data,key,{
                enumerable: true,
                configurable: true,
                set(newValue) {
                    if(newValue === val) {
                        return
                    }
                    val = newValue
                    dep.notify()
                },
                get() {
                    if(Dep.target) {
                        dep.addSub(Dep.target)
                    }
                    return val
                }
            })
        }
    }

    //发布者订阅模式
    class Dep {
        constructor() {
            this.subs = []
        }
        addSub(name) {
            this.subs.push(name)
        }
        //通知所有Watcher更新数据
        notify() {
            this.subs.forEach(item => {
                item.upData()
            })
        }
    }
    const reg = /\{\{(.+)\}\}/
    //html中{{}}命令解析
    class Compiler {
        constructor(el,vm) {
            this.el = document.querySelector(el)
            this.vm = vm    //指向Vue

            this.flag = this._createFragment()

            this.el.appendChild(this.flag)

        }

        _createFragment() {
            //创建一个文档片段
            let flag = document.createDocumentFragment()

            let child
            // console.log(this.el.firstChild)

            while(child = this.el.firstChild) {
                this._compiler(child)
                
                flag.appendChild(child)
            }
            return flag
        }
        _compiler(node) {
            //单向绑定
            if(node.nodeType === 1) {
                let attrs = node.attributes
                if(attrs.hasOwnProperty('v-model')) {
                    let name = attrs['v-model'].nodeValue
                    node.addEventListener('input',e => {
                        this.vm.$data[name] = e.target.value
                    })
                }
            }
            if (node.nodeType === 3) {
                if(reg.test(node.nodeValue)) {
                    const name = RegExp.$1.trim()
                    new Watcher(node,name,this.vm)
                }
            }
        }
    }

    //监听对象
    class Watcher {
        constructor(node,name,vm) {
            this.node = node
            this.name = name
            this.vm = vm

            Dep.target = this
            this.upData()
        }
        //数据更新
        upData() {
            this.node.nodeValue = this.vm.$data[this.name]
        }
    }
    
    const app = new Vue({
        el:'#app',
        data: {
            message:'张三',
            name:'里斯'
        }
    })
</script>

</body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容