亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue3的setup語(yǔ)法如何自定義v-model為公用hooks

 更新時(shí)間:2022年07月27日 09:37:50   作者:??油箱上的蔥花?  
這篇文章主要介紹了vue3的setup語(yǔ)法如何自定義v-model為公用hooks,文章分為兩個(gè)部分介紹,簡(jiǎn)單介紹vue3的setup語(yǔ)法如何自定義v-model和如何提取v-model語(yǔ)法作為一個(gè)公用hooks

前言

  • 基礎(chǔ)篇:簡(jiǎn)單介紹vue3setup語(yǔ)法如何自定義v-model;
  • 進(jìn)階篇:如何提取v-model語(yǔ)法作為一個(gè)公用hooks

基礎(chǔ)

基礎(chǔ)篇可繞過(guò),只是對(duì)于官網(wǎng)給出的教程,進(jìn)行了總結(jié)概括并給出demo

基本的v-model

子組件中滿足兩個(gè)點(diǎn),即可完成自定義雙向綁定:

  • props中定義一個(gè)值xxx
  • emit中定義一個(gè)update:xxx事件

下面我們來(lái)寫(xiě)一個(gè)最基本的v-model組件:

  • props中定義一個(gè)modelValue值,并綁定到inputvalue屬性上;
  • emit中定義一個(gè)update:modelValue事件

需要注意的是,當(dāng)modelValue作為props傳入,update:modelValue事件將被自動(dòng)注冊(cè)到emit事件中

<template>
??<input
????type="text"
????@input="emit('update:modelValue',?$event.target.value)"
????:value="props.modelValue"
??/>
</template>

<script?setup>
const?emit?=?defineEmits();
const?props?=?defineProps({
??modelValue:?String,
});
</script>

父組件中,引入modelComp子組件,并綁定test值到v-model上,test便完成了一次雙向綁定。

<template>
??<modelComp?v-model="test"></modelComp>
</template>

<script?setup>
import?{?ref,?watch?}?from?"vue";
import?modelComp?from?"./components/model/modelComp.vue";
const?test?=?ref("");
</script>

這便是一個(gè)最基本的自定義v-model組件;

多個(gè)v-model綁定

當(dāng)我們需要多個(gè)雙向綁定時(shí),如下:

<modelComp
??v-model="test"
??v-model:test1="test1"
??v-model:test2="test2"
></modelComp>

<script?setup>
import?{?ref,?watch?}?from?"vue";
import?modelComp?from?"./components/model/modelComp.vue";
const?test?=?ref("");
const?test1?=?ref("");
const?test2?=?ref("");
</script>

子組件中,同樣按著兩個(gè)點(diǎn)來(lái)定義:

  • props中定義兩個(gè)值,test1test2
  • emits中定義兩個(gè)事件,update:test1update:test2
<template>
??<input
????type="text"
????@input="emit('update:modelValue',?$event.target.value)"
????:value="props.modelValue"
??/>
??<input
????type="text"
????@input="emit('update:test1',?$event.target.value)"
????:value="props.test1"
??/>
??<input
????type="text"
????@input="emit('update:test2',?$event.target.value)"
????:value="props.test2"
??/>
</template>

<script?setup>
const?emit?=?defineEmits(["update:modelValue","update:test1",?"update:test2"]);
const?props?=?defineProps({
??modelValue:?String,
??test1:?String,
??test2:?String,
});
</script>

v-model修飾符

vue提供了一些v-model修飾符,我們可以在v-model中使用他們:

<modelComp
??v-model.trim="test"
??v-model:test1.lazy="test1"
??v-model:test2.trim.lazy="test2"
></modelComp>

在一些場(chǎng)景下,我們需要自己定義修飾符,來(lái)滿足我們的需求,舉個(gè)栗子:

<modelComp
??v-model.a="test"
??v-model:test1.b.c="test1"
></modelComp>

默認(rèn)v-model中我們綁定了a修飾符,v-model:test1中則綁定bc兩個(gè)修飾符;

