Vue自定義組件實(shí)現(xiàn)?v-model?的幾種方式
前言
在 Vue 中,v-model 是一個(gè)常用的指令,用于實(shí)現(xiàn)表單元素和組件之間的雙向綁定。當(dāng)我們使用原生的表單元素時(shí),直接使用 v-model 是很方便的,但是對(duì)于自定義組件來(lái)說(shuō),要實(shí)現(xiàn)類似的雙向綁定功能就需要一些額外的處理。
本篇文章將介紹幾種在自定義組件中實(shí)現(xiàn) v-model 的方式,主要如下:
使用
v-model
屬性:適用于表單元素定義
model
屬性:適用于非表單元素
除了以上的兩種方式外,還有我們通常使用的.sync 修飾符(2.3.0+ 新增),主要區(qū)別在于使用方式的不同,前者直接使用 v-model,后者使用 .sync
修飾符進(jìn)行綁定
一. 單向數(shù)據(jù)流
所有的 prop 都使得其父子 prop 之間形成了一個(gè)單向下行綁定:父級(jí) prop 的更新會(huì)向下流動(dòng)到子組件中,但是反過(guò)來(lái)則不行。這樣會(huì)防止從子組件意外變更父級(jí)組件的狀態(tài),從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。
注意:每次父級(jí)組件發(fā)生變更時(shí),子組件中所有的 prop 都將會(huì)刷新為最新的值。這意味著你不應(yīng)該在一個(gè)子組件內(nèi)部改變 prop。雖然可以,但是如果你這樣做了,Vue 會(huì)在瀏覽器的控制臺(tái)中發(fā)出警告。
二. 基礎(chǔ)原理淺析
v-model 實(shí)際上就是 props:value
和 $emit('input')
的組合語(yǔ)法糖,簡(jiǎn)單來(lái)說(shuō),v-model 的使用其實(shí)做了兩個(gè)比較重要的操作,理解這兩個(gè)操作,我們就可以輕松實(shí)現(xiàn)組件的自定義 v-model
v-bind 綁定 value 屬性的值 - props:value;
v-on 綁定 input 事件監(jiān)聽(tīng)到函數(shù)中,函數(shù)會(huì)獲取最新的值賦值到綁定的屬性中 - $emit('input');
三. 實(shí)現(xiàn) v-model 的兩種方式
1. 直接使用 v-model 屬性
以 input 表單元素為例,在 vue 中,我們可以直接使用 v-model 進(jìn)行綁定數(shù)據(jù),當(dāng)我們?cè)趯?shí)現(xiàn)自定義組件custom-component
進(jìn)行封裝 input 時(shí),我們的組件對(duì)外暴露時(shí)也需要使用 v-model,看下面我們應(yīng)該如何實(shí)現(xiàn):
在自定義組件中,我們可以通過(guò)在組件內(nèi)部使用 value 屬性和手動(dòng)觸發(fā) input 事件來(lái)實(shí)現(xiàn) v-model 的雙向綁定效果。具體實(shí)現(xiàn)如下:
<template> <input v-model="newValue" /> </template> <script> export default { props: { value: { type: Boolean, default: false, }, }, computed: { newValue: { get() { return this.value; }, set(val) { this.$emit("input", val); }, }, }, }; </script>
使用custom-component
<custom-component v-model="newValue" />
在上述代碼中,我們通過(guò) value 屬性接收父組件傳入的值,并且使用 computed 的 set 屬性用來(lái)監(jiān)聽(tīng)值的更新,手動(dòng)觸發(fā) $emit('input', value)
來(lái)將新值傳遞給父組件,從而實(shí)現(xiàn)雙向綁定的效果。
2. 定義 model 屬性
Vue 允許我們?cè)诙x組件中通過(guò)定義 model 屬性來(lái)簡(jiǎn)化 v-model 的使用。通過(guò)定義 model 屬性,我們可以指定組件中哪個(gè)屬性的值應(yīng)該作 v-model 的值。
假如我們實(shí)現(xiàn)一個(gè)計(jì)數(shù)器的組件custom-counter
,在頁(yè)面中顯示兩個(gè)按鈕,點(diǎn)擊按鈕可以進(jìn)行數(shù)值的加減操作,具體示例如下:
<template> <div> <button @click="increment">+</button> <span>{{ value }}</span> <button @click="decrement">-</button> </div> </template> <script> export default { // 當(dāng) model 為默認(rèn)值時(shí),可以將其省略 model: { prop: "value", // 默認(rèn)是 value event: "input", // 默認(rèn)是 input }, props: { value: { type: Number, default: 0, }, }, methods: { increment() { this.$emit("input", this.value + 1); }, decrement() { this.$emit("input", this.value - 1); }, }, }; </script>
提示:當(dāng) model 為默認(rèn)值時(shí),可以將其省略
父組件中使用custom-counter
<template> <div> <custom-counter v-model="count"></custom-counter> <p>計(jì)數(shù)器的值為:{{ count }}</p> </div> </template> <script> import CustomCounter from "./CustomCounter.vue"; export default { components: { CustomCounter, }, data() { return { count: 0, }; }, }; </script>
演示效果如下圖所示:
在上面的示例中,CustomCounter
組件接收一個(gè)value
屬性來(lái)接收父組件傳遞的值,并在點(diǎn)擊按鈕時(shí)修改value
屬性的值。通過(guò)調(diào)用this.$emit('input', newValue)
觸發(fā)input
事件,將新的value
值傳遞給父組件進(jìn)行更新。
在父組件中,使用v-model
將父組件中的count
屬性綁定到CustomCounter
組件的value
屬性上,綁定 input 事件監(jiān)聽(tīng)到函數(shù)中,從而實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定。
model 是允許 vue 自定義組件使用 v-model 的關(guān)鍵,雖然有時(shí)我們不顯性的使用它,也不影響我們?cè)谧远x組件中使用 v-model 指令,這只是因?yàn)楸辉O(shè)置默認(rèn)值。而有的時(shí)候,顯示的使用,并自定義 model 的 prop 和 event 會(huì)有益。
注意:允許一個(gè)自定義組件在使用 v-model 時(shí)定制 prop 和 event。默認(rèn)情況下,一個(gè)組件上的 v-model 會(huì)把 value 用作 prop 且把 input 用作 event,但是一些輸入類型比如單選框和復(fù)選框按鈕可能想使用 value prop 來(lái)達(dá)到不同的目的。使用 model 選項(xiàng)可以回避這些情況產(chǎn)生的沖突。
四. .sync 修飾符
在有些情況下,我們可能需要對(duì)一個(gè) prop 進(jìn)行 “雙向綁定”。但是,真正的雙向綁定會(huì)帶來(lái)維護(hù)上的問(wèn)題,因?yàn)樽咏M件可以變更父組件,且在父組件和子組件兩側(cè)都沒(méi)有明顯的變更來(lái)源。
這也是為什么我們推薦以 update:myPropName
的模式觸發(fā)事件取而代之。
舉個(gè)例子,還是上面的計(jì)數(shù)器的例子,在一個(gè)包含 count
prop 的計(jì)數(shù)組件中,我們可以用以下方法表達(dá)對(duì)其賦新值的意圖:
this.$emit("update:count", newCount);
然后父組件可以監(jiān)聽(tīng)那個(gè)事件并根據(jù)需要更新一個(gè)本地的數(shù)據(jù) property。例如:
<custom-counter v-bind:count="count" v-on:update:count="count = $event" />
我們?yōu)檫@種模式提供一個(gè)縮寫,即 .sync 修飾符,如下:
<custom-counter :count.sync="count"></custom-counter>
以上的兩種寫法是等價(jià)的
注意:帶有 .sync 修飾符的 v-bind 不能和表達(dá)式一起使用 (例如 v-bind:count.sync=”count + 1” 是無(wú)效的)。取而代之的是,你只能提供你想要綁定的 property 名,類似 v-model。
五. 總結(jié)
本篇文章介紹了在 Vue 自定義組中實(shí)現(xiàn) v-model 的幾種方式,包括定義 model 屬性和使用 v-model 屬性。通過(guò)以上案例實(shí)際分析,相信大家都已經(jīng)了解這幾種方式的創(chuàng)建以及應(yīng)用場(chǎng)景,以便更加靈活地應(yīng)用到實(shí)際項(xiàng)目中。
以上面兩種方式為例,我們可以靈活地根據(jù)自己的需求選擇合適的方式來(lái)實(shí)現(xiàn)自定義組件 v-model。如果是表單元素,可以直接使用 v-model 屬性;如果是非表單元素,可以通過(guò)定義 model 屬性指定組件中哪個(gè)屬性的值應(yīng)該作 v-model 的值。
除此之外,使用 .sync
修飾符也是進(jìn)行自定義組件雙向綁定的優(yōu)秀選擇,因此在實(shí)際開發(fā)中,選擇適合自己項(xiàng)目需求的方式是最重要的。
以上就是Vue自定義組件實(shí)現(xiàn) v-model 的幾種方式的詳細(xì)內(nèi)容,更多關(guān)于Vue實(shí)現(xiàn)v-model的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在?Vue?項(xiàng)目中如何引用?assets?文件夾中的圖片(方式匯總)
Vue中引用assets文件夾中的圖片有多種方式,在.vue文件的模板部分,使用相對(duì)路徑或通過(guò)@別名引用圖片,在CSS中,通過(guò)相對(duì)路徑或@別名引用圖片作為背景,在JavaScript中,通過(guò)import語(yǔ)句導(dǎo)入圖片資源,并使用v-bind在模板中綁定顯示,這些方法均可有效管理和引用項(xiàng)目中的圖片資源2024-09-09VUE-ElementUI?時(shí)間區(qū)間選擇器的使用
這篇文章主要介紹了VUE-ElementUI?時(shí)間區(qū)間選擇器的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05對(duì)vue中v-on綁定自定事件的實(shí)例講解
今天小編就為大家分享一篇對(duì)vue中v-on綁定自定事件的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vue簡(jiǎn)明介紹配置對(duì)象的配置選項(xiàng)
我們知道每一個(gè)vue項(xiàng)目應(yīng)用都是通過(guò)vue的構(gòu)造函數(shù)進(jìn)行創(chuàng)建一個(gè)新的vue項(xiàng)目的。創(chuàng)建vue實(shí)例的配置對(duì)象,可以包括一下屬性選項(xiàng),比如:data、methods、watch、template等等,每一個(gè)選項(xiàng)都有不同的功能,大家可以根據(jù)自己的需求選擇不同的配置2022-08-08Vue-cli assets SubDirectory及PublicPath區(qū)別詳解
這篇文章主要介紹了Vue-cli assets SubDirectory及PublicPath區(qū)別詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08vuex狀態(tài)管理數(shù)據(jù)狀態(tài)查詢與更改方式
這篇文章主要介紹了vuex狀態(tài)管理數(shù)據(jù)狀態(tài)查詢與更改方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue3+ts+element-plus實(shí)際開發(fā)之統(tǒng)一調(diào)用彈窗封裝的詳細(xì)過(guò)程
這篇文章主要介紹了vue3+ts+element-plus實(shí)際開發(fā)之統(tǒng)一調(diào)用彈窗封裝的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-03-03在vue項(xiàng)目中使用Nprogress.js進(jìn)度條的方法
NProgress.js是輕量級(jí)的進(jìn)度條組件,使用簡(jiǎn)便,可以很方便集成到單頁(yè)面應(yīng)用中。這篇文章主要介紹了在vue項(xiàng)目中使用Nprogress.js進(jìn)度條的方法,需要的朋友可以參考下2018-01-01