zoukankan      html  css  js  c++  java
  • vue数据双向绑定原理

    vue的数据双向绑定的小例子:

    。html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset=utf-8>
        <title>vue数据双向绑定原理</title>
    </head>
    <body>
        <h1 id="name"><<<<name>>>>>></h1>
    </body>
    <script src="testvuejs/observer.js"></script>
    <script src="testvuejs/watcher.js"></script>
    <script src="testvuejs/index.js"></script>
    <script type="text/javascript">
        var ele = document.querySelector('#name');
        var selfVue = new SelfVue({
            name: 'hello world'
        }, ele, 'name');
        window.setTimeout(function () {
            console.log('name值改变了');
            selfVue.name = 'canfoo';
        }, 2000);
    </script>
    </html>

    index.js

    function SelfVue (data, el, exp) {
        var self = this;
        this.data = data;
    
        //把data里的key直接绑定到this对象上
        Object.keys(data).forEach(function(key) {
            self.proxyKeys(key);
        });
    
        //对data的每一层级的属性进行监听,如果变化执行notify
        observe(data);
    
        // 初始化模板数据的值
        el.innerHTML = this.data[exp];  
        
        new Watcher(this, exp, function (value) {
            el.innerHTML = value;
        });
        return this;
    }
    
    SelfVue.prototype = {
        proxyKeys: function (key) {
            Object.defineProperty(this, key, {
                enumerable: false,
                configurable: true,
                get: ()=> {
                    return this.data[key];
                },
                set: (newVal)=> {
                    this.data[key] = newVal;
                }
            });
        }
    }

    observer.js

    function Observer(data) {
        this.data = data;
        this.walk(data);
    }
    Observer.prototype = {
        walk: function(data) {
            var self = this;
            Object.keys(data).forEach(function(key) {
                self.defineReactive(data, key, data[key]);
            });
        },
        defineReactive: function(data, key, val) {
            var dep = new Dep();
            //对二级三级子属性...进行监听尽
            observe(val);
            Object.defineProperty(data, key, {
                enumerable: true,
                configurable: true,
                get: function() {
                    if (Dep.target) {
                        dep.addSub(Dep.target);
                    }
                    return val;
                },
                set: function(newVal) {
                    if (newVal === val) {
                        return;
                    }
                    val = newVal;
                    dep.notify();
                }
            });
        }
    };
    
    function observe(value, vm) {
        if (!value || typeof value !== 'object') {
            return;
        }
        return new Observer(value);
    };
    
    function Dep () {
        this.subs = [];
    }
    Dep.prototype = {
        addSub: function(sub) {
            this.subs.push(sub);
        },
        notify: function() {
            this.subs.forEach(function(sub) {
                sub.update();
            });
        }
    };
    Dep.target = null;

    watcher.js

    function Watcher(vm, exp, cb) {
        this.cb = cb;
        this.vm = vm;
        this.exp = exp;
        //当new一个对象的时候,立即执行get方法,Dep的target为Watcher自己
        this.value = this.get();  // 将自己添加到订阅器的操作
    }
    
    Watcher.prototype = {
        update: function() {
            this.run();
        },
        run: function() {
            var value = this.vm.data[this.exp];
            var oldVal = this.value;
            if (value !== oldVal) {
                this.value = value;
                this.cb.call(this.vm, value);
            }
        },
        get: function() {
            Dep.target = this;  // 缓存自己
            var value = this.vm.data[this.exp]  // this.vm.data[this.exp]:强制执行监听器里的get函数,使自己(Watcher {cb: ƒ, vm: SelfVue, exp: "name"})被添加上
            Dep.target = null;  // 释放自己
            return value;
        }
    };

    原理:当new vue后,将data属性直接给vm添加上,将属性的每一级进行set get 当set新值时通知notify函数。执行 new watcher ,强制执行data的get 使watch被添加上。

    当data set新值时,触发notify函数,使所有watcher都执行update,watcher的update时,本地的value是旧值,取新值,回调函数更新view。

  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/wulinzi/p/10408287.html
Copyright © 2011-2022 走看看