百度前端学院学习:动态数据绑定(二)

题目地址
源代码地址git

处理深度对象

题目有个要求是若是传入的对象是比较深的对象,也就是 value 能够能是另一个新的对象,也是要给那个对象的属性加上 getter 和 setter 的,个人作法就是判断每个值是不是对象,而后在作一次递归处理。github

each(obj) {
  Object.keys(obj).forEach(key => {
    // 若是值是一个对象的话
    if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
      // 递归自身
      this.each(obj[key])
    } else {
      this.convert(key, obj[key])
    }
  })
}

这里用了Object.prototype.toString.call()来判断值是什么类型,由于使用typeof的话,object、array 和 null 都会返回 object,不是我想要的结果。json

实现 $watch

题目还有另一个要求就是实现$watch的功能,用过 Vue 的同窗都知道,咱们能够用这个函数去监听一个值的变化,而且传入一个回调函数,若是值发生变话的话,就执行回调函数。app

constructor中添加一个用来存储回调函数的变量:函数

...
this.watchProperties = {}
...

实现$watchemit函数:this

存储 watch 的回调函数作法我是用一个对象去处理的,key 为属性名,value 则是回调函数。prototype

$watch(name, fn) {
  this.watchProperties[name] = fn
}

emit(name, val) {
  if (this.watchProperties[name] && typeof this.watchProperties[name] === 'function') {
    this.watchProperties[name](val)
  }
}

convert中添加:code

convert(key, value) {
    ...
    Object.defineProperty(this.setData || this.data, key, {
      ...
      set: function (newValue) {
        ...
        // 调用 emit 执行 watchProperties 里的回调函数
        // key 为属性名
        // newValue 为新设置的值
        that.emit(key, newValue)
        ...
      }
    })
  }

最后一步,暴露$watch方法:server

constructor(json) {
    ...
    return {
      ...
      // 这里要注意,修改一下上下文的环境
      $watch: this.$watch.bind(this)
    }
  }

这里须要使用bind去修改执行的时候上下的环境,不然没法访问watchProperties对象

还没完成的功能

  • $watch函数不可以监听比较深的对象的属性。

  • 新建一个示例的时候,若是传入一个深对象,会被打平:

    let app = new Observer({
      name: {
        a: 1,
        b: 2
      }
    })
    
    console.log(app.data)
    // 会输出
    /*
      [object Object] {
        a: 1,
        b: 2
      }
    */
相关文章
相关标签/搜索