Vue自定義屬性實(shí)例分析
本文實(shí)例講述了Vue自定義屬性。分享給大家供大家參考,具體如下:
1 事件名
跟組件和 prop 不同,事件名不存在任何自動化的大小寫轉(zhuǎn)換。而是觸發(fā)的事件名需要完全匹配監(jiān)聽這個(gè)事件所用的名稱。舉個(gè)例子,如果觸發(fā)一個(gè) camelCase 名字的事件:
this.$emit('myEvent')
則監(jiān)聽這個(gè)名字的 kebab-case 版本是不會有任何效果的:
<my-component v-on:my-event="doSomething"></my-component>
跟組件和 prop 不同,事件名不會被用作一個(gè) JavaScript 變量名或?qū)傩悦?,所以就沒有理由使用 camelCase 或 PascalCase 了。并且 v-on 事件監(jiān)聽器在 DOM 模板中會被自動轉(zhuǎn)換為全小寫 (因?yàn)?HTML 是大小寫不敏感的),所以 v-on:myEvent 將會變成 v-on:myevent——導(dǎo)致 myEvent 不可能被監(jiān)聽到。
因此,我們推薦你始終使用 kebab-case 的事件名。
2 自定義組件的 v-model
2.2.0+ 新增
一個(gè)組件上的 v-model 默認(rèn)會利用名為 value 的 prop 和名為 input 的事件,但是像單選框、復(fù)選框等類型的輸入控件可能會將 value 特性用于不同的目的。model 選項(xiàng)可以用來避免這樣的沖突:
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)"
>
`
});
現(xiàn)在在這個(gè)組件上使用 v-model 的時(shí)候:
<base-checkbox v-model="loving"></base-checkbox>
這里的 loving 的值將會傳入這個(gè)名為 checked 的 prop。同時(shí)當(dāng) <base-checkbox> 觸發(fā)一個(gè) change 事件并附帶一個(gè)新的值的時(shí)候,這個(gè) loving 的屬性將會被更新。
注意你仍然需要在組件的 props 選項(xiàng)里聲明 checked 這個(gè) prop。
3 將原生事件綁定到組件
你可能有很多次想要在一個(gè)組件的根元素上直接監(jiān)聽一個(gè)原生事件。這時(shí),你可以使用 v-on 的 .native 修飾符:
<base-input v-on:focus.native="onFocus"></base-input>
在有的時(shí)候這是很有用的,不過在你嘗試監(jiān)聽一個(gè)類似 <input> 的非常特定的元素時(shí),這并不是個(gè)好主意。比如上述<base-input>組件可能做了如下重構(gòu),所以根元素實(shí)際上是一個(gè) <label> 元素:
<label>
{{ label }}
<input
v-bind=$attrs",
v-bind:value="value"
v-on:input="$emit('input',$event.target.value)"
>
</label>
這時(shí),父級的 .native 監(jiān)聽器將靜默失敗。它不會產(chǎn)生任何報(bào)錯(cuò),但是 onFocus 處理函數(shù)不會如你預(yù)期地被調(diào)用。
為了解決這個(gè)問題,Vue 提供了一個(gè) $listeners 屬性,它是一個(gè)對象,里面包含了作用在這個(gè)組件上的所有監(jiān)聽器。例如:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
有了這個(gè) $listeners 屬性,你就可以配合 v-on="$listeners" 將所有的事件監(jiān)聽器指向這個(gè)組件的某個(gè)特定的子元素。對于類似 <input> 的你希望它也可以配合 v-model 工作的組件來說,為這些監(jiān)聽器創(chuàng)建一個(gè)類似下述inputListeners 的計(jì)算屬性通常是非常有用的:
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this;
//Object.assign() 會將所有的對象合并為一個(gè)新對象
return Object.assign({},
//從父級添加所有的監(jiān)聽器
this.$listeners,
//添加自定義監(jiān)聽器或復(fù)寫監(jiān)聽器行為
{
input: function (event) {
vm.$emit('input', event.target.value);
}
}
)
}
},
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
</label>
`
});
現(xiàn)在 <base-input> 組件是一個(gè)完全透明的包裹器了,也就是說它可以完全像一個(gè)普通的 <input> 元素一樣使用了:所有跟它相同的特性和監(jiān)聽器的都可以工作。
4 .sync 修飾符
2.3.0+ 新增
在有些情況下,我們可能需要對一個(gè) prop 進(jìn)行“雙向綁定”。不幸的是,真正的雙向綁定會帶來維護(hù)上的問題,因?yàn)樽咏M件可以修改父組件,且在父組件和子組件都沒有明顯的改動來源。
這也是為什么我們推薦以 update:my-prop-name 的模式觸發(fā)事件取而代之。舉個(gè)例子,在一個(gè)包含 title prop 的假設(shè)的組件中,我們可以用以下方法表達(dá)對其賦新值的意圖:
this.$emit('update:title', newTitle)
然后父組件可以監(jiān)聽那個(gè)事件并根據(jù)需要更新一個(gè)本地的數(shù)據(jù)屬性。例如:
<text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event" ></text-document>
為了方便起見,我們?yōu)檫@種模式提供一個(gè)縮寫,即 .sync 修飾符:
<text-document v-bind:title.sync="doc.title"></text-document>
當(dāng)我們用一個(gè)對象同時(shí)設(shè)置多個(gè) prop 的時(shí)候,也可以將這個(gè) .sync 修飾符和 v-bind 配合使用:
<text-document v-bind.sync="doc"></text-document>
這樣會把 doc 對象中的每一個(gè)屬性 (如 title) 都作為一個(gè)獨(dú)立的 prop 傳進(jìn)去,然后各自添加用于更新的 v-on 監(jiān)聽器。
將 v-bind.sync 用在一個(gè)字面量的對象上,例如v-bind.sync=”{ title: doc.title }”,是無法正常工作的,因?yàn)樵诮馕鲆粋€(gè)像這樣的復(fù)雜表達(dá)式的時(shí)候,有很多邊緣情況需要考慮。
希望本文所述對大家vue.js程序設(shè)計(jì)有所幫助。
相關(guān)文章
一看就會的vuex實(shí)現(xiàn)登錄驗(yàn)證(附案例)
vue項(xiàng)目中如何調(diào)用多個(gè)不同的ip接口
vue使用axios?post發(fā)送json數(shù)據(jù)跨域請求403的解決方案
關(guān)于Element上傳組件beforeUpload上傳前限制失效問題
vue+elementUI實(shí)現(xiàn)多文件上傳與預(yù)覽功能實(shí)戰(zhàn)記錄(word/PDF/圖片/docx/doc/xlxs/txt)

