美文网首页
动态数据绑定(二)

动态数据绑定(二)

作者: 不系流年系乾坤 | 来源:发表于2017-09-20 19:37 被阅读6次

    动态数据绑定(一)

    vue早期源码学习系列之一:如何监听一个对象的变化

    方法一

    // 观察者构造函数
    function Observer(data) {
      this.data = data;
      this.walk(data)
    }
    
    let p = Observer.prototype;
    
    // 此函数用于深层次遍历对象的各个属性
    // 采用的是递归的思路
    // 因为我们要为对象的每一个属性绑定getter和setter
    p.walk = function(obj) {
      let val;
      for (let key in obj) {
        // 这里为什么要用hasOwnProperty进行过滤呢?
        // 因为for...in 循环会把对象原型链上的所有可枚举属性都循环出来
        // 而我们想要的仅仅是这个对象本身拥有的属性,所以要这么做。
        if (obj.hasOwnProperty(key)) {
          val = obj[key];
    
          // 这里进行判断,如果还没有遍历到最底层,继续new Observer
          if (typeof val === 'object') {
            new Observer(val);
          }
    
          this.convert(key, val);
        }
      }
    };
    
    p.convert = function(key, val) {
      Object.defineProperty(this.data, key, {
        enumerable: true,
        configurable: true,
        get: function() {
          console.log('你访问了' + key);
          return val
        },
        set: function(newVal) {
          console.log('你设置了' + key);
          console.log('新的' + key + ' = ' + newVal)
          if (newVal === val) 
            return;
          val = newVal
          if(typeof val === "object"){
            new Observer(val);
          }
        }
      })
    };
    
    let data = {
      user: {
        name: "liangshaofeng",
        age: "24"
      },
      address: {
        city: "beijing"
      }
    };
    
    let app = new Observer(data);
    app.data.user.name 
    app.data.user = {
      job: 'front-end'
    }
    app.data.user.job
    app.data.user.job = 'back-end'
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <textarea style="width: 800px;height: 600px;">
            var app1 = new Observer({
                name: 'youngwind',
                age: 25,
                edu: {
                    university: 'bupt',
                    major: 'computer'
                }
            });
            
            var app2 = new Observer({
              university: 'bupt',
              major: 'computer'
            });
            
            // 要实现的结果如下:
            app1.data.name // 你访问了 name
            app1.data.age = 100;  // 你设置了 age,新的值为 100
            app1.data.edu.university;  // 你访问了 edu  你访问了 university
            app1.data.edu.major = 'science';  // 你访问了 edu  你设置了 major,新的值为 science
            app1.data.edu = {
                university: 'cnu',
                major: 'core'
            };  // 你设置了 edu,新的值为 {university: 'cnu',major: 'core'}
            app1.data.edu.university;  // 你访问了 edu  你访问了 university
            app1.data.edu.major = 'science';  // 你访问了 edu  你设置了 major,新的值为 science
            
            app2.data.university // 你访问了 university
            app2.data.major = 'science'  // 你设置了 major,新的值为 science
        </textarea>
    <button>运行一下</button>
    <script>
    class  Observer {
        constructor(obj){
            this.data = Observer.observer(obj);
        }
        static observer(obj) {
            let res = {};
            for(let key in obj){
                if(typeof obj[key] === 'object')
                    res[key] = Observer.observer(obj[key])
            }
            return new Proxy(res, {
                get: (target, prop, receiver) => {
                    console.log('你访问了 ' + prop);
                    return Reflect.get(target, prop, receiver);
                },
                set: (target, prop, value, receiver) => {
                    if(typeof value === 'object'){
                        console.log('你设置了 ' + prop + ', 新的值为 ' + JSON.stringify(value))
                        value = Observer.observer(value);
                    } else {
                        console.log('你设置了 ' + prop + ', 新的值为' + value)
                    }
                    return Reflect.set(target, prop, value, receiver);
                }
            })
        }
    } 
    console.log = new Proxy(console.log, {
        apply: (target, thisArg, argumentsList) => {
            alert(argumentsList);
            return Reflect.apply(target, thisArg, argumentsList)
        }
    })
    
    window.onload = function() {
        document.querySelector('button').onclick = function() {
            eval(document.querySelector('textarea').value);
        }
    }
    </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题: 动态数据绑定(二)

          本文链接:https://www.haomeiwen.com/subject/qrzosxtx.html