上一篇已經學會如何把外部元件的資料傳到內部元件,如果是內部傳到外部,就需要透過emit
來達成。
Props in, Ebent out
:
emit
傳遞事件emit
除了可以傳遞資料,也可以只傳遞事件,來觸發外部的事件:
<div id="app">
{{ text }}:
<button type="button" @click="add()">add</button>
{{ num }}
<br>
<br>
<out-text @button-click="add"></out-text>
</div>
const app = Vue.createApp({
data() {
return {
text: "外部元件",
num: 0,
}
},
methods: {
add() {
this.num++;
}
}
});
app.component("outText",{
template: `<button @click="click">emit add</button>`,
data() {
return {
text: "內部元件"
};
},
methods: {
click() {
this.$emit('buttonClick');
}
}
});
app.mount("#app");
emit
起手式:$emit
觸發的函式@button-click="add"
跟Props
一樣記法前內後外,撰寫時可以按照步驟console.log
,會比較順利完成。
emit
傳遞參數將內層資料傳遞到外層元件上使用:
<div id="app">
<h3> {{ title }} </h3>
{{ text }}:
<button type="button" @click="add">add</button>
{{ num }}
<br>
<br>
<out-text @button-click="add"></out-text>
</div>
const app = Vue.createApp({
data() {
return {
title: "",
text: "外部元件",
num: 0,
}
},
methods: {
add(addtext) {
this.num++;
this.title = addtext;
//addtext 沒有值傳起來就會變成 事件物件 [object PointerEvent]
}
}
});
app.component("outText",{
template: `<button @click="click">emit add</button>`,
data() {
return {
text: "內部元件",
insideText: "內部元件傳遞文字"
};
},
methods: {
click() {
this.$emit('buttonClick', this.insideText);
}
}
});
app.mount("#app");
因為要帶參數所以原本$emit
裡要多帶一個this.insideText
參數,透過外層模板@button-click="add"
,傳遞到外層元件的add(addtext)
,最後再傳回外層data
渲染畫面。
emits
驗證<div id="app">
{{ text }}:{{ num }}
<br>
<br>
<out-text @button-click="add"></out-text>
</div>
const app = Vue.createApp({
data() {
return {
text: "外部 num",
num: 0,
}
},
methods: {
add(num) {
this.num = this.num + num;
}
}
});
app.component("outText",{
template: `{{ text }}:<button @click="$emit('buttonClick', num)">emit add</button>`,
data() {
return {
text: "內部元件",
num: 3,
};
},
});
app.mount("#app");
內層元件除了使用methods
的方式撰寫emit
,也可以直接寫在template
,@click="$emit('buttonClick', num)"
裡面的'buttonClick'
就是內層的@button-click
,num
則是內層data
的num
。當我們開啟開發者工具Console
,會發現跳出這一段警告:
這是因為無法正確追蹤你帶入的變數內層的num
,就會跳出這個警告提示,這時只要加上emits:['buttonClick']
就能消除警告。
emits
正確用法是拿來驗證事件參數傳出去的值,是否符合預期的型別:
<div id="app">
{{ text }}:{{ num }}
<br>
<br>
<out-text @button-click="add"></out-text>
<br>
<out-text2 @button-click="add"></out-text2>
</div>
const app = Vue.createApp({
data() {
return {
text: "外部 num",
num: 0,
}
},
methods: {
add(num) {
this.num = this.num + num;
}
}
});
app.component("outText",{
template: `{{ text }}:<button @click="$emit('buttonClick', num)">emit add</button>`,
data() {
return {
text: "內部元件",
num: 3,
};
},
emits: ['buttonClick']
});
app.component("outText2",{
template: `{{ text }}:<button @click="$emit('buttonClick', '1')">test</button>`,
data() {
return {
text: "emits",
num: 3,
};
},
emits: {
buttonClick: (num) => {
if (typeof num !== 'string') {
console.warn('buttonClick 事件參數型別須為 String')
}
return typeof num === 'string'
}
}
});
app.mount("#app");
觀察outText2
裡面的$emit
帶的參數是一個字串1,而emits
要改為物件,把要觀察的事件
帶入buttonClick: (num)
,(num)
就是$emit('buttonClick', '1')
的參數,如果參數的型別是字串的話就不會跳出警告,可以試著更改參數型別,警告提示就會顯示:[Vue warn]: Invalid event arguments: event validation failed for event 'buttonClick'
,事件驗證失敗,就可以知道帶出去的參數是否符合預期。
以上如有錯誤,歡迎指教。