因為有一些需求的緣故,所以需要做到動態載入元件。想當然爾,事情不是想像中的那麼簡單。雖然說 VueJS 已經很方便了,不過做起來還是有一些地方需要留意
動態元件
VueJS 有一個 :is
可以用,詳細的使用辦法可以參考官方說明。
<component :is="myComponent"></component>
import myComponent from 'components/myComponent.vue'
export default {
components: {
myComponent: myComponent
},
data () {
return {
myComponent: 'myComponent'
}
}
}
一般來說項上述的用法,其實就能動態的改變樣版中的元件。問題來了,如果每次都修改都要重新產生一次檔案(也就是每次都要 npm run build
,然後更新整包檔案)。這樣用起來也太麻煩了點。
所以說,是不是能有更好的方式來做這件事情?
把 Vue 放到外面去
假設我們有一個 App.js
,用來初始化整個 App 的地方,我們將 Vue 給拋出去。
import Vue from 'vue'
export default {
name: 'app',
created () {
// 從這裡把 Vue 丟到外面去
if (typeof window.Vue === 'undefined') {
window.Vue = Vue
}
}
}
或許你會問,丟出去要幹嘛?我們現在再回來看上面提到的例子。
export default {
mounted () {
let dynamicComponent = document.getElementById('dynamicComponent')
if (!dynamicComponent) {
dynamicComponent.src = '/static/my_component.js'
dynamicComponent.async = true
dynamicComponent.onload = c => {
this.component = 'myComponent'
}
} else {
const script = document.querySelector('script')
dynamicComponent = document.createElement('script')
dynamicComponent.src = '/static/my_component.js'
dynamicComponent.async = true
dynamicComponent.onload = c => {
this.component = 'myComponent'
}
script.parentNode.insertBefore(dynamicComponent, script)
}
},
data () {
return {
component: ''
}
}
}
看起來很麻煩,但是上面做的事情就是將 /static/my_component.js
給載入到我們的 App 裡面。那 /static/my_component.js
會長什麼樣子呢?
Vue.component('myComponent', {
template: '<div>這是一個簡單的範例</div>',
mounted: function () {
// ...
}
});
他其實就是一個包裝好的 Vue Component 而已,沒有什麼太神奇的地方。
附加條件
這種方法有一個弊病,看到剛剛的 window.Vue = Vue
了嗎?意思就是,你的專案不能使用 Runtime-only
的方式,一定得用 Runtime + Compiler
,不然你包裝好的 Vue Component 有可能會無法使用。
為何不用 import
雖然說 import
也可以直接使用在 components
裡面,但是這個方式在 runtime 的時候會造成錯誤,畢竟原本的 App 結構當中可能不存在你的檔案。或者說,你的檔案是後期才要製作或是修改的,那麼即便 import
好用,在此也是無用武之地。
外部檔案也可以打包
既然 App 都可以了,我們自己外部的檔案當然也是可以。不過,這麼做的話專案可能會變得比較複雜。也就是說,你做個專案可能得跑好幾次 npm run build
就是了。
但如果是頻繁修改某一個元件,或是元件結構相對複雜,需要多重動態載入的話,這種方法也不會麻煩。畢竟不用每次都打包一整個 App,而且就算 Component 壞掉了,也只會是某個區塊無法顯示,不會讓整個 App 掛掉。
LIVE DEMO
建議開 1080P,因為我螢幕錄影解析度開太大了 XD
webpack 設定
我所使用的只是 Vue-CLI 內建的 webpack-simple 這個樣版而已,其中你有幾個地方需要修改,
output: {
// path: path.resolve(__dirname, './dist'),
// 把輸出的資料夾指定到你要的地方
path: path.resolve(__dirname, './components'),
// publicPath: '/dist/',
// 把輸出的 publicPath 根據你的主要 App 作對應的設定
publicPath: '/static/components/',
// 最後可以改一下輸出檔案名稱
// filename: 'build.js'
filename: 'components.js'
},
單一元件 main.js
修改
上述有提到把 Vue 丟出來給 window.Vue
這件事情,所以當我單一元件要使用的時候,其實相對容易,把原本的 main.js
稍微改一下就好了,
import App from './App.vue'
import Hello from './Hello.vue'
// 注意這邊,這個 Component 叫做 'single-component'
window.Vue.component('single-component', {
render: h => h(App)
})
// 你可以載入其他的,記得要先 import 進來
window.Vue.component('hello-component', {
render: h => h(Hello)
})
小結
我目前已經有一兩個正式專案使用者種方式載入,對於頻繁修改元件來說,挺愜意的。