對(duì)于修飾符,我們需要滿足以下條件:

  • 對(duì)于默認(rèn)v-model來(lái)說(shuō),需要props中定義兩個(gè)值
    • modelValue
    • modelModifiers,接受修飾符key
  • 對(duì)于自定義v-model:xxx來(lái)說(shuō),props中:
    • xxx
    • xxxModeifiers,接受修飾符key

由此,上代碼:

<template>
??<input?type="text"?@input="vModelInput"?:value="props.modelValue"?/>
??<input?type="text"?@input="vModelTest1"?:value="props.test1"?/>
</template>

<script?setup>
const?emit?=?defineEmits(["update:modelValue",?"update:test1"]);
const?props?=?defineProps({
??modelValue:?String,
??//接受v-model的修飾符
??modelModifiers:?{
????default:?()?=>?({}),
??},
??test1:?String,
??//接受v-model:test1的修飾符
??test1Modifiers:?{
????default:?()?=>?({}),
??}
});

const?vModelInput?=?(e)?=>?{
??let?value?=?e.target.value
??console.log(props.modelModifiers);
??//{a:true}
??if(props.modelModifiers.a){
??????//處理value值
??}
??emit("update:modelValue",?value);
};

const?vModelTest1?=?(e)?=>?{
??let?value?=?e.target.value
??console.log(props.test1Modifiers);
??//{b:true,c:true}
??if(props.modelModifiers.b){
??????//處理value值
??}
??if(props.modelModifiers.c){
??????//處理value值
??}
??emit("update:test1",?value);
};
</script>

進(jìn)階

問(wèn)題背景

基礎(chǔ)篇中已經(jīng)講解了如何封裝一個(gè)自定義v-model的組件,可是在實(shí)際開(kāi)發(fā)中,子組件中使用@input:value來(lái)綁定我們的值,會(huì)比較麻煩,有沒(méi)有更簡(jiǎn)單的辦法呢?

我們通常想要對(duì)需要雙向綁定的子組件,直接進(jìn)行v-model綁定:

<!--?子組件?-->
<input?type="text"?v-model="xxx"?/>

問(wèn)題來(lái)了,在子組件中接受到父組件的傳值時(shí),xxx我們應(yīng)該綁定誰(shuí)?直接綁定props.modelValue么?

<!--?子組件?-->
<input?type="text"?v-model="props.modelValue"/>

我們會(huì)得到一個(gè)錯(cuò)誤:

??reactivity.esm-bundler.js:512?Set?operation?on?key?"modelValue"?failed:?target?is?readonly.

因?yàn)?code>props是一個(gè)readonly的值(isReadonly(props) === true),所以我們不能直接這么使用

所以,我們是需要一個(gè)中間值來(lái)綁定v-model

方式一:通過(guò)watch中轉(zhuǎn)

借助內(nèi)部變量綁定v-model,使用watch監(jiān)聽(tīng)它,并同步數(shù)據(jù)props.xxx

<!--?子組件?-->
<template>
??<input?type="text"?v-model="proxy"?/>
</template>

<script?setup>
import?{?ref,?watch?}?from?"vue";
const?emit?=?defineEmits();
const?props?=?defineProps({
??modelValue:?String,
});

const?proxy?=?ref(props.modelValue);

watch(
??()?=>?proxy.value,
??(v)?=>?emit("update:modelValue",v)
);
</script>

因?yàn)橛袝r(shí)候我們雙向綁定的可能是一個(gè)對(duì)象或者數(shù)組,因此我們可以使用watch里的deep選項(xiàng)來(lái)深度監(jiān)聽(tīng)并同步proxy;

watch(
??()?=>?proxy.value,
??(v)?=>?emit("update:modelValue",v),
??{deep:true}
);

當(dāng)然,props.modelValue可能存在默認(rèn)值傳入,所以我們也可以加上immediate選項(xiàng),使得組件在創(chuàng)建時(shí),就直接給proxy賦上默認(rèn)值;

