亚洲欧美日韩综合系列在线_91精品人妻一区二区_欧美大肥婆一级特大AA片_九色91视频免费观看_亚洲综合国产精品_av中文字幕在线不卡_久久精品色综合网_看黄色视频的软件_无卡无码高清中文字幕码2024_亚洲欧美日韩天堂网

Vue.js 子組件的異步加載及其生命周期控制-------異步加載子組件,子組件的生命周期控制過程不一樣

來源:Hex 發(fā)布時間:2018-07-03 14:28:27 閱讀量:1679

異步組件

討論異步加載,需要先了解下異步組件。Vue.js 的異步組件是把組件定義為一個工廠函數(shù),在組件需要渲染時觸發(fā)工廠函數(shù),并且把結(jié)果緩存起來,用于后面的再次渲染。例如注冊一個全局異步組件:

Vue.component('async-demo', function(resolve, reject) {setTimeout(function() {// 將組件定義傳入 resolve 回調(diào)函數(shù)resolve({template: '<div>I am async!</div>'     // 組件的其他選項(xiàng)})}, 1000)})

異步子組件和全局注冊很類似:

Vue.component('parent-demo', { // 父組件的其他選項(xiàng) components: {   'async-demo': function(resolve, reject) {setTimeout(function() {// 將組件定義傳入 resolve 回調(diào)函數(shù)resolve({template: '<div>I am async!</div>'         // 子組件的其他選項(xiàng)})}, 1000)}}})

工廠函數(shù)的第一個參數(shù) resolve 為成功后的回調(diào),第二個參數(shù) reject 為失敗后的回調(diào),可以在這里提示用戶加載失敗等。

這里使用 setTimeout 只是為了模擬異步,在實(shí)際項(xiàng)目中,應(yīng)該配合 webpack 的代碼分離功能來實(shí)現(xiàn)異步加載。

異步加載

在實(shí)際的項(xiàng)目中,如果不使用異步加載,則 Vue.js 組件的 JS、CSS 和模板都會打包到一個 .js 文件中,這個文件可能達(dá)到幾 MB 甚至更多,嚴(yán)重影響首屏加載時間。所以在項(xiàng)目中我們需要啟用組件的異步加載。

webpack 代碼分離

webpack 的代碼分離有兩種,第一種,也是優(yōu)先選擇的方式是,使用符合 ECMAScript 提案的 import() 語法。第二種,則是使用 webpack 特定的 require.ensure。讓我們先看看第一種:

import() 調(diào)用會在內(nèi)部用到 promises。如果在舊有版本瀏覽器中使用 import(),記得使用一個 polyfill 庫(例如 es6-promise 或 promise-polyfill),來 shim Promise。
Vue.component('async-demo',// 該 import 函數(shù)返回一個 Promise 對象。() => import('./async-demo'))

上面的例子中,前文提到的工廠函數(shù)支持返回一個 Promise 對象,所以可以使用 import() 這種代碼分離方式。

局部注冊也是類似的:

Vue.component('parent-demo', { // 父組件的其他選項(xiàng) components: {   'async-demo': () => import('./async-demo')}})

本質(zhì)上,import() 函數(shù)返回一個 Promise 實(shí)例,你可以自定義這個過程,下文會有說明。

第二種 webpack 代碼分離是這樣的:

Vue.component('async-demo', function(resolve) {require.ensure([], function(require) {    resolve(require('./async-demo'))}, function(error) {   // 加載出錯執(zhí)行這里 })})

看起來比較繁瑣,如果你使用 webpack 2 及以上版本,則不建議使用第二種方式。

生命周期控制

在使用子組件(或者叫局部注冊)時,我們可能需要在子組件實(shí)例化(或者叫創(chuàng)建完畢)后做某些事情。在非異步的子組件中,我們很容易做這件事:

<template><div><my-demo ref="demo"></my-demo></div></template><script>import Demo from './Demo'export default {mounted() {   // 在這里可以通過組件的 $refs 獲取到子組件的實(shí)例   // 可以認(rèn)為,在這里子組件實(shí)例化完畢   console.log(this.$refs.demo)},components: {MyDemo: Demo}}</script>

上例中使用了 Vue.js 的子組件引用,所以可以在生命周期函數(shù) mounted 中很方便的獲取到子組件的實(shí)例,這樣就可以在這個函數(shù)中處理一些子組件實(shí)例化后要做的事情。

但是在異步子組件中,mounted 函數(shù)中是無法獲取到子組件的實(shí)例的,所以我們需要一些技巧來實(shí)現(xiàn)這個功能。

<template><div><my-demo ref="demo"></my-demo></div></template><script>export default {components: {MyDemo: () => import('./Demo').then(component => {     // 清理已緩存的組件定義     component.default._Ctor = {}if (!component.default.attached) {       // 保存原組件中的 created 生命周期函數(shù)       component.default.backupCreated = component.default.created}     // 注入一個特殊的 created 生命周期函數(shù)     component.default.created = function() {// 子組件已經(jīng)實(shí)例化完畢       // this 即為子組件 vm 實(shí)例       console.log(this)if (component.default.backupCreated) {         // 執(zhí)行原組件中的 created 生命周期函數(shù)          component.default.backupCreated.call(this)}}     // 表示已經(jīng)注入過了      component.default.attached = truereturn component})}}</script>

上例中,可以看到我們對組件異步加載做了一些特殊的控制,其中 import().then() 則是在加載完子組件的 .js 文件后,實(shí)例化子組件之前的回調(diào),如果需要處理出錯的情況,則 import().then().catch() 即可。

以上代碼只是注入了一個 created 函數(shù),如果要注入其他生命周期函數(shù),例如 mounted,也是類似的:

<template><div><my-demo ref="demo"></my-demo></div></template><script>export default {components: {MyDemo: () => import('./Demo').then(component => {     component.default._Ctor = {}if (!component.default.attached) {       component.default.backupMounted = component.default.mounted}     component.default.mounted = function() {if (component.default.backupMounted) {         component.default.backupMounted.call(this)}}component.default.attached = truereturn component})}}</script>

通過上面的討論,我們可以做到完全控制 Vue.js 組件的異步加載的全過程,這對于需要精確控制子組件加載的組件,會有很大的幫助。

演示項(xiàng)目

根據(jù)上面的思路,寫了一個基于 Bootstrap 的異步彈窗演示項(xiàng)目:

https://github.com/hex-ci/vue...


原文地址https://segmentfault.com/a/1190000012427477

標(biāo)簽: HTML JS
分享:
評論:
你還沒有登錄,請先