关于vue3手写响应式原理解释

    class Dep {
            constructor() {
                this.subs = []
            }

            addSub(sub) {
                if (sub && (this.subs.indexOf(sub) === -1)) {
                    this.subs.push(sub)
                }
            }

            notify() {
                this.subs.length > 0 && this.subs.forEach(sub => {
                    sub.update()
                })
            }
        }
        Dep.depTarget = null;

        class Watcher {
            constructor(value, getter) {
                this.getter = getter
                this.value = this.get()
                this.val = value
            }

            get() {
                Dep.depTarget = this
                this.getter()
                Dep.depTarget = null
                return this.val
            }

            update() {
                this.value = this.get()
            }
        }

        const typeTo = (val) => Object.prototype.toString.call(val)

        function observe(obj) {
            let dep = new Dep()

            if (typeTo(obj) !== '[object Object]') {
                return null
            }

            return new Proxy(obj, {
                get(target, key, receiver) {
                    dep.addSub(Dep.depTarget)
                    return target[key];
                },
                set(target, key, value, receiver) {
                    let newValue = Reflect.set(target, key, value, receiver)
                    dep.notify()
                    return newValue;
                }
            })
        }

        class Vue {
            constructor(options) {
                this.$options = options;
                this._data = options.data();
                this.render = options.render;
                this.$el = typeof options.el === 'string' ?
                    document.querySelector(options.el) :
                    options.el;
                this.$data = observe(this._data)
                new Watcher(this._data, () => {
                    this.$mount()
                })
            }

            createElement(tagName, data, children) {
                let element = document.createElement(tagName)
                if (Object.prototype.toString.call(children) === '[object Array]') {
                    children.forEach(child => {
                        element.appendChild(child)
                    });
                } else {
                    element.textContent = children
                }
                return element
            }

            $mount() {
                const elements = this.render(this.createElement)
                this.$el.innerHTML = ''
                this.$el.appendChild(elements)
            }
        }

        window.app = new Vue({
            el: '#app',
            data() {
                return {
                    info: {
                        message: '个人信息'
                    },
                    age: 3
                }
            },
            render(createElement) {
                return createElement(
                    'div', {
                        attr: {
                            title: this.$data.info.message
                        }
                    },
                    [
                        createElement('span', {}, `黑宝(我家猫)快${this.$data.age}岁了`)
                    ]
                )
            }
        });

        setTimeout(() => {
            window.app.$data.info.message = 14;
            window.app.$data.age = 4;
            console.log('window.app._data.info.message: ', window.app._data.info.message)
        }, 1000)
        
        
        

上面是一位网友的vue3响应式原理手写代码,因为本人比较小白,有些地方不太了解什么意思,麻烦大神标记一下注释讲解一下,帮助入门。感谢

阅读 1.2k
1 个回答
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