說(shuō)說(shuō)在 Vue.js 中如何實(shí)現(xiàn)組件間通信

1 用法

假設(shè)父組件的模板包含子組件,我們可以通過(guò) props 來(lái)正向地把數(shù)據(jù)從父組件傳遞給子組件。props 可以是字符串?dāng)?shù)組,也可以是對(duì)象。

html:

<div id="app">
    <deniro-component message=""嫦娥四號(hào)"成功發(fā)射升空 飛向月球背面要登陸"></deniro-component>
</div>

js:

Vue.component('deniro-component', {
    props: ['message'],
    template:
        '<div>{{message}}</div>'
});


var app = new Vue({
    el: '#app',
    data: {}
});

渲染結(jié)果:

<div id="app"><div>"嫦娥四號(hào)"成功發(fā)射升空 飛向月球背面要登陸</div></div>

組件中的 props 與 data 函數(shù)的區(qū)別是:props 中的數(shù)組來(lái)自于父級(jí),而 data 函數(shù)是組件內(nèi)定義的數(shù)據(jù),所以它的作用域是組件本身。它們都可以在 template、computed 以及 methods 中使用。

如果需要傳遞多個(gè)數(shù)據(jù),直接在 props 數(shù)組中定義即可。

因?yàn)?HTML 不區(qū)分大小寫,所以當(dāng)使用 DOM 模板時(shí),建議直接使用短橫分隔(kebab-case)的命名方式來(lái)定義 props 參數(shù)名稱。

html:

<div id="app2">
    <deniro-component2 special-message="微軟向谷歌投降重構(gòu)Edge 但I(xiàn)E瀏覽器為何將長(zhǎng)存"></deniro-component2>
</div>

js:

Vue.component('deniro-component2', {
    props: ['specialMessage'],
    template:
        '<div>{{specialMessage}}</div>'
});


var app2 = new Vue({
    el: '#app2',
    data: {}
});

注意:如果使用的是字符串模板,那么可以忽略這個(gè)限制。

有時(shí)候,傳遞過(guò)來(lái)的數(shù)據(jù)來(lái)自于父級(jí)的動(dòng)態(tài)數(shù)據(jù),這是我們可以使用 v-bind 來(lái)動(dòng)態(tài)綁定 props 中的數(shù)據(jù)。

html:

<div id="app3">
    <input type="text" v-model="parentMessage">
    <deniro-component3 :message="parentMessage"></deniro-component3>
</div>

js:

Vue.component('deniro-component3', {
    props: ['message'],
    template:
        '<div>{{message}}</div>'
});


var app3 = new Vue({
    el: '#app3',
    data: {
        parentMessage:''
    }
});

效果:

這里我們使用 v-model 綁定了父級(jí)數(shù)據(jù) parentMessage。所以當(dāng)在輸入框中鍵入的內(nèi)容,也會(huì)同步傳遞給子組件。

注意:如果不使用 v-bind 來(lái)傳遞數(shù)字、布爾對(duì)象、數(shù)組或者對(duì)象,那么傳遞的僅僅是字符串!

html:

<div id="app4">
    <deniro-component4 :message="['a','b','c']"></deniro-component4>
    <deniro-component4 message="['a','b','c']"></deniro-component4>
</div>

js:

Vue.component('deniro-component4', {
    props: ['message'],
    template:
        '<div>參數(shù)類型:{{typeof message}};參數(shù)長(zhǎng)度:{{message.length}}</div>'
});


var app4 = new Vue({
    el: '#app4',
    data: {}
});

輸出結(jié)果:

參數(shù)類型:object;參數(shù)長(zhǎng)度:3
參數(shù)類型:string;參數(shù)長(zhǎng)度:13

2 改變單向數(shù)據(jù)流

Vue2.x 中,通過(guò) props 傳遞的數(shù)據(jù)是單向的,也就是說(shuō),如果父組件中的數(shù)據(jù)發(fā)生變化,那么也會(huì)影響到子組件中的數(shù)據(jù)。

有時(shí)候,因?yàn)闃I(yè)務(wù)場(chǎng)景的要求,我們需要改變這種單向數(shù)據(jù)流的設(shè)計(jì)。

2.1 作為初始值

子組件把父組件傳遞過(guò)來(lái)的值作為初始值,然后在自己的作用域內(nèi)隨意修改與使用它。這可以通過(guò)在子組件的 data 內(nèi)定義一個(gè)新數(shù)據(jù),用于引用父組件中的參數(shù)。

html:

<div id="app5">
    <deniro-component5 :init-value="0"></deniro-component5>
</div>

js:

Vue.component('deniro-component5', {
    props: ['initValue'],
    template:
        '<div>初始值:{{initValue}};<button @click="counter++">{{counter}}</button></div>',
    data:function () {
        return {
            counter:this.initValue
        }
    }
});

var app5 = new Vue({
    el: '#app5',
    data: {}
});

效果:

組件中定義了 counter,它被初始化為傳入的 initValue,初始化之后,counter 就與 initValue 無(wú)關(guān)啦O(∩_∩)O~

2.2 轉(zhuǎn)換后傳入

有時(shí)候,我們必須把 props 中的值轉(zhuǎn)換后傳入子組件,這可以通過(guò)計(jì)算屬性來(lái)實(shí)現(xiàn)。

html:

<div id="app6">
    <deniro-component6 :border="5" :width="200"></deniro-component6>
</div>

js:

Vue.component('deniro-component6', {
    props: ['border', 'width'],
    template:
        '<div :style="style">一個(gè)算法通吃三大棋類</div>',
    computed: {
        style: function () {
            return {
                border: this.border + 'px solid red',
                width: this.width + 'px'
            }
        }
    }
});

var app6 = new Vue({
    el: '#app6',
    data: {}
});

效果:

注意:在 JS 中,對(duì)象與數(shù)組是引用類型,即子組件中定義的變量如果賦值的是這些類型,那么改變這些變量的值,是會(huì)影響到父組件的!

3 驗(yàn)證

我們自定義的組件,如果需要提供給第三方使用,那么最好進(jìn)行參數(shù)驗(yàn)證,這就需要用到對(duì)象寫法。如果驗(yàn)證失敗,那么會(huì)在瀏覽器的控制臺(tái)輸出警告日志。

html:

<div id="app7">
    <deniro-component7 :a="'str'"></deniro-component7>
</div>

js:

<script src="https://cdn.bootcss.com/vue/2.2.2/vue.js"></script>
<script>
    Vue.component('deniro-component7',{
       props:{
           a:Number
       },
        template:
            '<div >{{a}}</div>',
    });

    var app7 = new Vue({
        el: '#app7',
        data: {}
    });
</script>

注意:這里引入了開發(fā)版的 vue.js(生產(chǎn)版一般是 vue.min.js)。

控制臺(tái)輸出:

其它示例:

Vue.component('deniro-component8', {
    props: {
        //必須是數(shù)字類型
        a: Number,
        //數(shù)字類型或者字符串類型
        b: [Number, String],
        //布爾類型,默認(rèn)值為 true
        c: {
            type: Boolean,
            default: true
        },
        //字符串類型,必須傳值
        d: {
            type: String,
            required: true
        },
        //自定義
        e: {
            validator: function (v) {
                return v > 1;
            }
        }
    }
});

type 可以為這些類型:String、Number、Boolean、Object、Array、Function。


以上示例 DEMO

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容