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

Vue生命周期函數(shù)調(diào)用詳解

 更新時間:2022年08月15日 10:50:08   作者:夏日  
這篇文章主要介紹了Vue生命周期函數(shù)調(diào)用詳解,本文將實現(xiàn)Vue生命周期相關(guān)代碼的核心邏輯,從源碼層面來理解生命周期,感興趣的小伙伴可以參考一下

生命周期

Vue為用戶提供了許多生命周期鉤子函數(shù),可以讓用戶在組件運行的不同階段書寫自己的邏輯。

那么Vue內(nèi)部到底是如何處理生命周期函數(shù)的呢?Vue的生命周期究竟是在代碼運行的哪個階段執(zhí)行呢?本文將實現(xiàn)Vue生命周期相關(guān)代碼的核心邏輯,從源碼層面來理解生命周期。

Vue.mixin

在介紹生命周期之前,我們先來看下Vue.mixin

Vue.mixinVue的全局混合器,它影響Vue創(chuàng)建的每一個實例,會將mixin 中傳入的配置項與組件實例化時的配置項按照一定規(guī)則進行合并。對于生命周期鉤子函數(shù),相同名字的生命周期將會合并到一個數(shù)組中,混合器中的鉤子函數(shù)將會先于組件中的鉤子函數(shù)放入到數(shù)組中。在特定時機時,從左到右執(zhí)行數(shù)組中的每一個鉤子函數(shù)。

<div id="app">
</div>
<script>
  // 生命周期:
  Vue.mixin({
    created () {
      console.log('global created');
    }
  });
  const vm = new Vue({
    el: '#app',
    data () {
    },
    created () {
      console.log('component created');
    }
  });
  // global created
  // component created  
</script>

上述代碼會先執(zhí)行Vue.mixin中的created函數(shù),然后再執(zhí)行組件中的created函數(shù)。下面我們看下Vue.mixin是怎么實現(xiàn)。

// src/global-api/index.js
import mergeOptions from '../shared/merge-options';

export function initGlobalApi (Vue) {
  Vue.options = {};
  Vue.mixin = function (mixin) {
    this.options = mergeOptions(this.options, mixin);
  };
}

// src/index.js
function Vue (options) {
  this._init(options);
}

// 初始化全局api
initGlobalApi(Vue);
export default Vue;

scr/index.js中執(zhí)行initGlobalApi方法,會為Vue添加optionsVue.mixin屬性。

Vue.mixin會將調(diào)用該函數(shù)時傳入的配置項與Vue.options中的選項進行合并:

Vue.options = {};
Vue.mixin = function (mixin) {
  // Vue.options = mergeOptions(Vue.options, mixin)
  this.options = mergeOptions(this.options, mixin);
};

Vue.options中會保存所有全局的配置項,如components,directives等。執(zhí)行Vue.mixin之后,Vue.options會和Vue.mixin 中的選項進行合并,之后會在組件初始化時將其和組件實例化時傳入的選項根據(jù)不同的合并策略進行合并,這樣會根據(jù)最終合并后的全局選項和組件選項來創(chuàng)建Vue 實例:

// src/init.js
function initMixin (Vue) {
  Vue.prototype._init = function (options) {
    const vm = this;
    // 在初始化根組件時: vm.constructor.options -> Vue.options
    // 在初始化子組件時: vm.constructor.options -> Sub.options
    // 將局部選項和全局選項進行合并
    vm.$options = mergeOptions(vm.constructor.options, options);
    // some code ...  
  };
  // some code ...  
}

現(xiàn)在關(guān)鍵邏輯來到了mergeOptions,下面來介紹mergeOptions的整體編寫思路以及生命周期的合并過程。

生命周期選項合并

mergeOptions函數(shù)完成了組件中選項合并的邏輯:

const strategies = {};

function defaultStrategy (parentVal, childVal) {
  return childVal === undefined ? parentVal : childVal;
}
const LIFECYCLE_HOOKS = [
  'beforeCreate',
  'created',
  'beforeMount',
  'mounted',
  'beforeUpdate',
  'updated',
  'beforeDestroy',
  'destroyed'
];
function mergeHook (parentVal, childVal) {
  if (parentVal) {
    if (childVal) {
      // concat可以拼接值和數(shù)組,但是相對于push來說,會返回拼接后新數(shù)組,不會改變原數(shù)組
      return parentVal.concat(childVal);
    }
    return parentVal;
  } else {
    return [childVal];
  }
}

LIFECYCLE_HOOKS.forEach(hook => {
  strategies[hook] = mergeHook;
});

