成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Vue響應(yīng)式原理-排除所有優(yōu)化,只看核心

xumenger / 2075人閱讀

摘要:響應(yīng)式原理作為寫業(yè)務(wù)的碼農(nóng),幾乎不必知道原理。所以找工作之前可以先復(fù)習(xí)下,只要是關(guān)于的,必定會(huì)問響應(yīng)式原理。如果是,運(yùn)行其方法,其方法中含有的值時(shí),會(huì)觸發(fā)收集當(dāng)更新時(shí),也會(huì)觸發(fā)更新重新獲取值如果是會(huì)觸發(fā)的函數(shù)響應(yīng)式原理計(jì)算屬性值這是

Vue響應(yīng)式原理

作為寫業(yè)務(wù)的碼農(nóng),幾乎不必知道原理。但是當(dāng)你去找工作的時(shí)候,可是需要造原子彈的,什么都得知道一些才行。所以找工作之前可以先復(fù)習(xí)下,只要是關(guān)于vue的,必定會(huì)問響應(yīng)式原理。

核心:

//es5
Object.defineProperty(obj,key,{
    get() {
        // 獲取obj[key]的時(shí)候觸發(fā)
    },
    set(val) {
       // obj[key] = "xxx"時(shí)觸發(fā)
    }
})

其實(shí),只需要在修改data值的時(shí)候,需要觸發(fā)一個(gè)回調(diào)方法,來更新與此值有關(guān)的數(shù)據(jù),就完了。但是你面試的時(shí)候,那些大佬可不會(huì)覺得是這樣的,需要把整個(gè)流程說明白才行。

簡(jiǎn)單的Vue響應(yīng)式代碼如下: Vue.js:
class Vue {
  constructor(opts) {
    this.opts = opts
    if (opts.data) this.initData(opts.data);
    if (opts.watch) this.initWatch(opts.watch);
    if (opts.computed) this.initComputed(opts.computed);
    if (opts.el) this.$mount(opts.el)
  }
  initData(data) {
    // 讓data上的數(shù)據(jù)被get的時(shí)候能夠搜集watcher,data變?yōu)橛^察者
    new Observable(data);
    this.data = data
    // 數(shù)據(jù)可在this上直接讀取
    Object.keys(data).forEach(key => {
      this.proxy(key)
    })
  }

  initWatch(watch) {
    Object.keys(watch).forEach(key => {
      // 
      new Watcher(this, key, watch[key])
    })
  }
  initComputed(data) {
    Object.keys(data).forEach(key => {
      new Watcher(this, key)
      this.proxy(key, {
        get: data[key],
      })
    })

  }

  $mount(el) {
    el = document.querySelector(el)
    this.template = el.innerHTML

    this.el = el
    const fn = _ => {
      const nwTemp = this.parseHTML(this.template)
      this.el.innerHTML = nwTemp
      if(this.opts.mounted) {
        this.opts.mounted.call(this)
      }
    }
    new Watcher(this, fn)
  }
  parseHTML(template) {

    return template.replace(/{{(.*?)}}/g, (str, str1) => {
      return this[str1.trim()]
    })
  }


  // 將數(shù)據(jù)直接掛到this上,使用getterSetter代理,獲取vm.data上的值
  proxy(key, getterSetter) {
    const vm = this
    getterSetter = getterSetter || {
      set(value) {
        vm.data[key] = value
      },
      get() {
        return vm.data[key]
      }
    }
    Object.defineProperty(vm, key, getterSetter)
  }
}
// 給data作為觀察者用的
class Observable {
  constructor(obj) {

    Object.keys(obj).forEach(key => {
      this.defineReact(obj, key, obj[key])
    });
  }

  defineReact(obj, key, value) {
  
    const dep = new Dep()
    Object.defineProperty(obj, key, {
      get() {
        // 獲取data里面信息的時(shí)候,能夠搜集依賴,這些依賴都是watcher實(shí)例
        if (Dep.target) {
          dep.append(Dep.target)
        }
        return value
      },
      set(val) {
        value = val
        // 修改data里面數(shù)據(jù)的時(shí)候,去通知已搜集的依賴更新
        dep.notify()
      }
    })
  }

}

