最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析vue 函數(shù)配置項watch及函數(shù) $watch 源碼分享

 更新時間:2018年11月22日 14:34:12   作者:moderiona  
這篇文章主要介紹了vue 函數(shù)配置項watch及函數(shù) $watch 源碼分享 ,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下

Vue雙向榜單的原理

大家都知道Vue采用的是MVVM的設(shè)計模式,采用數(shù)據(jù)驅(qū)動實現(xiàn)雙向綁定,不明白雙向綁定原理的需要先補(bǔ)充雙向綁定的知識,在watch的處理中將運(yùn)用到Vue的雙向榜單原理,所以再次回顧一下:

Vue的數(shù)據(jù)通過Object.defineProperty設(shè)置對象的get和set實現(xiàn)對象屬性的獲取,vue的data下的數(shù)據(jù)對應(yīng)唯一 一個dep對象,dep對象會存儲改屬性對應(yīng)的watcher,在獲取數(shù)據(jù)(get)的時候為相關(guān)屬性添加具有對應(yīng)處理函數(shù)的watcher,在設(shè)置屬性的時候,觸發(fā)def對象下watcher執(zhí)行相關(guān)的邏輯

// 為data的的所有屬性添加getter 和 setter
function defineReactive( obj,key,val,customSetter,shallow
) {
  //
  var dep = new Dep();
  /*....省略部分....*/
  var childOb = !shallow && observe(val); //為對象添加備份依賴dep
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      var value = getter ? getter.call(obj) : val;
      if (Dep.target) {
        dep.depend(); // 
        if (childOb) {
          childOb.dep.depend(); //依賴dep 添加watcher 用于set ,array改變等使用
          if (Array.isArray(value)) {
            dependArray(value);
          }
        }
      }
      return value
    },
    set: function reactiveSetter(newVal) {
      var value = getter ? getter.call(obj) : val;
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if ("development" !== 'production' && customSetter) {
        customSetter();
      }
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      childOb = !shallow && observe(newVal);
      dep.notify();//有改變觸發(fā)watcher進(jìn)行更新
    }
  });
} 

在vue進(jìn)行實例化的時候,將調(diào)用 initWatch(vm, opts.watch);進(jìn)行初始化watch的初始化,該函數(shù)最終將調(diào)用 vm.$watch(expOrFn, handler, options) 進(jìn)行watch的配置,下面我們將講解 vm.$watch方法

Vue.prototype.$watch = function (
      expOrFn,
      cb,
      options
    ) {
      var vm = this;
      if (isPlainObject(cb)) {
        return createWatcher(vm, expOrFn, cb, options)
      }
      options = options || {};
      options.user = true;
      //為需要觀察的 expOrFn 添加watcher ,expOrFn的值有改變時執(zhí)行cb,
      //在watcher的實例化的過程中會對expOrFn進(jìn)行解析,并為expOrFn涉及到的data數(shù)據(jù)下的def添加該watcher
      var watcher = new Watcher(vm, expOrFn, cb, options);
      //immediate==true 立即執(zhí)行watch handler
      if (options.immediate) { 
        cb.call(vm, watcher.value);
      }
      //取消觀察函數(shù)
      return function unwatchFn() {
        watcher.teardown();
      }
    };

來看看實例化watcher的過程中(只分享是觀察函數(shù)中的實例的watcher)

