vue高級進(jìn)階( 二 ) 8種組件通信詳解

猛獸總是獨(dú)行,牛羊才成群結(jié)隊(duì)芯勘。 -------魯迅

vue組件通信的重要性無需多言右冻。装蓬。。但是你肯定沒有全部掌握纱扭,所以這第二篇文章應(yīng)運(yùn)而生

props和$emit

props父傳子牍帚,$emit子傳父,看下邊代碼乳蛾,清澈的像少女的眼眸履羞。。屡久。emmm

    Vue.component('child',{
        data(){
            return {
                mymessage:this.message
            }
        },
        template:`
            <div>
                <input type="text" v-model="mymessage" 
                @input="passData(mymessage)"> </div>
        `,
        props:['message'],//得到父組件傳遞過來的數(shù)據(jù)
        methods:{
            passData(val){
                //觸發(fā)父組件中的事件
                this.$emit('getChildData',val)
            }
        }
    })
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
    Vue.component('parent',{
        template:`
            <div>
                <p>this is parent compoent!</p>
                <child :message="message"
                v-on:getChildData="getChildData"></child>
            </div>
        `,
        data(){
            return {
                message:'張不慫'
            }
        },
        methods:{
            //執(zhí)行子組件觸發(fā)的事件
            getChildData(val){
                console.log(val)
            }
        }
    })
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*

     // 掛載
    var app=new Vue({
        el:'#app',
        template:`
            <div>
                <parent></parent>
            </div>
        `
    })
復(fù)制代碼

中央事件總線new Bus

新建一個(gè)Vue事件bus對象忆首,然后通過bus.$emit觸發(fā)事件,bus.$on監(jiān)聽觸發(fā)的事件被环。

Vue.component('brother1',{
        data(){
            return {
                mymessage:'hello brother1'
            }
        },
        template:`
            <div>
                <p>this is brother1 compoent!</p>
                <input type="text" v-model="mymessage"
                @input="passData(mymessage)"> 

            </div>
        `,
        methods:{
            passData(val){
                //觸發(fā)全局事件globalEvent
                bus.$emit('globalEvent',val)

            }
        }
    })
 ┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*

    Vue.component('brother2',{
        template:`
            <div>
                <p>this is brother2 compoent!</p>
                <p>brother1傳遞過來的數(shù)據(jù):{{brothermessage}}</p>
            </div>
        `,
        data(){
            return {
                mymessage:'hello brother2',

                brothermessage:''
            }
        },
        mounted(){
            //綁定全局事件globalEvent
            bus.$on('globalEvent',(val)=>{
                this.brothermessage=val;
            })
        }
    })
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*

    //中央事件總線
    var bus=new Vue();

    var app=new Vue({
        el:'#app',
        template:`
            <div>
                <brother1></brother1>
                <brother2></brother2>
            </div>
        `
    })
復(fù)制代碼

provide和inject

父組件中通過provider來提供變量糙及,然后在子組件中通過inject來注入變量。不論子組件有多深筛欢,只要調(diào)用了inject那么就可以注入provider中的數(shù)據(jù)浸锨。而不是局限于只能從當(dāng)前父組件的prop屬性來獲取數(shù)據(jù),只要在父組件的生命周期內(nèi)版姑,子組件都可以調(diào)用柱搜。