// 搜集與觸發(fā)wacher
class Dep {

  constructor() {
    this.subs = []
  }
  append(watcher) {
    // 避免重復(fù)添加watcher
    // watcher 在update的時(shí)候,會(huì)重新獲取值,此時(shí)不必再添加
    if(this.subs.includes(watcher)) return
    this.subs.push(watcher)
  }
  notify() {
    this.subs.forEach(watcher => {
      watcher.update()
    })
  }
}
Dep.target = null


class Watcher {
  // keyOrFn 為字符串或者function,opts.watch為字符串,computed,$mount中為function
  constructor(vm, keyOrFn, cb) {
    this.cb = cb
    if (typeof keyOrFn === "string") {
      this.getter = function () {
        return vm[keyOrFn] // 例:initWatch時(shí),watch:{a(){}} ,a為data里的數(shù)據(jù),此處獲取vm.a會(huì)觸發(fā)a的收集
      }
    } else {
      
      this.getter = keyOrFn // 如果為fn(computed中)值為此函數(shù)的返回值
    }

    this.value = this.get()
  }
  get() {
    Dep.target = this // 此watcher記錄下來
    const value = this.getter(this.vm)
     // 運(yùn)行g(shù)etter,如果是watch,獲取一次data里的值,完成收集。
     // 如果是computed,運(yùn)行其方法,其方法中含有data的值時(shí),會(huì)觸發(fā)收集
    // 當(dāng)更新時(shí),也會(huì)觸發(fā)getter
     Dep.target = null 
    return value
  }

  update() {
    // 更新
    const oldValue = this.value
    // 重新獲取值
    this.value = this.get()
    if (this.cb) {
      //如果是watch,會(huì)觸發(fā)watch的函數(shù)
      this.cb.call(this.vm, this.value, oldValue)
    }
  }
}
index.html
  

Vue響應(yīng)式原理


msg: {{ msg }}

num: {{ num }}

num+1計(jì)算屬性值:{{ add1 }}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104174.html

相關(guān)文章

  • 前端每周清單第 34 期:Vue 現(xiàn)狀盤點(diǎn)與 3.0 展望,React 代碼遷移與優(yōu)化,圖片優(yōu)化詳論

    摘要:工程實(shí)踐立足實(shí)踐,提示實(shí)際水平內(nèi)聯(lián)函數(shù)與性能很多關(guān)于性能優(yōu)化的文章都會(huì)談及內(nèi)聯(lián)函數(shù),其也是常見的被詬病為拖慢性能表現(xiàn)的元兇之一不過本文卻是打破砂鍋問到底,論證了內(nèi)聯(lián)函數(shù)并不一定就會(huì)拖慢性能,過度的性能優(yōu)化反而會(huì)有損于應(yīng)用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...

    CoderStudy 評(píng)論0 收藏0
  • 深入學(xué)習(xí)Vuex

    摘要:深入學(xué)習(xí)作為配合使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。至此,構(gòu)造函數(shù)部分已經(jīng)過了一遍了。 深入學(xué)習(xí)Vuex vuex作為配合vue使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。本文以使用者的角度,結(jié)合源碼來學(xué)習(xí)vuex。其中也參考了許多前輩的文章,參見最后的Reference Vue加載Vuex...

    codercao 評(píng)論0 收藏0
  • 深入學(xué)習(xí)Vuex

    摘要:深入學(xué)習(xí)作為配合使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。至此,構(gòu)造函數(shù)部分已經(jīng)過了一遍了。 深入學(xué)習(xí)Vuex vuex作為配合vue使用的數(shù)據(jù)狀態(tài)管理庫(kù),針對(duì)解決兄弟組件或多層級(jí)組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。本文以使用者的角度,結(jié)合源碼來學(xué)習(xí)vuex。其中也參考了許多前輩的文章,參見最后的Reference Vue加載Vuex...

    funnyZhang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<