var Watcher = function Watcher(
    vm,
    expOrFn,
    cb,
    options,
    isRenderWatcher
  ) {
    this.vm = vm;
    if (isRenderWatcher) {
      vm._watcher = this;
    }
    vm._watchers.push(this);
    // options
    if (options) {
      this.deep = !!options.deep; //是否觀察對象內(nèi)部值的變化
      this.user = !!options.user;
      this.lazy = !!options.lazy;
      this.sync = !!options.sync;
    } else {
      this.deep = this.user = this.lazy = this.sync = false;
    }
    this.cb = cb; // 觀察屬性改變時執(zhí)行的函數(shù)
    this.id = ++uid$1; // uid for batching
    this.active = true;
    this.dirty = this.lazy; // for lazy watchers
    this.deps = [];
    this.newDeps = [];
    this.depIds = new _Set();
    this.newDepIds = new _Set();
    this.expression = expOrFn.toString();
    // parse expression for getter
    if (typeof expOrFn === 'function') {
      this.getter = expOrFn;
    } else {
      // 將需要觀察的數(shù)據(jù):string | Function | Object | Array等進(jìn)行解析 如:a.b.c, 并返回訪問該表達(dá)式的函數(shù) 
      this.getter = parsePath(expOrFn); 
      if (!this.getter) {
        this.getter = function () { };
        "development" !== 'production' && warn(
          "Failed watching path: \"" + expOrFn + "\" " +
          'Watcher only accepts simple dot-delimited paths. ' +
          'For full control, use a function instead.',
          vm
        );
      }
    }
    // this.get()將訪問需要觀察的數(shù)據(jù) 
    this.value = this.lazy
      ? undefined
      : this.get(); 
  };
  /**
   * Evaluate the getter, and re-collect dependencies.
   */
  Watcher.prototype.get = function get() {
    //this為$watch方法中實例化的watcher
    pushTarget(this);講this賦給Dep.target并緩存之前的watcher
    var value;
    var vm = this.vm;
    try {
      //訪問需要觀察的數(shù)據(jù),在獲取數(shù)據(jù)的getter中執(zhí)行dep.depend();將$watch方法中實例化的watcher添加到對應(yīng)數(shù)據(jù)下的dep中
      value = this.getter.call(vm, vm); 
    } catch (e) {
      if (this.user) {
        handleError(e, vm, ("getter for watcher \"" + (this.expression) + "\""));
      } else {
        throw e
      }
    } finally {
      // "touch" every property so they are all tracked as
      // dependencies for deep watching
      if (this.deep) {
        traverse(value);
      }
      popTarget(); //將之前的watcher賦給Dep.target
      this.cleanupDeps();
    }
    return value
  };<br><br><br><br> 
  Watcher.prototype.run = function run() {

/*....省略部分....*/ 
    var value = this.get(); //重新獲取info的值
    var oldValue = this.value; //保存老的值
    this.value = value;
    this.cb.call(this.vm, value, oldValue); //執(zhí)行watch的回調(diào)
/*....省略部分....*/ 
  };

  以上代碼在watcher實例化的時候執(zhí)行  this.getter = parsePath(expOrFn); 返回一個訪問該屬性的函數(shù),參數(shù)為被訪問的對象  如vm.$watch("info",function(new, old){console.log("watch success")});, this.getter =function(obj){return obj.info};,在執(zhí)行watcher的get方法中,將執(zhí)行value = this.getter.call(vm, vm);,觸發(fā)屬性的get方法,添加該watcher至info屬性對應(yīng)的def對象中,如果需要深度監(jiān)聽,將執(zhí)行traverse(value),依次訪問info(假設(shè)info只對象)對象下的屬性,如果info的屬性還有是對象的屬性,將進(jìn)行遞歸訪問,以達(dá)到info以及info下所有的屬性的def對象都會添加該watcher實例。

     當(dāng)我們執(zhí)行vm.info="change"時,將出發(fā)info的set方法,執(zhí)行dep.notify();出發(fā)info所依賴的watcher執(zhí)行watcher的run方法,即實現(xiàn)監(jiān)聽

總結(jié)

