Vue-101-Day 15
23 Jun 2019 |自定義事件
事件名稱(Event name)不會提供任何大小寫自動轉換的機制,再DOM 使用 v-on 監聽事件會自動轉換成小寫
,所以v-on:myEvent
會變成v-on:myevent
,導致 myEvent 監聽不到
使用 kebab-case
Vue 官方推薦使用 kebab-case 當作使用事件名稱的命名方式
客製化 Component 使用 v-model
預設 Component 會使用value 當作 prop
而input 當作 event
,但有時會利用不同的值,做不同的事情,像是在 input type = checkbox or radio button 的時候
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change',$event.target.checked)"
>`
})
new Vue({
el: '#app-22',
data: {
lovingVue: true
}
})
<div id="app-22">
<base-checkbox v-model="lovingVue"></base-checkbox>
</div>
上述的v-model="lovingVue"
會將值傳入名為 checked 的 prop,當 base-checkbox 觸發 change 事件時並附帶新的 value,lovingVue 這個屬性將會被更新
註:於 Vue2.2 以上使用
在 component 綁定原生事件
若要在 component 監聽原生事件,可以使用v-on 的 .native 修飾符
Vue.component('base-input', {
template: `
<input
type="text"
v-bind:value="lovingVue"
>`
})
new Vue({
el: '#app-22',
data: {
lovingVue: 'Vue is great!'
},
methods: {
onFocus: function(el) {
console.log(el) // FocusEvent{...}
}
}
})
<div id="app-22">
<base-input v-bind:value="lovingVue" v-on:focus.native="onFocus">
</base-input>
</div>
將上述 base-input 做調整,根元素調整為 label 而不是 input,如下
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
>
</label>`
})
new Vue({
el: '#app-22',
data: {
lovingVue: 'I love vue very much',
msg: 'Hi everyone'
},
methods: {
onFocus: function(el) {
console.log(el) // FocusEvent{...}
}
}
})
會發現v-on:focus.native="onFocus" 事件
似乎會失敗,因為 focus.native 是綁定到根元素(label)導致 focus 事件沒有被觸發
若要正確的執行事件,需使用 Vue 提供的v-on="listeners"
綁定組件事件
依上述範例
- 加入 inputListeners
- 將父組件 focus 移除 native 修飾符
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function() {
var vm = this
return Object.assign({}, this.$listeners, {
input: function(event) {
vm.$emit('input', event.target.value)
}
})
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="$listeners"
>
</label>`
})
<div id="app-22">
<base-input :label="lovingVue" :value="msg" v-on:focus="onFocus">
</base-input>
</div>
即可正常執行 focus 事件
.sync 修飾符
在某些情況下,prop 也需要執行雙向綁定,官方推薦以update:myPropName
的模式觸發事件
Vue.component('base-button', {
props: ['title'],
template: `
<button @click="click">{{title}}</button>
`,
methods: {
click() {
// 反轉button中的字串
const newTitle = this.title
.split('')
.reverse()
.join('')
this.$emit('update:title', newTitle)
}
}
})
new Vue({
el: '#app-23',
data: {
title: 'I Love Vue.js'
}
})
父組件可以監聽該事件,並更新 title 字串
<div id="app-23">
<base-button :title="title" @update:title="title=$event"></base-button>
</div>
為了方便撰寫,Vue 也提供較簡易的寫法,與上述的寫法效果是同樣的
<base-button :title.sync="title"></base-button>
參考資料:
Comments