六、vue底层原理——响应式

66 阅读1分钟

vue2

<body>
    <div id="app">
        用户名:<span class="username"></span><br/>
        密码:<span class="password"></span>
    </div>
    <script>
        const dataObj = {}        
        fnZ({
            objOrigin: dataObj,
            objKey: 'username',
            tag: 'tagA',
            selector: '.username'
        })
        fnZ({
            objOrigin: dataObj,
            objKey: 'password',
            tag: 'tagB',
            selector: '.password'
        })
        dataObj.username = 'zs'
        dataObj.password = '123456'
    </script>
</body>
// 订阅器
const Dep = {
    clientList: {},
    listen: function(key, fn) {
        (this.clientList[key] || (this.clientList[key] = [])).push(fn)
    },
    trigger: function() {
        const key = Array.prototype.shift.call(arguments)
        const fns = this.clientList[key]
        if (!fns || fns.length === 0) return false;
        for (let i = 0, fn; fn = fns[i++];) {
            fn.apply(this,arguments)
        }
    }
} 
const fnZ = function({objOrigin, objKey, tag, selector}) {
    let value = ''
    Object.defineProperty(objOrigin, objKey, {
        get: function() {
            return value
        },
        set: function(val) {
            value = val
            Dep.trigger(tag, val)
        }
    })
    // 用户先订阅一个到货通知,等货到了就可以加购物车,购买之类
    Dep.listen(tag, function(val) {
        document.querySelector(selector).innerText = val
    })
}

vue3

  const obj = {
            name: 'zs',
            age: 18
        }
        const p = new Proxy(obj, {
            get(target, propName) {
                return target[propName]
            },
            set(target, propName, value) {
                target[propName] = value
            },
            deleteProperty(target, propName) {
                return delete target[propName]
            }
        })