百度前端學院學習:動態數據綁定(二)

題目地址
源代碼地址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
      }
    */
相關文章
相關標籤/搜索