Vue.component('child',{
        inject:['parent_var'],//得到父組件傳遞過來的數(shù)據(jù)
        data(){
            return {
                mymessage:this.parent_var
            }
        },
        template:`
            <div>
               {{ message }}
            </div>
    })
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
    Vue.component('parent',{
        template:`
            <div>
                <child></child>
            </div>
        `,
        provide:{
            // 看你想傳遞啥了,這里不寫固定的原因是為了防止限制大家的思維
            /*
            比如你可以把用戶登錄信息存儲在App.vue中剥险,可以把
            provide:{app:this}注入聪蘸,后續(xù)所有組件通過inject:['app'],
            就可以直接通過app.userInfo拿到用戶信息
            */
            parent_var:'隨便什么都可以(可以是this,可以是data中的數(shù)據(jù))'
        },
        data(){
            return {
                message:'hello'
            }
        }
    })
┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┄┅┄┅┄┅┄┅┄*
    var app=new Vue({
        el:'#app',
        template:`
            <div>
                <parent></parent>
            </div>
        `
    })
復(fù)制代碼

$attrs和$listeners

還是多層的場景,App.vue-->A—>B,如果App直接想給B傳遞數(shù)據(jù)該怎么辦表制?Vue 2.4開始提供了[圖片上傳失敗...(image-17bd97-1613815451793)]

listeners來解決這個(gè)問題健爬,能夠讓組件App直接傳遞數(shù)據(jù)給組件B。我將代碼中關(guān)鍵點(diǎn)已經(jīng)標(biāo)注出么介, // ******關(guān)鍵點(diǎn)*****

app.vue引入A組件

<template>
  <div id="app">
    {{app}}
    // ******關(guān)鍵點(diǎn)*****
    <A :app="app" @test="doTest"/>
  </div>
</template>

<script>
import A from "./components/A";

export default {
  name: "App",
  data() {
    return {
      app: "我是App的數(shù)據(jù)"
    };
  },
  components: {
    A
  },
  methods: {
    doTest() {
      console.log(this.app)
    }
  }
};
復(fù)制代碼

A.vue引入B組件

<template>
  <div class="hello">
    <h6>這里是A組件</h6>
    <p>$attrs: {{$attrs}}</p>
    <p>$listeners: {{$listeners}}</p>
     // ******關(guān)鍵點(diǎn)***** v-bind傳遞的都是$attrs,v-on傳遞的都是$listeners
    <B v-bind="$attrs" v-on="$listeners"/>
  </div>
</template>

<script>
import B from "./B";

export default {
  name: "A",
  props: {
    msg: String
  },
  components: { B },
  mounted() {
    console.log(this.$listeners);
  }
};
</script>
復(fù)制代碼

B組件

<template>
  <div class="hello">
    <h6>這里是B組件</h6>
     // ******關(guān)鍵點(diǎn)*****
    <p>$attrs: {{$attrs}}</p>
  </div>
</template>

<script>

export default {
  name: "B",
  props: {
    msg: String
  },
  mounted() {
   // ******關(guān)鍵點(diǎn)*****
   // 為啥這里直接能emitApp組件傳遞的test呢娜遵?
   // 因?yàn)樵贏組件中有一個(gè)關(guān)鍵操作是  <B v-bind="$attrs" v-on="$listeners"/>
    this.$emit("test");
  }
};
</script>
復(fù)制代碼

$parent和$children

分別是獲得父組件和子組件的實(shí)例

Vue.component('child',{
        props:{
            value:String, //v-model會自動(dòng)傳遞一個(gè)字段為value的prop屬性
        },
        data(){
            return {
                mymessage:this.value
            }
        },
        methods:{
            changeValue(){
                this.$parent.message = this.mymessage;//通過如此調(diào)用可以改變父組件的值
            }
        },
        template:`
            <div>
                <input type="text" v-model="mymessage" @change="changeValue"> 
            </div>
    })
    Vue.component('parent',{
        template:`
            <div>
                <p>this is parent compoent!</p>
                <button @click="changeChildValue">test</button >
                <child></child>
            </div>
        `,
        methods:{
            changeChildValue(){
                this.$children[0].mymessage = 'hello';
            }
        },
        data(){
            return {
                message:'hello'
            }
        }
    })
    var app=new Vue({
        el:'#app',
        template:`
            <div>
                <parent></parent>
            </div>
        `
    })
復(fù)制代碼

v-model

父組件通過v-model傳遞值給子組件時(shí),會自動(dòng)傳遞一個(gè)value的prop屬性壤短,在子組件中通過this.$emit(‘input’,val)自動(dòng)修改v-model綁定的值