function mergeOptions (parent, child) { // 將子選項和父選項合并
  const options = {};

  function mergeField (key) {
    const strategy = strategies[key] || defaultStrategy;
    options[key] = strategy(parent[key], child[key]);
  }

  for (const key in parent) {
    if (parent.hasOwnProperty(key)) {
      mergeField(key);
    }
  }
  for (const key in child) {
    if (child.hasOwnProperty(key) && !parent.hasOwnProperty(key)) {
      mergeField(key);
    }
  }
  return options;
}
export default mergeOptions;

對于不同的選項,Vue會采取不同的合并策略。也就是為strategies添加Vue的各個選項作為key,其對應(yīng)的合并邏輯是一個函數(shù),為strategies[key]的值。如果沒有對應(yīng)key 的話,會采用默認的合并策略defaultStrategy來處理默認的合并邏輯。

這樣可以讓我們不用再用if else來不停為每一個選項進行判斷,使代碼更加簡潔。并且在之后如果需要添加新的合并策略時,只需要添加類似如下代碼即可,更易于維護:

function mergeXXX (parentVal, childVal) {
  return result
}
strategies[xxx] = mergeXXX

對于生命周期,我們會將每個鉤子函數(shù)都通過mergeHook合并為一個數(shù)組:

function mergeHook (parentVal, childVal) {
  if (parentVal) {
    if (childVal) {
      // concat可以拼接值和數(shù)組,但是相對于push來說,會返回拼接后新數(shù)組,不會改變原數(shù)組
      return parentVal.concat(childVal);
    }
    return parentVal;
  } else {
    return [childVal];
  }
}

Vue.mixin中提到例子的合并結(jié)果如下:

現(xiàn)在我們已經(jīng)成功將生命周期處理成了數(shù)組,接下來便到了執(zhí)行數(shù)組中的所有鉤子函數(shù)的邏輯了。

調(diào)用生命周期函數(shù)

完成上述代碼后,我們已經(jīng)成功將所有合并后的生命周期放到了vm.$options中對應(yīng)的生命周期數(shù)組中:

vm.$options = {
  created: [f1, f2, f3],
  mounted: [f4, f5, f6]
  // ...
}

想要執(zhí)行某個生命周期函數(shù),可以用它的名字從vm.$options找到其對應(yīng)的函數(shù)執(zhí)行。為了方便生命周期的調(diào)用,封裝了一個callHook函數(shù)來幫我們做這些操作:

// src/lifecycle.js
export function callHook (vm, hook) {
  const handlers = vm.$options[hook];
  if (handlers) {
    handlers.forEach(handler => handler.call(vm));
  }
}

對于目前我們已經(jīng)完成的代碼,可以在如下位置添加生命周期鉤子函數(shù)的調(diào)用:

此時,用戶在使用時傳入的beforeCreate,created,beforeMount,Mounted鉤子函數(shù)就可以正確執(zhí)行了。

  • beforeCreate:在組件初始化狀態(tài)initState之前執(zhí)行,此時不能訪問props,methods,data,computed等實例上的屬性
  • created:組件初始化狀態(tài)后執(zhí)行,此時props,methods,data等選項已經(jīng)初始化完畢,可以通過實例來直接訪問
  • beforeMount: 組件過載之前執(zhí)行
  • mounted: 組件掛載之后執(zhí)行,即使用實例上最新的data生成虛擬DOM,然后將虛擬DOM掛載到真實DOM之后執(zhí)行。

結(jié)語

生命周期函數(shù)本質(zhì)上就是我們在配置項中傳入回調(diào)函數(shù),Vue會將我們傳入的配置項收集到數(shù)組中,然后在特定時機統(tǒng)一執(zhí)行。

Vue的生命周期從定義到執(zhí)行一共經(jīng)歷了如下幾個步驟:

  • 在組件實例化時作為選項傳入
  • 首先將Vue.mixin中傳入的配置項和Vue.options中的生命周期函數(shù)合并為一個數(shù)組
  • 將組件實例化時傳入的選項和Vue.options中的生命周期繼續(xù)進行合并
  • 封裝callHook函數(shù),從vm.$options中找到指定生命周期函數(shù)對應(yīng)的數(shù)組
  • 在特定時機執(zhí)行特定的生命周期函數(shù)

到此這篇關(guān)于Vue生命周期函數(shù)調(diào)用詳解的文章就介紹到這了,更多相關(guān)Vue生命周期內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

源碼地址:傳送門

相關(guān)文章

最新評論

军事| 罗甸县| 乐业县| 尚志市| 远安县| 淮安市| 中山市| 瑞昌市| 偏关县| 正安县| 界首市| 澳门| 临汾市| 全南县| 淄博市| 石楼县| 砀山县| 石棉县| 兰溪市| 云浮市| 个旧市| 西平县| 南安市| 普陀区| 双江| 阜城县| 长武县| 宜兴市| 灵山县| 八宿县| 泽库县| 江都市| 梅河口市| 连江县| 鄂州市| 余干县| 遵化市| 霍林郭勒市| 县级市| 双峰县| 莆田市|