vue composition and reusability
組件的組成和重用
索引index
parent/children: 取得組件的上一層或下一層組件
mixins: 重用methods
extends: 擴充組件
provider/inject: context全域變數
slot: 為組件留位子
parent/children
在組件中透過this.$parent取得其父組件,用this.$children則是可以取得子組件
注意:必須謹慎使用,如果直接改變其parent/children的內部狀態,可能會導致無法預期的錯誤,一般仍是使用props/events去進行組件間的溝通
mixins
如果同一個方法會被用到好幾次,那麼這時候就可以考慮將其寫成mixin,讓各個組件都可以使用,如此一來就不必重複寫多次(clean code的不要重複自己原則),以及測試會更加簡單(只要測一次就好)
// 基本用法
const sayHelloMixin = {
mounted() { this.sayHello(); },
methods: {
sayHello() { console.log('Hi!!'); },
},
};{
// ...
mixins: [
sayHelloMixin,
],
}
以優先順序來說,data優先於mixin中的值,當有一樣的key時,data會取代掉原本的值
// mixin with data
const commonDataMixin = {
data() {
return {
common: 'something from mixin.',
}
},
};({
// ...
data() {
return {
common: 'something from component.',
}
},
mixins: [
commonDataMixin,
],
created() {
console.log(this.$data.common); // 'something from component.'
}
})
而created(), mounted() …等等 生命週期的方法,則是不會像data同樣的key被取代,而是會被儲存成function[],相關週期被觸發時function會被「依序」呼叫
const saySomethingWhenCreatedMixin = {
created() {
console.log('Hey from mixin!');
},
};({
// ...
created() {
console.log('Yo from component!');
},
mixins: [
sayHelloMixin,
],
})// 'Hey from mixin!' <== First, before component's created
// 'Yo from component!'
全域mixin,「所有」(包含引用的library)的組件都會被影響,因此需要非常謹慎使用,通常會使用在自訂option的情況,如以下範例
// global mixinconst globalMixin = {
created() {
const option = this.$options.someOption;
if(option) {
console.log(option);
}
},
};Vue.mixin({ ...globalMixin, })new Vue({
someOption: 'option from component instance.'
})
// 'option from component instance.'
extends
等同於Vue.extends(),只是更加直接簡單地擴充component
const Text = { //... }const Title = {
extends: Text,
// ...
}
provide/inject
子組件能夠取得父組件provide的值,無論層級多深都可以取得,方便作為某一部份組件的共同狀態管理,類似react的context
provide: object | () => object
inject: string[] | { [key: string]: string | Symbol | object }
// Provider
<template>
<div>
<slot></slot>
</div>
</template>const Provider = Vue.component({
provide: {
context: 'some value',
},
// ...
})// inject child componentconst Child = Vue.component({
inject: ['context'],
created() {
console.log(this.context) // 'some value'
}
})// wrap Child in Provider
<Provider>
<Child />
</Provider>
provide/inject可使用Symbol
const stateKey = Symbol()// provider
{
//...
provider() {
returu {
[stateKey]: 'some foo'
};
},
}// child
{
inject: { stateKey },
}
可作為props的預設值(適用於2.2.1之後),
// props
{
inject: ['context'],
props: {
inputVal: {
default() { return this.context; },
}
}
}
// data
{
inject: ['context'],
data() {
return {
inputVal: this.context,
}
}
}
inject使用不同的key名字(像是子組件中使用的是a,而Provider中provide的是b)以及設定預設值
(適用於2.5.0之後)
// default value of inject(v2.5.0+){
inject: {
dataFromCtx: {
from: 'context', // Provider provide this
default: 'some default value',
// default: () => []
// if default is not string/number/undefined/null/boolean/Symbol, use a function.
}
}
參考/引用/延伸閱讀:
mixins: https://vuejs.org/v2/guide/mixins.html
composition: https://vuejs.org/v2/api/#Options-Composition