方式二:computed的get和set

我們也可以借助computed提供的getset來(lái)進(jìn)行數(shù)據(jù)同步

const?proxy?=?computed({
??get()?{
????return?props.modelValue;
??},
??set(v)?{
????emit("update:modelValue",?v);
??},
});

終極:封裝v-model的hooks

我們先來(lái)提取watch這種方式,將其封裝為一個(gè)hooks

<!--?子組件?-->
<template>
??<input?type="text"?v-model="proxy"?/>
</template>

<script?setup>
import?{?ref,?watch,?computed?}?from?"vue";
const?emit?=?defineEmits();
const?props?=?defineProps({
??modelValue:?String,
});

const?proxy?=?ref(props.modelValue);

watch(
??()?=>?proxy.value,
??(v)?=>?emit("update:modelValue",?v)
);
</script>

在子組件中,我們用v-modelinput上綁定了一個(gè)內(nèi)部值proxy,并以props.modelValue的值初始化proxy變量(ref(props.modelValue));

watch中,我們監(jiān)聽(tīng)input上的綁定值proxy,在input進(jìn)行輸入其值變化時(shí),向外分發(fā)emit('update:modelValue',v)事件,將改變的值動(dòng)態(tài)傳到外部組件上

提取公用邏輯

//?useVmodel1.js
import?{?ref,?watch?}?from?"vue";
export?function?useVmodel(props,?emit)?{
??const?proxy?=?ref(props.modelValue);
??watch(
????()?=>?proxy.value,
????(v)?=>?emit("update:modelValue",?v)
??);
??return?proxy;
}

一個(gè)最簡(jiǎn)單的hooks便被封裝好了;

<template>
??<input?type="text"?v-model="proxy"?/>
</template>

<script?setup>
import?{?ref,?watch,?computed?}?from?"vue";
import?{?useVmodel?}?from?"./hooks/useVmodel1";
const?emit?=?defineEmits();
const?props?=?defineProps({
??modelValue:?String,
});
const?proxy?=?useVmodel(props,?emit);
</script>

繼續(xù)抽離封裝

考慮到以下幾個(gè)點(diǎn),繼續(xù)進(jìn)行抽離封裝:

  • emit可以不傳,更簡(jiǎn)潔的調(diào)用方式
  • 多個(gè)v-model:test1這種情況的事件,emit("update:xxxx")中的xxxx事件名需要提取

我們可以通過(guò)vue3提供的getCurrentInstance方法,獲取當(dāng)前的組件實(shí)例,而modelValue可覆蓋,則抽取成變量:

//useVmodel2.js
import?{?ref,?watch,?getCurrentInstance?}?from?"vue";
export?function?useVmodel(props,?key?=?"modelValue",?emit)?{
??const?vm?=?getCurrentInstance();
??const?_emit?=?emit?||?vm?.emit;
??const?event?=?`update:${key}`;
??const?proxy?=?ref(props[key]);
??watch(
????()?=>?proxy.value,
????(v)?=>?_emit(event,?v)
??);
??return?proxy;
}

好了,現(xiàn)在我們可以更簡(jiǎn)單的調(diào)用我們的hooks了:

<!--?子組件?childModel?-->
<template>
??<input?type="text"?v-model="modelValue"?/>
??<input?type="text"?v-model="test"?/>
</template>

<script?setup>
import?{?useVmodel?}?from?"./hooks/useVmodel2";
const?emit?=?defineEmits();
const?props?=?defineProps({
??modelValue:?String,
??test:?String,
});
const?modelValue?=?useVmodel(props);
const?test?=?useVmodel(props,?"test");
</script>

<!--?父組件?-->
<template>
??<Model?v-model="modelValue"?v-model:test="test"?/>
</template>?

<script?setup>
import?{?ref,?watch?}?from?"vue";
import?Model?from?"./childModel.vue";

const?modelValue?=?ref("");
const?test?=?ref("");
</script>

