vue組件間通信方式

  1. props$emit 父組件向子組件傳遞數據是經過prop傳遞的,子組件傳遞數據給父組件是經過$emit觸發事件來作到的
  2. .syncv-model的使用(父子組件數據同步)
  3. $parent,$children 多層級傳遞數據,智能組件封裝
  4. $attrs(屬性的集合)和$listeners(方法的集合)。Vue 2.4 開始提供了$attrs$listeners來解決A->B->C問題,組件間向下傳遞,能夠不用 props註冊。v-bind屬性傳遞,v-on方法傳遞
  5. 父組件中經過provider來提供變量,而後在子組件中經過inject來注入變量。
  6. $refs 獲取實例
  7. envetBus 平級組件數據傳遞 這種狀況下可使用中央事件總線的方式

props傳遞數據

父組件vue

<template>
    <div>
        父組件:{{money}}
        <son1 :money='money' @addMoney = 'addMoney'></son1>
    </div>
</template>
<script>
import son1 from './son1'
export default {
    components:{
        son1
    },
    data(){
        return {
            money:100
        }
    },
    methods:{
        addMoney(val){
            this.money = val
        }
    }
}
</script>
複製代碼

子組件 son1.vuevue-router

<template>
    <div>
        兒子1得到{{money}}
        <button @click="raiseMoney">多給點嘛</button>
    </div>
</template>
<script>
export default {
    props:{
        money:{
            type:Number,
            default:1
        }  
    },
    methods:{
        raiseMoney(){
            this.$emit('addMoney',200)
        }
    }
}
</script>
複製代碼

.sync 和 v-model的使用(父子組件數據同步)

.syncbash

  • 需求須要對一個 prop 進行「雙向綁定」。不幸的是,真正的雙向綁定會帶來維護上的問題,由於子組件能夠修改父組件,且在父組件和子組件都沒有明顯的改動來源。
  • update:myPropName 的模式觸發事件取而代之
  • 父組件 <son1 :money.sync='money'></son1>
    子組件 this.$emit('update:money',200)
    是對下面代碼的簡寫(語法糖)
    父組件 <son1 :money="money" @update:money="(val)=>this.money=val"></son1>
    子組件this.$emit('update:money',200)

v-modelapp

  • <son1 :value="money" @input="(val)=>this.money=val></son1>
  • 也能夠寫成<son1 v-model="money"></son1>
  • v-model這種方法,子組件只能接收value,具備侷限性,而.sync則能夠隨意起名字

多層級傳遞數據 $parent $children

  • 孫子組件直接更改父組件<button @click="$parent.$emit('addMoney',400)">更改父組件</button>
    像這樣若是有多級孫子組件,就會一直$parent下去,這樣會很麻煩,不如直接封裝一個$dispatch
    $dispatch只會通知本身對父親, 而eventBus是全局通知,通知全部的父親或者兒子
  • 在main.vue裏封裝dispatch

向上通知dom

Vue.prototype.$dispatch = function (eventName,value){
    let parent = this.$parent;
    while(parent){
        parent.$emit(eventName,value);
        parent = parent.$parent
    }
}

使用時只須要 this.$dispatch('addMoney',400)
//666 親測無誤
複製代碼

向下傳遞ide

  • 在main.js裏封裝$broadcast
Vue.prototype.$broadcast = function (eventName,value){
    //獲取當前組件下的因此孩子
    const broadcast = (children) => {
        children.forEach(child => {
            child.$emit(eventName,value);
            if(child.$children){
                broadcast(child.$children)
            }
        })
    }
    broadcast(this.$children)
}

使用時只須要 在父級 this.$broadcast('say',1111) 只要子組件中有綁say的都給我說1111

在son1.vue中        
    <Grandson :money = money @say='say1'></Grandson>

    methods:{
        say1(val){
            console.log("我很帥"+val)
        }
    }
<!--親測控制檯打印 我很帥1111-->
複製代碼