Vue.component('child',{
        props:{
            value:String, //v-model會自動(dòng)傳遞一個(gè)字段為value的prop屬性
        },
        data(){
            return {
                mymessage:this.value
            }
        },
        methods:{
            changeValue(){
                this.$emit('input',this.mymessage); //通過如此調(diào)用可以改變父組件上v-model綁定的值
            }
        },
        template:`
            <div>
                <input type="text" v-model="mymessage" @change="changeValue"> 
            </div>
    })
    Vue.component('parent',{
        template:`
            <div>
                <p>this is parent compoent!</p>
                <p>{{message}}</p>
                <child v-model="message"></child>
            </div>
        `,
        data(){
            return {
                message:'hello'
            }
        }
    })
    var app=new Vue({
        el:'#app',
        template:`
            <div>
                <parent></parent>
            </div>
        `
    })
復(fù)制代碼

boradcast和dispatch

vue1.0中提供了這種方式设拟,但vue2.0中沒有慨仿,但很多開源軟件都自己封裝了這種方式,比如min ui纳胧、element ui, broadcast是向特定的父組件镰吆,觸發(fā)事件,dispatch是向特定的子組件觸發(fā)事件躲雅,本質(zhì)上這種方式還是使用遞歸對on和emit的封裝,但在一些基礎(chǔ)組件中卻很實(shí)用骡和。注意:所有組件的名稱不能重復(fù)O嗔蕖!慰于!

function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    var name = child.$options.componentName;

    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat(params));
    }
  });
}

function dispatch(componentName, eventName, params) {
        var parent = this.$parent;
      var name = parent.$options.componentName;
      while (parent && (!name && name !== componentName)) {
        parent = parent.$parent;
        if (parent) {
          name = parent.$options.componentName;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
}
export default {
  methods: {
    dispatch(componentName, eventName, params) {
      dispatch.call(this, componentName, eventName, params);
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};
復(fù)制代碼

vuex

對于vuex不再做過多的贅述钮科。。婆赠。

第二章非常全面的講解了vue炒雞重要的一個(gè)技能绵脯,組件通信,我說這一篇全面大家應(yīng)該沒意見吧休里?好了就這樣...

覺得對你有幫助蛆挫,不妨點(diǎn)個(gè)

,后續(xù)持續(xù)輸出這種簡短有效的文章妙黍,幫助你用最短的時(shí)間內(nèi)掌握最多的內(nèi)容悴侵,畢竟誰不喜歡一勞永逸不是? ?(^_-) thank you ~

后續(xù)目錄

vue高級進(jìn)階( 一 ) 組件精髓概述

vue高級進(jìn)階( 二 ) 8種組件通信詳解

vue高級進(jìn)階( 三 ) 組件高級用法及最佳實(shí)踐

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拭嫁,一起剝皮案震驚了整個(gè)濱河市可免,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌做粤,老刑警劉巖浇借,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怕品,居然都是意外死亡妇垢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門肉康,熙熙樓的掌柜王于貴愁眉苦臉地迎上來修己,“玉大人,你說我怎么就攤上這事迎罗〔欠撸” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵纹安,是天一觀的道長尤辱。 經(jīng)常有香客問我砂豌,道長,這世上最難降的妖魔是什么光督? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任阳距,我火速辦了婚禮,結(jié)果婚禮上结借,老公的妹妹穿的比我還像新娘筐摘。我一直安慰自己,他們只是感情好船老,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布咖熟。 她就那樣靜靜地躺著,像睡著了一般柳畔。 火紅的嫁衣襯著肌膚如雪馍管。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天薪韩,我揣著相機(jī)與錄音确沸,去河邊找鬼。 笑死俘陷,一個(gè)胖子當(dāng)著我的面吹牛罗捎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拉盾,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼宛逗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盾剩?” 一聲冷哼從身側(cè)響起雷激,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎告私,沒想到半個(gè)月后屎暇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡驻粟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年根悼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜀撑。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挤巡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酷麦,到底是詐尸還是另有隱情矿卑,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布沃饶,位于F島的核電站母廷,受9級特大地震影響轻黑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜琴昆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一氓鄙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧业舍,春花似錦抖拦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至脚牍,卻和暖如春向臀,著一層夾襖步出監(jiān)牢的瞬間巢墅,已是汗流浹背诸狭。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留君纫,地道東北人驯遇。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像蓄髓,于是被迫代替她去往敵國和親叉庐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容