到此這篇關(guān)于vue3的setup語(yǔ)法如何自定義v-model為公用hooks的文章就介紹到這了,更多相關(guān)vue自定義v-model內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue+axios 攔截器實(shí)現(xiàn)統(tǒng)一token的案例

    vue+axios 攔截器實(shí)現(xiàn)統(tǒng)一token的案例

    這篇文章主要介紹了vue+axios 攔截器實(shí)現(xiàn)統(tǒng)一token的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • vue前端HbuliderEslint實(shí)時(shí)校驗(yàn)自動(dòng)修復(fù)設(shè)置

    vue前端HbuliderEslint實(shí)時(shí)校驗(yàn)自動(dòng)修復(fù)設(shè)置

    這篇文章主要為大家介紹了vue前端中Hbulider中Eslint實(shí)時(shí)校驗(yàn)自動(dòng)修復(fù)設(shè)置操作過(guò)程,有需要的朋友可以借鑒參考下希望能夠有所幫助
    2021-10-10
  • 一篇文章帶你搞懂VUE基礎(chǔ)知識(shí)

    一篇文章帶你搞懂VUE基礎(chǔ)知識(shí)

    這篇文章主要介紹了vue 組件基礎(chǔ)知識(shí)的相關(guān)資料,幫助大家更好的理解和使用vue的組件,感興趣的朋友可以了解下
    2021-11-11
  • Vue+node實(shí)現(xiàn)音頻錄制播放功能

    Vue+node實(shí)現(xiàn)音頻錄制播放功能

    這篇文章主要介紹了Vue+node實(shí)現(xiàn)音頻錄制播放,功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Vue3?KeepAlive實(shí)現(xiàn)原理解析

    Vue3?KeepAlive實(shí)現(xiàn)原理解析

    KeepAlive?是一個(gè)內(nèi)置組件,那封裝一個(gè)組件對(duì)于大家來(lái)說(shuō)應(yīng)該不會(huì)有太大的困難,它的核心邏輯在于它的?render?函數(shù),它用?map?去記錄要緩存的組件,就是?[key,vnode]?的形式,這篇文章主要介紹了Vue3?KeepAlive實(shí)現(xiàn)原理,需要的朋友可以參考下
    2022-09-09
  • VSCode插件安裝完成后的配置(常用配置)

    VSCode插件安裝完成后的配置(常用配置)

    這篇文章主要介紹了VSCode插件安裝完成后的配置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • vue 彈出遮罩層樣式實(shí)例

    vue 彈出遮罩層樣式實(shí)例

    這篇文章主要介紹了vue 彈出遮罩層樣式實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • 基于Vue、Vuex、Vue-router實(shí)現(xiàn)的購(gòu)物商城(原生切換動(dòng)畫(huà))效果

    基于Vue、Vuex、Vue-router實(shí)現(xiàn)的購(gòu)物商城(原生切換動(dòng)畫(huà))效果

    這篇文章主要介紹了基于Vue、Vuex、Vue-router實(shí)現(xiàn)的購(gòu)物商城(原生切換動(dòng)畫(huà))效果,需要的朋友可以參考下
    2018-01-01
  • vue插件實(shí)現(xiàn)v-model功能

    vue插件實(shí)現(xiàn)v-model功能

    最近在開(kāi)發(fā)自己的富文本編輯器插件,在開(kāi)發(fā)中遇到了很多問(wèn)題其中我覺(jué)得比較好的問(wèn)題就是在你定義的插件中實(shí)現(xiàn)雙向綁定。這篇文章主要介紹了vue插件實(shí)現(xiàn)v-model功能,需要的朋友可以參考下
    2018-09-09
  • vue實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)實(shí)例代碼(防抖函數(shù)的應(yīng)用場(chǎng)景)

    vue實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)實(shí)例代碼(防抖函數(shù)的應(yīng)用場(chǎng)景)

    這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)的相關(guān)資料,主要是防抖函數(shù)的應(yīng)用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09

最新評(píng)論