1. 程式人生 > >vue2.0中的元件通訊

vue2.0中的元件通訊

vue中元件是模組化開發的基礎,在元件A中使用了元件B,那他們必然需要資料通訊,父元件要將資料傳遞給自組建,子元件要通知父元件自己內部發生的事情。

在vue.js中父子元件的關係可以總結為props down, events up,父元件通過props向下傳遞資料給子元件,子元件通過events給父元件反饋訊息,引用官方的一張圖,來看看他們是怎麼工作的

1、父子元件通訊

①父元件向子元件傳遞資料,子元件需要顯式的用props選項宣告它期待接受的資料

父元件傳遞資料:

<parent> 
    <child :msg="msg"></child>
</parent>

export
default { data() { return { msg: [1, 2, 3] } } } 子元件接收資料: export default { props: { msg: { type: Array, default() { return [] // 這裡可以寫預設值 } } } }

初學者常犯的錯誤是使用字面量語法傳遞數值

<child some-props
="1">
</child>

它是一個字面prop,傳遞的是字串1,而不是number,如果想傳遞number型別的數值,需要使用v-bind。把它的值當作JaveScript表示式計算:

<child v-bind:some-props="1"></child>

在vue中,子元件是不允許直接修改父元件通過props傳遞過來的資料,這樣會導致父元件和子元件耦合,並且父元件的資料可能會被任意子元件修改,另外每次父元件更新,子元件相應的props都會更新為最新值。之所以想修改props中的資料是因為:

1、我們希望把props中的資料當作區域性資料使用

2、希望把props中的資料處理成其他資料使用

對於這兩種方式我們應該正確的處理為:

定義一個區域性變數,並用props的值初始化它
props: {
    someProp: {
        type: String,
        default: ""
    }
},
data () {
    return {
        initData: this.someProp
    }
}

定義一個computed,處理props的值並返回
props: {
    someProp: {
        type: String,
        default: ""
    }
},
computed: {
    normalData() {
        return this.someProp.trim().toLowerCase()
    }
}

需要注意的是:JavaScript中陣列和物件是引用型別,指向同一記憶體空間,如果props是陣列或物件,在子元件內部直接改變它會影響父元件的狀態。

②子元件與父元件通訊

我們知道,父元件是使用 props 傳遞資料給子元件,但如果子元件要把資料傳遞回去,應該怎樣做?那就是自定義事件!
父元件可以直接在子元件使用的地方使用v-on繫結事件

父元件繫結事件和傳遞資料:
<parent> 
    <child @upup="change" :msg="msg"></child> //監聽子元件觸發的upup事件,然後呼叫change方法 
</parent>

export default {
    data() {
        return {
            msg: '123'
        }
    },
    methods: { 
        change(msg) { 
            this.msg = msg; // 接收子元件傳遞過來的引數,並更新msg,從而子元件也相應的更新msg
        } 
    }
}

子元件接收資料和觸發事件:
<template> 
    <div @click="up">{{msg}}</div>
</template> 

export default {
    props: {
        msg: {
            type: String,
            default: ''
        }
    },
    methods: { 
        up() { 
            this.$emit('upup','updateMsg'); //主動觸發upup方法,'updateMsg'為向父元件傳遞的資料 
        } 
    }
}

③ 父元件如何觸發子元件的事件

<parent @click="doSomeThing">
    <child ref="childComp"></child>
</parent>

export default {
    methods: {
        doSomeThing() {
            this.$refs.childComp.yesSir('123')
        }
    }
}

<template></template>

export default{
    methods: {
        yesSir(a) {
            console.log(a) // 123
        }
    }
}

2、非父子元件通訊

在簡單的場景下,vue建議我們使用一個空的 Vue 例項作為中央事件匯流排:

新建一個bus.js用於儲存我們空的事件中轉站:

import Vue from 'vue'

export var bus = new Vue()

元件a通過$on繫結事件:

<template>
</template>
import { bus } from 'bus.js'
export default {
    created() {
        bus.$on('change', () => { //接收事件
            this.msg = 'hehe';
        });
    }
}

元件b通過$emit繫結事件:

<div @click="eve"></div>

import { bus } from 'bus.js'
export default {
    methods: {
        eve() {
            bus.$emit('change','hehe'); //觸發事件
        }
    }
}