$attrs屬性的集合

  • $attrs表明上級傳過來的全部屬性,當父組件給子組件須要穿過來不少值時,用props一個一個接收豈不是很累,使用$attrs就能夠一次性把父級傳過來當全部值接收到,完美~
  • 直接用$attrs接收完數據,打開控制檯,你會發現以下狀況,屬性所有掛載在了dom上,咱們並不想這樣
    解決:在使用$attrs的子組件上,添加inheritAttrs:false,代碼以下
<!--父組件-->
<son2 name="奔跑" address="北京"></son2>

<!--子組件-->
template>
    <div>
        <!-- $attrs表明上級傳過來的全部屬性 -->
        兒子2: {{$attrs}}
    </div>
</template>
<script>
export default {
    inheritAttrs:false
}
</script>
<!--頁面顯示:兒子2: { "name": "奔跑", "address": "北京" }-->
複製代碼
  • 如何子組件把獲取到的數據再一次性傳給孫子組件,只須要這麼作:
    <grandson2 v-bind="$attrs"></grandson2>
    孫子組件接收時一樣使用$attrs便可得到全部的數據

$listeners方法的集合

  • 父級在子組件綁定的方法,在子組件裏均可以用$listeners來調用這些方法
  • 若是子組件不使用這些方法,孫子組件使用,則可使用v-on="$listeners"來傳遞給孫子組件這些方法,孫子組件使用時,一樣使用$listeners
<!--父組件-->
<son2 name="奔跑" address="北京" @look="console.log('look')"></son2>

<!--子組件-->
<grandson2 v-bind="$attrs" v-on="$listeners"></grandson2>

<!--孫子組件-->
<template>
    <div>
        孫子2:{{$attrs}}
        <button @click="$listeners.look()">看</button>
    </div>
</template>

<!--在孫子組件上點擊按鈕'看',則會在控制檯打印'look'-->
複製代碼

provide提供變量,inject註冊變量

  • 問題:導航欄的地址發生改變可是頁面卻不刷新 (用vue-router路由到當前頁面,頁面是不進行刷新的),例以下面的搜索功能

解決:

  • 一、this.$router.go(0);
  • 二、location.reload();
    上面兩種方法會出現閃屏的問題,用戶體驗很差
    如何產品贊成,我更喜歡window.open一下
  • 三、終極解決,哈哈哈
    在App.vue,聲明reload方法,控制router-view的顯示或隱藏,從而控制頁面的再次加載。(provide /inject )

      【祖先組件(provide )向其全部子孫後代(inject )注入一個依賴】ui

  • app.vue中
    1.data中聲明變量 2.綁定v-if 3.方法裏寫邏輯 4.向後代注入依賴

在須要的頁面 調用方法
inject接受app傳遞的方法

$refs獲取實例

  • ref被用來給元素或者子組件註冊引用信息。引用信息將會註冊在父組件的$refs對象上。
    若是在普通的Dom元素上使用,引用指向的就是DOM元素;
    若是用在子組件上,引用就指向組件實例,父級就可以使用子組件上的方法,經過$refs
  • $refs相對document.getElementById的方法,會減小獲取dom節點的消耗。
  • $refs只在組件渲染完成後才填充,而且它是非響應式當。它僅僅是一個直接操做子組件的應急方案---應當避免在模版或者計算屬性中使用$refs
<!--父級-->
<son2 name="奔跑" address="北京" ref="son2"></son2>

    mounted(){
        this.$refs.son2.sleep()
    },
    
<!--son2子組件-->
    methods:{
        sleep(){
            console.log('我想睡覺')
        }
    }
複製代碼

跨組件通訊 eventBus

  • eventBus定義到了全局上,經過$on(eventName,function)註冊事件,經過$emit(eventName,參數)獲取使用事件
<!--在mian.js上註冊bus-->
Vue.prototype.$bus = new Vue();

<!--在恰當的頁面 註冊事件-->
    this.$bus.$on('有人找我了',function(val){
        console.log('呵呵'+val)
    })
<!--在恰當的頁面 使用事件-->
    this.$nextTick(()=>{
        this.$bus.$emit('有人找我了','xxx')
    })
<!--控制檯打印-->
    呵呵xxx
複製代碼
  • this.$nextTick的用途 new Premise().then(()=>{ //等待全部代碼都同步完之後再執行 })
相關文章
相關標籤/搜索