Vue3中的常見(jiàn)組件通信之v-model使用詳解
Vue3中的常見(jiàn)組件通信之v-model
概述
? 在vue3中常見(jiàn)的組件通信有props、mitt、v-model、refs、parent、provide、inject、pinia、slot等。不同的組件關(guān)系用不同的傳遞方式。
常見(jiàn)的撘配形式如下表所示。
組件關(guān)系 | 傳遞方式 |
---|---|
父?jìng)髯?/td> | 1. props 2. v-model 3. $refs 4. 默認(rèn)插槽、具名插槽 |
子傳父 | 1. props 2. 自定義事件 3. v-model 4. $parent 5. 作用域插槽 |
祖?zhèn)鲗O、孫傳祖 | 1. $attrs 2. provide、inject |
兄弟間、任意組件間 | 1. mitt 2. pinia |
? props和自定義事件詳見(jiàn)本人另一篇文章:
Vue3中的常見(jiàn)組件通信之props和自定義事件
mitt用法詳見(jiàn)本人另一篇文章:
下面接著前面的文章繼續(xù)記錄v-model的用法。
v-model
v-model常用于普通html標(biāo)簽中的雙向綁定,這個(gè)綁定用法無(wú)法實(shí)現(xiàn)跨組件通信,v-model用在組件標(biāo)簽中的時(shí)候,可以實(shí)現(xiàn)父子間的組件通信,而這樣通信方式常用于UI組件庫(kù)。
要理解UI組件庫(kù)的v-model的雙向通信原理,需要先明白普通html標(biāo)簽中的v-model的底層原理。
普通HTML標(biāo)簽中v-model實(shí)現(xiàn)雙向綁定的底層原理
在普通html標(biāo)簽中用v-model可以實(shí)現(xiàn)數(shù)據(jù)的雙向綁定,如下代碼所示是把input輸入框里的數(shù)據(jù)與username進(jìn)行雙向綁定:
<template> <div class="father"> <h3>父組件</h3> <br> <input id="input1" type="text" v-model="username"> </div> </template> <script setup lang="ts" name="Father"> import { ref } from "vue"; // 數(shù)據(jù) let username = ref('zhansan') </script> <style scoped> .father { height: 300px; padding: 20px; color: #ffffff; text-align:center; background-image: url(https://xyyhxxx.oss-cn-beijing.aliyuncs.com/picGoImg/202406041301030.png); background-size: cover } #input1{ color: #000; } </style>
運(yùn)行后在瀏覽器打開vue開發(fā)者工具,如下圖所示:
上圖中更改vue開發(fā)者工具中的username的值頁(yè)面也會(huì)跟著發(fā)生變化,這個(gè)實(shí)現(xiàn)的是把數(shù)據(jù)呈現(xiàn)在頁(yè)面,如果修改input輸入框中的內(nèi)容,username的數(shù)據(jù)也會(huì)跟著發(fā)生改變,這個(gè)實(shí)現(xiàn)的是頁(yè)面?zhèn)飨驍?shù)據(jù),這就雙向綁定中的雙向,而實(shí)現(xiàn)這個(gè)雙向綁定的關(guān)鍵就是在于input標(biāo)簽中寫了v-model,如下所示:
<input id="input1" type="text" v-model="username">
而上面的代碼實(shí)現(xiàn)的底層原理是這樣的,先把上面的代碼改成如下圖所示:
<input id="input1" type="text" :value="username">
這樣可以實(shí)現(xiàn)數(shù)據(jù)呈現(xiàn)在頁(yè)面,數(shù)據(jù)修改頁(yè)面也會(huì)跟著修改,但是修改頁(yè)面,數(shù)據(jù)卻不會(huì)變化,這只實(shí)現(xiàn)了一個(gè)方向的數(shù)據(jù)綁定,接著再給input標(biāo)簽增加屬性,如下代碼:
<input id="input1" type="text" :value="username" @input="username=$event.target.value" >
這樣再測(cè)試,就會(huì)發(fā)現(xiàn)頁(yè)面中的數(shù)據(jù)也可以傳向數(shù)據(jù)了,修改input標(biāo)簽中的內(nèi)容,數(shù)據(jù)也會(huì)變化。
注意上面代碼中@input="@input="username=event.target.value"這句代碼 ts 會(huì)報(bào)警,我們需要處理一下,對(duì)event.target進(jìn)行斷言,報(bào)警就會(huì)消失:
<input id="input1" type="text" :value="username" @input="username=(<HTMLInputElement>$event.target).value" >
普通input標(biāo)簽中v-model實(shí)現(xiàn)雙向綁定的底層原理就是:value+@input事件。
組件標(biāo)簽中v-model中實(shí)現(xiàn)雙向綁定
首先準(zhǔn)備一個(gè)自己的UI組件,作為子組件,代碼如下:
<template> <input type="text"> </template> <script setup lang="ts" name="MyInput"> </script> <style scoped> input{ background-color:transparent; color: #ffffff; border: 0px; border-bottom: 1px solid #ffffff ; margin: 5px; } </style>
然后在父組件中引入:
//引入MyInput組件 import MyInput from "./MyInput.vue";
在父組件中把MyInput組件呈現(xiàn)在頁(yè)面中:
<label>用戶名:<MyInput/></label>
運(yùn)行效果如下:
這樣效果出來(lái)了,但是沒(méi)有還沒(méi)有實(shí)現(xiàn)數(shù)據(jù)綁定,首先在MyInput組件標(biāo)簽上增加:modelValue屬性和綁定@update:model-value事件,如下代碼:
<MyInput :modelValue="username" @update:model-value="username=$event"/>
然后需要在MyInput組件中聲明props和聲明事件來(lái)接收數(shù)據(jù)和事件:
//接收props defineProps(["modelValue"]) //聲明事件 let emit = defineEmits(['update:model-value'])
最后在MyInput組件中的普通html標(biāo)簽中添加:value屬性和綁定@input事件:
<input type="text" :value="modelValue" @input="emit('update:model-value',(<HTMLInputElement>$event.target).value)" >
至此,已經(jīng)實(shí)現(xiàn)了父組件和子組件MyInput組件的雙向通信,如下圖所示:
最后在父組件中的MyInput組件標(biāo)簽上可以直接簡(jiǎn)寫為如下代碼:
<MyInput v-model="username"/>
實(shí)現(xiàn)的效果是完全一樣的。
我們?cè)谟肬I組件庫(kù)的時(shí)候可以直接這樣寫,前提是UI組件庫(kù)已經(jīng)處理好了底層邏輯。
以下是完整代碼:
- 父組件:
<template> <div class="father"> <h3>父組件</h3> <br> <!-- <input id="input1" type="text" v-model="username"> --> <!-- 下面是v-model 的本質(zhì) --> <!-- <input id="input1" type="text" :value="username" @input="username=(<HTMLInputElement>$event.target).value" > --> <!-- 下面是v-model 的本質(zhì) --> <!-- <label>用戶名:<MyInput :modelValue="username" @update:model-value="username=$event"/></label> --> <label>用戶名:<MyInput v-model="username"/></label> </div> </template> <script setup lang="ts" name="Father"> import { ref } from "vue"; //引入MyInput組件 import MyInput from "./MyInput.vue"; // 數(shù)據(jù) let username = ref('zhansan') </script> <style scoped> .father { height: 300px; padding: 20px; color: #ffffff; text-align:center; background-image: url(https://xyyhxxx.oss-cn-beijing.aliyuncs.com/picGoImg/202406041301030.png); background-size: cover } #input1{ color: #000; } </style>
- MyInput組件:
<template> <input type="text" :value="modelValue" @input="emit('update:model-value',(<HTMLInputElement>$event.target).value)" > </template> <script setup lang="ts" name="MyInput"> //聲明props defineProps(["modelValue"]) //聲明事件 let emit = defineEmits(['update:model-value']) </script> <style scoped> input{ background-color:transparent; color: #ffffff; border: 0px; border-bottom: 1px solid #ffffff ; margin: 5px; } </style>
一個(gè)UI組件實(shí)現(xiàn)多個(gè)數(shù)據(jù)傳送
在父組件中可以改value,比如改成usName,如下代碼所示:
<MyInput v-model:usName="username"/>
這個(gè)代碼的本質(zhì)是如下代碼:
<MyInput :usName="username" @update:usName="username=$event"/>
在MyInput組件代碼中就需要改成如下代碼:
<template> <input type="text" :value="usName" @input="emit('update:usName',(<HTMLInputElement>$event.target).value)" > </template> <script setup lang="ts" name="MyInput"> //聲明props defineProps(["usName"]) //聲明事件 let emit = defineEmits(['update:usName']) </script>
這樣改完后運(yùn)行效果跟之前是完全一樣的,接下來(lái)再擴(kuò)展一下,父組件中的MyInput標(biāo)簽改成如下代碼:
<MyInput v-model:usName="username" v-model:paword="password"/>
然后在MyInput組件中代碼改成如下:
<template> <input type="text" :value="usName" @input="emit('update:usName',(<HTMLInputElement>$event.target).value)" > <br> <input type="text" :value="paword" @input="emit('update:paword',(<HTMLInputElement>$event.target).value)" > </template> <script setup lang="ts" name="MyInput"> //聲明props defineProps(["usName",'paword']) //聲明事件 let emit = defineEmits(['update:usName','update:paword']) </script>
這樣就實(shí)現(xiàn)一個(gè)組件內(nèi)雙向綁定兩個(gè)數(shù)據(jù)了,如下圖所示:
總結(jié)
v-model可以實(shí)現(xiàn)父子間的通信,v-model即可以設(shè)置在普通html標(biāo)簽中,也可以設(shè)置在組件標(biāo)簽中,設(shè)置在組件標(biāo)簽中可以實(shí)現(xiàn)父子間的雙向通信,前提是子組件底層做了處理。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue前端自適應(yīng)布局實(shí)現(xiàn)教程(一步到位所有自適應(yīng))
?自適應(yīng)布局是一種根據(jù)不同的設(shè)備屏幕分辨率進(jìn)行布局的方式,它為不同的屏幕分辨率定義了不同的布局,下面這篇文章主要給大家介紹了關(guān)于vue前端自適應(yīng)布局實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2024-08-08解決vue keep-alive 數(shù)據(jù)更新的問(wèn)題
今天小編就為大家分享一篇解決vue keep-alive 數(shù)據(jù)更新的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09前端vue3中的ref與reactive用法及區(qū)別總結(jié)
這篇文章主要給大家介紹了關(guān)于前端vue3中的ref與reactive用法及區(qū)別的相關(guān)資料,關(guān)于ref及reactive的用法,還是要在開發(fā)中多多使用,遇到響應(yīng)式失效問(wèn)題,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08Vue通過(guò)Blob對(duì)象實(shí)現(xiàn)導(dǎo)出Excel功能示例代碼
這篇文章主要介紹了Vue通過(guò)Blob對(duì)象實(shí)現(xiàn)導(dǎo)出Excel功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Vue 中v-model的完整用法及v-model的實(shí)現(xiàn)原理解析
這篇文章詳細(xì)介紹了Vue.js中的v-model指令的使用,包括基本用法、原理、結(jié)合不同類型的表單元素(如radio、checkbox、select)以及使用修飾符(如lazy、number、trim)等,感興趣的朋友一起看看吧2025-02-02ant?菜單組件報(bào)錯(cuò)Cannot?read?property?‘isRootMenu‘?of?undefin
這篇文章主要介紹了ant?菜單組件報(bào)錯(cuò)Cannot?read?property?‘isRootMenu‘?of?undefined解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08詳解vue如何使用rules對(duì)表單字段進(jìn)行校驗(yàn)
這篇文章主要介紹了詳解vue如何使用rules對(duì)表單字段進(jìn)行校驗(yàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10