Vue自定義組件實(shí)現(xiàn)v-model指令

Tips: 本文所描述的Vue均默認(rèn)是Vue2版本

在我們初次接觸Vue的時(shí)候,一定會(huì)了解到一個(gè)語(yǔ)法糖,那就是v-model指令,它帶給我們的第一印象就是它可以實(shí)現(xiàn)雙向綁定

那么,什么是雙向綁定?通俗一點(diǎn)來(lái)說(shuō),就是當(dāng)數(shù)據(jù)發(fā)生變化的時(shí)候,視圖同時(shí)發(fā)生變化,這可以說(shuō)是Vue的精髓之處了(不過(guò)關(guān)于雙向綁定,后續(xù)可以出一篇更為詳盡的博文來(lái)深入模擬一下Vue的實(shí)現(xiàn),這里重點(diǎn)還是探討實(shí)現(xiàn)自定義組件的v-model指令)

所以,在我們深入使用Vue之后,編寫一個(gè)自定義組件,如何手動(dòng)實(shí)現(xiàn)一個(gè)v-model的指令呢,今天我們就來(lái)詳細(xì)探討一下

v-model指令的原理是什么?

  1. v-bind綁定一個(gè)value屬性
  2. v-on監(jiān)聽當(dāng)前元素的input事件,當(dāng)數(shù)據(jù)變化時(shí),將值傳遞給value實(shí)時(shí)更新數(shù)據(jù)

v-modelv-bind:value有什么區(qū)別?

自定義組件中,必定會(huì)使用v-bind指令來(lái)實(shí)現(xiàn)組件之間值的傳遞,所以在我還是菜鳥的那段時(shí)間,我一直有個(gè)疑惑,既然有的v-bind指令,為什么還需要在自定義的組件中實(shí)現(xiàn)v-model指令呢?在我實(shí)踐了一番之后,我才明白,v-model既能夠?qū)崿F(xiàn)值的傳遞,也能夠?qū)崿F(xiàn)頁(yè)面數(shù)據(jù)的實(shí)時(shí)變化,而v-bind只是實(shí)現(xiàn)值的傳遞,如果需要實(shí)現(xiàn)實(shí)時(shí)變化的效果,需要使用另外的方法修改變量的值,可以總結(jié)為下面兩點(diǎn)

  1. v-model實(shí)現(xiàn)視圖和數(shù)據(jù)的雙向綁定,一者變化另一者也會(huì)同時(shí)變化
  2. v-bind只會(huì)在初始化的時(shí)候?qū)?shù)據(jù)綁定到視圖上,后續(xù)視圖變化不會(huì)影響數(shù)據(jù)

擼一個(gè)v-model

看到這里,相信你也理解了為什么我們會(huì)需要在自定義的組件中自定義一個(gè)v-model指令,下面我們通過(guò)一個(gè)簡(jiǎn)易的示例來(lái)擼一個(gè)v-model,在此之前我們需要在一個(gè)空Vue項(xiàng)目中,定義一個(gè)dad.vue文件,以及child.vue文件。為了方便初學(xué)者學(xué)習(xí),我將一個(gè)完整的簡(jiǎn)易示例項(xiàng)目放到了github倉(cāng)庫(kù)中供大家下載學(xué)習(xí),大家如果喜歡可以為了點(diǎn)一顆Star,Thanks?(?ω?)?!!!

<span id="jumpId-dad"></span>

dad.vue

<template>
    <div>
        <child v-model='childName'></child>
    </div>
</template>

<script>
    import child from './child.vue';
    export default {
        name: 'dad',
        components: {
            child
        },
        data() {
            return {
                childName: '我是兒子'
            };
        },
        methods: {}
    };
</script>

<span id="jumpId-child"></span>

child.vue

<template>
    <!-- vue中的自定義組件中,若父組件中用v-model的話,其實(shí)相當(dāng)于v-bind:value='***'并且v-on:input='***' -->
    <!-- 因此子組件內(nèi)部用props接收value值,用$emit觸發(fā)input事件,默認(rèn)傳遞value值和input事件是模擬v-model的默認(rèn)規(guī)則 -->
    <!-- 基礎(chǔ)知識(shí)提示:@是v-on監(jiān)聽事件的簡(jiǎn)寫,:是v-bind綁定屬性的簡(jiǎn)寫 -->
    <div class="box-v-model">
        <input type="text" class="input-v-model" :value="value" @input="inputChange" />
        <!-- 簡(jiǎn)寫的方式 -->
        <!-- <input type="text" @input="value=$event.target.value" :value="value" /> -->
        <div>{{ value }}</div>
    </div>
</template>

<script>
    export default {
        name: "child",
        props: {
            value: {
                type: String
            }
        },
        methods: {
            // $emit 方法可以觸發(fā)當(dāng)前實(shí)例上的事件,這里觸發(fā)的事input事件,附加參數(shù)都會(huì)傳給監(jiān)聽器回調(diào)
            // input 事件在用戶輸入時(shí)觸發(fā),它是在元素值發(fā)生變化時(shí)立即觸發(fā)
            inputChange(e) {
                this.$emit("input", e.target.value);
            }
        }
    }
</script>

參考文檔一 ———— vue自定義組件中的v-model
參考文檔二 ———— Vue中v-model和v-bind:value的區(qū)別以及手動(dòng)實(shí)現(xiàn)v-model
參考文檔三 ———— Vue官方文檔關(guān)于$emit的說(shuō)明

我是 fx67ll.com,如果您發(fā)現(xiàn)本文有什么錯(cuò)誤,歡迎在評(píng)論區(qū)討論指正,感謝您的閱讀!
如果您喜歡這篇文章,歡迎訪問(wèn)我的 本文github倉(cāng)庫(kù)地址,為我點(diǎn)一顆Star,Thanks~ :)
轉(zhuǎn)發(fā)請(qǐng)注明參考文章地址,非常感謝!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。