Vue-双向绑定笔记

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style>
</style>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <h1 id="name"></h1>
    <input type="text">
    <input type="button" value="改变data内容" onclick="changeInput()">
    <script type="text/javascript">
    let log = console.log.bind(console)
 
    // 数据观测
    function observe(obj){
        if( !obj || typeof obj !== 'object'){
            return 
        }
        let keys = Object.keys(obj)
        keys.forEach( key =>{
            observeable(obj, key, obj[key])
        })
        return obj
    }
 
    function observeable(obj, key, value){
        let dep =  new Dep()
        Object.defineProperty(obj, key, {
            get(){
                dep.depend()
                console.log(`${key}属性被读取了`);
                return value
            },
            set(newVal){
               value =  newVal
                console.log(`${key}属性被修改了`);
               dep.notify()
            }
        })
    }
 
 
    // 订阅收集器
    class Dep{
        constructor(){
            this.subs = []
        }
        depend(){
            if( Dep.target ){
                this.addSub(Dep.target)
            }
        }
        addSub(target){
            this.subs.push(target)
        }
        notify(){
            this.subs.forEach(sub =>{
                sub.update()
            })
        }
    }
    Dep.target = null
 
    
    // 订阅者
    class Watcher{
        constructor(vm, exp, cb){
            this.vm = vm     // vm实例对象
            this.exp = exp   // 绑定的属性
            this.cb = cb     // 数据变化的回调函数
            this.value = this.get()
 
        }
        update(){
            let newVal = this.vm.date[this.exp]
            let oldVal = this.value
            if( newVal !== oldVal){
                this.value = newVal
               this.cb.call(this.vm, newVal, oldVal) 
            }
        }
        get(){
            Dep.target = this
            let value = this.vm.date[this.exp]
            Dep.target = null
            return value
        }
    }
 
    function MyVue(date, ele, exp){
 
        this.date = date
        // 数据可观测性
        observe(this.date)
        log(this.date)
        // 初始化数据
        ele.innerHTML  = this.date[exp]
        // 订阅者绑定
        new Watcher(this, exp, function(val){
            ele.innerHTML = val
        })
        return this
    }
 
    let ele = document.querySelector('#name');
    let input = document.querySelector('input');
 
    let myVue = new MyVue({
        name: '初始化数据'
    }, ele, 'name')
 
    // 改变输入框
    input.oninput = function(e){
        log(myVue)
        myVue.date.name = e.target.value
    }
 
    // 修改date内容
    function changeInput(){
        log(myVue)
        myVue.date.name = '修改date内容'
    }    
    </script>
</body>
</html>

参考地址:
https://www.jianshu.com/p/5990a386132a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值