本章節須要掌握組件基礎
emit我譯成發射,以爲發射這個詞比較形象的形容將子組件事件發射出來的一個動做。javascript
像組件和props
,事件名也會進行自動轉換,若是你在子組件裏發射一個駝峯命名的事件,你就能夠在父組件中添加一個短橫線分隔的監聽:css
this.$emit('myEvent')
<my-component @my-event="doSomething"></my-component>
由於有props
情形存在,模板內DOM議使用短橫線分隔命名方式。若是你使用字符串模板,則不存在這個限制。html
自定義事件發射(請子組件傳遞到父組件)能夠經過emits
選項:java
app.component('custom-form', { emits: ['inFocus', 'submit'] })
當在emits
中定義了一個原生事件(如click
)時,組件事件將會代替原生事件監聽。api
提示
推薦定義全部已發射的事件,以便記錄組件是如何工做的數組
同prop
類型驗證同樣,一個已發射事件若是經過對象語法而不是數組語法,也能夠被驗證。
添加一個驗證,事件會分配一個函數來接收參數,並傳遞給$emit
調用,返回一個布爾值來確認事件是否有效。app
app.component('custom-form', { emits: { // 無驗證 click: null, // 驗證提交事件 submit: ({ email, password }) => { if (email && password) { return true } else { console.warn('不合法的 submit 事件加載!') return false } } }, methods: { submitForm() { this.$emit('submit', { email, password }) } } })
v-model
參數默認組件的v-model
使用modelValue
做爲prop和update:modelValue
做爲事件。咱們能夠傳遞一個參數給v-model
修改這些名稱:less
<my-component v-model:title="bookTitle"></my-component>
app.component('my-component', { props: { title: String }, emits: ['update:title'], template: ` <input type="text" :value="title" @input="$emit('update:title', $event.target.value)"> ` })
在這個案例中,子組件會同步接收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)"> ` })
<my-component v-model:title="bookTitle"></my-component>
v-model
綁定正如前面所學習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)"> ` })
咱們來寫一個完整點的例子,實現一個區號-座機輸入組件,結果以下圖:
代碼以下:
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>component v-model</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <tel-input v-model:tel-number="telNumber" v-model:area-number="areaNumber"></tel-input> <p> {{areaNumber}}-{{telNumber}} </p> </div> </body> <script type="text/javascript"> const data_and_methods = { data() { return { telNumber: '', areaNumber: '' } }, methods: { } } const app = Vue.createApp(data_and_methods) app.component('tel-input',{ props: { areaNumber:String, telNumber:String }, emits: ['update:areaNumber','update:telNumber'], template: ` <input placeholder="區號" type="number" class="area-number" :value="areaNumber" @input="$emit('update:areaNumber',$event.target.value)" /> - <input placeholder="座機號碼" type="number" class="tel-number" :value="telNumber" @input="$emit('update:telNumber',$event.target.value)" /> ` }) app.mount("#app") </script> <style type="text/css"> .area-number {width:60px;} </style> </html>
v-model
修飾符在前面咱們學習輸入綁定時,v-model
有一些內置的修飾符如.trim
,.number
,.lazy
等。有些情形,你也想增長一些自定義的修飾符。
讓咱們來建立一個capitalize
修飾符,使用v-model
綁定將輸入首字母轉換爲大寫。
組件v-model
修飾符經過modelModifers
prop提供給組件。下面的例子,咱們建立了一個含有默認爲空對象 的modelModifiers
prop組件。
注意在組件created
生命週期勾子觸發器中,modelModifiers
prop包含capitalize
且值是true
- 當它被設置在v-model
綁定v-model.capitalize="myText"
。
<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
對象的鍵,而後經過方法處理要發射出去的值。下面咱們來把輸入框的首字母轉換爲大寫:
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>component v-model modifiers</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <my-component v-model.capitalize="myText"></my-component> <p>{{ myText }}</p> </div> </body> <script type="text/javascript"> const data_and_methods = { data() { return { myText: '' } } } const app = Vue.createApp(data_and_methods) app.component('my-component',{ props: { modelValue: String, modelModifiers: { default: () => ({}) } }, emits: ['update:modelValue'], template: ` <input type="text" :value="modelValue" @input="emitValue" /> `, 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) } }, created() { console.log(this.modelModifiers) } }) app.mount("#app") </script> </html>
v-model
綁定參數,生成的prop名將會是arg+"modelModifiers"
:
<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 } } })