以上所述是小編給大家介紹的vue 函數(shù)配置項watch及函數(shù) $watch 源碼分享,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Vue3中Element-Plus分頁(Pagination)組件的使用

    Vue3中Element-Plus分頁(Pagination)組件的使用

    Element-Plus分頁(Pagination)組件在開發(fā)過程中數(shù)據(jù)展示會經(jīng)常使用到,同時分頁功能也會添加到頁面中,下面我們就來學(xué)習(xí)一下它的具體使用,需要的可以參考一下
    2023-11-11
  • Vue中傳遞自定義參數(shù)到后端、后端獲取數(shù)據(jù)并使用Map接收參數(shù)

    Vue中傳遞自定義參數(shù)到后端、后端獲取數(shù)據(jù)并使用Map接收參數(shù)

    有些傳遞的參數(shù)是直接拼接到URL地址欄中的、但是為了統(tǒng)一管理、不能將傳遞的參數(shù)直接拼接到地址欄中,接下來通過本文給大家介紹Vue中傳遞自定義參數(shù)到后端、后端獲取數(shù)據(jù)并使用Map接收參數(shù),感興趣的朋友一起看看吧
    2022-10-10
  • vite+vue3.0+ts+element-plus快速搭建項目的實現(xiàn)

    vite+vue3.0+ts+element-plus快速搭建項目的實現(xiàn)

    本文將結(jié)合實例代碼,介紹vite+vue3.0+ts+element-plus快速搭建項目的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Vue3+vant+ts 上滑加載解決上滑調(diào)用多次數(shù)據(jù)的問題(推薦)

    Vue3+vant+ts 上滑加載解決上滑調(diào)用多次數(shù)據(jù)的問題(推薦)

    這篇文章主要介紹了Vue3+vant+ts 上滑加載解決上滑調(diào)用多次數(shù)據(jù)的問題,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • vue項目自適應(yīng)屏幕分辨率實現(xiàn)步驟

    vue項目自適應(yīng)屏幕分辨率實現(xiàn)步驟

    這篇文章主要給大家介紹了關(guān)于vue項目自適應(yīng)屏幕分辨率實現(xiàn)的相關(guān)資料,作為前端人員,為了適配各種型號的電腦、手機(jī),我們往往離不開屏幕分辨率的適配,需要的朋友可以參考下
    2023-09-09
  • vue+iview使用樹形控件的具體使用

    vue+iview使用樹形控件的具體使用

    這篇文章主要介紹了vue+iview使用樹形控件的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Vue中?引入使用?babel-polyfill?兼容低版本瀏覽器的方法

    Vue中?引入使用?babel-polyfill?兼容低版本瀏覽器的方法

    最近在項目中使用 webpack 打包后升級,用戶反饋使用瀏覽器(chrome 45)訪問白屏。經(jīng)過排查發(fā)現(xiàn):由于 chrome 45 無法兼容 ES6 語法導(dǎo)致的,接下來給大家介紹下Vue中?引入使用?babel-polyfill?兼容低版本瀏覽器方法,需要的朋友可以參考下
    2023-02-02
  • 如何使用vue-pdf-embed實現(xiàn)PDF在線預(yù)覽

    如何使用vue-pdf-embed實現(xiàn)PDF在線預(yù)覽

    vue-pdf-embed是一個基于Vue.js的插件,專門用于在Vue應(yīng)用中嵌入和展示PDF文件,本文將使用vue-pdf-embed實現(xiàn)PDF在線預(yù)覽功能,有需要的小伙伴可以參考一下
    2025-03-03
  • 淺析Vue中defineProps的解構(gòu)和不解構(gòu)

    淺析Vue中defineProps的解構(gòu)和不解構(gòu)

    defineProps?是?Vue?3?Composition?API?中用來聲明組件接收的?props?的方法,本文主要為大家介紹了defineProps的解構(gòu)和不解構(gòu),感興趣的可以了解下
    2025-02-02
  • 在Vant的基礎(chǔ)上封裝下拉日期控件的代碼示例

    在Vant的基礎(chǔ)上封裝下拉日期控件的代碼示例

    這篇文章主要介紹了在Vant的基礎(chǔ)上封裝下拉日期控件的代碼示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12

最新評論

遵义县| 杨浦区| 呼伦贝尔市| 江西省| 武隆县| 大同县| 康乐县| 科技| 义马市| 平遥县| 绥滨县| 陵川县| 昭通市| 清原| 礼泉县| 黄梅县| 邹城市| 奉新县| 北川| 菏泽市| 永定县| 南投市| 南康市| 高雄县| 阜新市| 恩施市| 彝良县| 徐州市| 陕西省| 沐川县| 东莞市| 祁东县| 聂拉木县| 广水市| 措美县| 林口县| 建始县| 铜山县| 原阳县| 武隆县| 深水埗区|