Vue3值得注意的新特性之——觸發(fā)組件選項(xiàng)
事件名
與組件和prop一樣,事件名提供了自動的大小寫轉(zhuǎn)換。如果用駝峰命名的子組件中觸發(fā)一個事件,你將可以在父組件中添加一個kebabcase(短橫線分割命名)的監(jiān)聽器。
- <my-component @my-event="doSomething"></my-component>
- this.$emit('myEvent')
與props命名一樣,當(dāng)你使用DOM模板時,我們建議使用kebabcase事件監(jiān)聽器。如果你使用的是字符串模板,這個限制就不適用。
定義自定義事件
可以通過emits選項(xiàng)在組件上定義已發(fā)出的事件。
- app.component('custom-form', {
- emits: ['inFocus', 'submit']
- })
當(dāng)在emits選項(xiàng)中定義了原生事件(如click)時,將使用組件中的事件替代原生事件偵聽器。
驗(yàn)證拋出的事件
與props類型驗(yàn)證類似,如果使用對象語法而不是數(shù)組語法,則可以驗(yàn)證它。
要添加驗(yàn)證,將為事件分配一個函數(shù),該函數(shù)接收傳遞給$emit調(diào)用的參數(shù),并返回一個布爾值以指示事件是否有效。
- app.component('custom-form', {
- emits: {
- // 沒有驗(yàn)證
- click: null,
- // 驗(yàn)證submit 事件
- submit: ({ email, password }) => {
- if (email && password) {
- return true
- } else {
- console.warn('Invalid submit event payload!')
- return false
- }
- }
- },
- methods: {
- submitForm() {
- this.$emit('submit', { email, password })
- }
- }
- })
v-model事件
默認(rèn)情況下,組件上的v-model使用modelValue作為props和update:modelValue做完事件。我們可以通過向v-model傳遞參數(shù)來修改這些名稱:
- <my-component v-model:title="bookTitle"></my-component>
在本例中,子組件將需要一個 title prop 并發(fā)出 update:title 要同步的事件:
- app.component('my-component', {
- props: {
- title: String
- },
- emits: ['update:title'],
- template: `
- <input
- type="text"
- :value="title"
- @input="$emit('update:title', $event.target.value)">
- `
- })
多個v-model綁定
通過利用特定prop和事件為目標(biāo)的能力,正如我們之前在v-model參數(shù)中所學(xué)的那樣,我們現(xiàn)在可以在單個組件實(shí)例上創(chuàng)建多個v-model綁定。
每個v-model將同步到不同的prop,而不需要在組件中添加額外的選項(xiàng)。
- <user-name
- v-model:first-name="firstName"
- v-model:last-name="lastName"
- ></user-name>
- app.component('user-name', {
- props: {
- firstName: String,
- lastName: String
- },
- emits: ['update:firstName', 'update:lastName'],
- template: `
- <input
- type="text"
- :value="firstName"
- @input="$emit('update:firstName', $event.target.value)">
- <input
- type="text"
- :value="lastName"
- @input="$emit('update:lastName', $event.target.value)">
- `
- })
處理v-model修飾詞
在2.X中,我們對組件v-model上的.trim等修飾符提供了硬編碼支持。但是,如果組件可以支持自定義修飾符,則會更有用。
在3.X中,添加到組件v-model的修飾符將通過modelModifiers prop提供給組件。
v-model有內(nèi)置的修飾符——.trim,.number和.lazy。但是,在某些情況下,你可能還需要添加自己的自定義修飾符。
我們做個實(shí)例:將提供的字符串第一個字母大寫。
- <my-component v-model.capitalize="myText"></my-component>
- app.component('my-component', {
- props: {
- modelValue: String,
- modelModifiers: {
- default: () => ({})
- }
- },
- emits: ['update:modelValue'],
- template: `
- <input type="text"
- :value="modelValue"
- @input="$emit('update:modelValue', $event.target.value)">
- `,
- created() {
- console.log(this.modelModifiers) // { capitalize: true }
- }
- })
現(xiàn)在我們已經(jīng)設(shè)置了 prop,我們可以檢查 modelModifiers 對象鍵并編寫一個處理器來更改發(fā)出的值。在下面的代碼中,每當(dāng)<input/> 元素觸發(fā) input 事件時,我們都將字符串大寫。
- <div id="app">
- <my-component v-model.capitalize="myText"></my-component>
- {{ myText }}
- </div>
- const app = Vue.createApp({
- data() {
- return {
- myText: ''
- }
- }
- })
- app.component('my-component', {
- props: {
- modelValue: String,
- modelModifiers: {
- default: () => ({})
- }
- },
- emits: ['update:modelValue'],
- methods: {
- emitValue(e) {
- let value = e.target.value
- if (this.modelModifiers.capitalize) {
- value = value.charAt(0).toUpperCase() + value.slice(1)
- }
- this.$emit('update:modelValue', value)
- }
- },
- template: `<input
- type="text"
- :value="modelValue"
- @input="emitValue">`
- })
- app.mount('#app')
對于帶參數(shù)的 v-model 綁定,生成的 prop 名稱將為 arg + "Modifiers":
- <my-component v-model:description.capitalize="myText"></my-component>
- app.component('my-component', {
- props: ['description', 'descriptionModifiers'],
- emits: ['update:description'],
- template: `
- <input type="text"
- :value="description"
- @input="$emit('update:description', $event.target.value)">
- `,
- created() {
- console.log(this.descriptionModifiers) // { capitalize: true }
- }
- })