數據監聽--watch實現(簡易版)

watch 監聽數據變化

使用這個屬性,能夠監視 data 中指定數據的變化,而後觸發這個 watch 中對應的 function 處理函數函數

基本思路 --- Object.defineProperty()

getter:當獲取(get)一個對象的某個屬性時執行的方法ui

setter:當設置(set)一個對象的某個屬性時執行的方法this

getter 和 setter 不須要咱們手動去調用,只要咱們對這個數據進行了操做,那這連個方法就會自動調用spa

(function () {
            var o = { a: 1}
            Object.defineProperty(o, 'b', {
                get: function() {
                    console.log('get') // 只有調用o.b時纔會輸出get
                    return this.a
                },
                set: function(val) {
                    this.a = val
                },
                configurable: true
            })
            // 此處雖然調用o.b,輸出的倒是o.a的值
            console.log('a', o.a, 'b', o.b);  // a 1 b 1
            o.b = 2  // 給o.b賦值,實際上是賦值給了o.a
            console.log(o.a)  // 2
            // o始終只有a一個屬性
            console.log(o)   // {a: 2}
        })()
複製代碼

實現watch

// 定義watcher對象
        class watcher {
          constructor (opts) {
            this.$data = this.getBaseType(opts.data) === 'Object' ? opts.data : {}
            this.$watch = this.getBaseType(opts.watch) === 'Object' ? opts.watch : {}
            
            console.log(opts.data, opts.watch)
            // 遍歷data的全部屬性
            for (let key in opts.data) {
              console.log('key', key)  // key a key b
              this.setData(key, opts.data[key])
            }
          }
        
          getBaseType (target) {
            // 判斷取數據類型
            const typeStr = Object.prototype.toString.call(target)
            return typeStr.slice(8, -1)
          }
        
          setData(_key, _value) {
            console.log(_key, _value)  // a 0 b hello
            // this: Object.defineProperty(this) 把上下文指向當前的對象
            Object.defineProperty(this, _key, {
              get: function () {
                console.log(_key)    // b a
                return this.$data[_key]
              },
              // val是新的值
              set: function (val) {
                console.log('val', val, '_value', _value);   // val 7 _value 0
                const oldVal = this.$data[_key]
                if (oldVal === val) return val  // 值相同,不更新
                this.$data[_key] = val  // 更新
                console.log(_key, this.$data[_key])  // a 7
                this.$watch[_key] && typeof this.$watch[_key] === 'function' && this .$watch[_key].call(this, val, oldVal)
                return val
              }
            })
          }
        }
        
        let vm = new watcher({
          data: {
            a: 0,
            b: 'hello'
          },
          watch: {
            // 處理函數
            // 一旦data.a的值發生改變則執行watch[a]()
            a(newVal, oldVal) {
              console.log('new', newVal, 'old', oldVal)  // new 7 old 0
            }
          }
        })
        
        console.log(vm.b)    // hello
        
        setTimeout(() => {
          console.log(vm.a = 7)  // 7
          console.log('vm.a', vm.a)  // vm.a 7
        }, 3000)
複製代碼
輸出:
    { a: 0, b: 'hello' } { a: [Function: a] }
    key a
    a 0
    key b
    b hello
    b
    hello
    ------------- 3s後 -------------
    val 7 _value 0
    a 7
    new 7 old 0
    7
    a
    vm.a 7複製代碼
相關文章
相關標籤/搜索