Vue3值得注意的新特性之——觸發組件選項
事件名
與組件和prop一樣,事件名提供了自動的大小寫轉換。如果用駝峰命名的子組件中觸發一個事件,你將可以在父組件中添加一個kebabcase(短橫線分割命名)的監聽器。
- <my-component @my-event="doSomething"></my-component>
- this.$emit('myEvent')
與props命名一樣,當你使用DOM模板時,我們建議使用kebabcase事件監聽器。如果你使用的是字符串模板,這個限制就不適用。
定義自定義事件
可以通過emits選項在組件上定義已發出的事件。
- app.component('custom-form', {
- emits: ['inFocus', 'submit']
- })
當在emits選項中定義了原生事件(如click)時,將使用組件中的事件替代原生事件偵聽器。
驗證拋出的事件
與props類型驗證類似,如果使用對象語法而不是數組語法,則可以驗證它。
要添加驗證,將為事件分配一個函數,該函數接收傳遞給$emit調用的參數,并返回一個布爾值以指示事件是否有效。
- app.component('custom-form', {
- emits: {
- // 沒有驗證
- click: null,
- // 驗證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事件
默認情況下,組件上的v-model使用modelValue作為props和update:modelValue做完事件。我們可以通過向v-model傳遞參數來修改這些名稱:
- <my-component v-model:title="bookTitle"></my-component>
在本例中,子組件將需要一個 title prop 并發出 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和事件為目標的能力,正如我們之前在v-model參數中所學的那樣,我們現在可以在單個組件實例上創建多個v-model綁定。
每個v-model將同步到不同的prop,而不需要在組件中添加額外的選項。
- <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有內置的修飾符——.trim,.number和.lazy。但是,在某些情況下,你可能還需要添加自己的自定義修飾符。
我們做個實例:將提供的字符串第一個字母大寫。
- <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 }
- }
- })
現在我們已經設置了 prop,我們可以檢查 modelModifiers 對象鍵并編寫一個處理器來更改發出的值。在下面的代碼中,每當<input/> 元素觸發 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')
對于帶參數的 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 }
- }
- })