自己的理解:元件化通訊,無非就是資料你傳我,我傳你,兩個元件的相互交流,方法很多,下方有圖示(此篇建議小白閱讀,大神的話也不會看,哈哈哈哈!僅供參考,有不同的意見可以一起交流!)
我的理解是:如果建議使用props
的方式,那我們就來了解一下props
props傳資料:
解釋:一個元件需要顯式宣告它所接受的 props,這樣 Vue 才能知道外部傳入的哪些是 props
(你要是想用父元件的傳下來的資料,你肯定得先傳呀,父元件傳完之後,就是子元件接收了,這之後就要用到props來接收了,接收的型別很多,字串呀,物件呀,陣列呀,布林值呀,其中props中的屬性,最終都會出現在VueComponent的範例物件上,也就是說,會暴露在當前this上)
1.props宣告:
1.1 為什麼要宣告?你不宣告怎麼知道外部傳來的是哪個props
1.2 宣告定義的型別有很多
1.2.1 最簡單的字串陣列的宣告方式(只接收): props:['foo']
1.2.2 稍微微微的有點小變化(限制型別):props:{name:'String'}
1.2.3 稍微有點多的物件方式來宣告(可以指定傳遞的型別進行校驗,限制必要性):
props:{
name:{
type:String, //型別
required:true, //必要性
default:'xxx' //預設值
}
備註:props是唯讀的,Vue底層會監測你對props的修改,如果進行了修改,就會發出警告,若業務需求確實需要修改,那麼請複製props的內容到data中一份,然後去修改data中的資料。
2. 細節
2.1很多小夥伴困擾,該怎麼起名字,要有什麼規範嗎?
我平常起名字的話也是有點小隨意,但是正在改進,主要還是英語限制了,跑題了!!!
如果一個 prop 的名字很長,強烈建議使用 camelCase 形式或者 kebab-case ,建議Vue官方的推薦,這種方式不管從美觀度還是可讀性都是極好的,也是JavaScript合法的識別符號,不比我們自己起的好?如果英語基礎不是很好,可以去有道之類的一些查詞軟體上查,不斷提升自己的命名能力!
那我們在多說一點吧,可以大說是小夥伴都知道,對於元件名我們推薦使用 PascalCase 寫法,使用元件單閉合的形式,這樣能更好的區分原生的標籤
2.2 props 動態和靜態的理解
分為動態和靜態,但是在我們實際開發中,用的動態還是比較多的,很少傳靜態,
動態: 我們可以通過 v-bind 來動態繫結 props
<!-- 根據一個變數的值動態傳入 -->
<BlogPost :title="post.title" />
<!-- 根據一個更復雜表示式的值動態傳入 -->
<BlogPost :title="可以傳遞一個方法,表示式等" />
2.3 實際上任何型別的值都可以作為 props 的值被傳遞。String,Number,Boolean,Array,Object
2.4 有時候我們傳遞的不只是一個屬性,把物件傳遞過去,使用一個物件傳遞多個props,
如果你想要將一個物件的所有屬性都當作 props 傳入,你可以使用沒有引數的 v-bind,即只使用 v-bind 而非 :prop-name
<BlogPost v-bind="post" />
等價於:<BlogPost :id="post.id" :title="post.title" />
嵌入程式碼更易於理解
1.最笨重的方法,但是有效
就是利用props傳遞,有人會說,props不是父給子傳嗎?其實有一種方法是可以實現子給父傳遞資料的
我們需要利用props給子元件傳遞有參方法,子元件接收並呼叫傳遞引數,資料以引數的形式傳遞給父元件,此時父元件拿到的引數就是子元件中的資料來實現,以此子傳父.
嵌入程式碼
2.相對於方法1稍微好點
2.1 一種元件間通訊的方式,適用於:子元件 ===> 父元件
2.2 使用場景:A是父元件,B是子元件,B想給A傳資料,那麼就要在A中給B繫結自定義事件(事件的回撥在A中)。
2.3 繫結自定義事件:第一種方式,在父元件中:<Demo @taoTao="test"/>
或 <Demo v-on:taoTao="test"/>
第二種方式,在父元件中:
<Demo ref="demo"/>
......
mounted(){
this.$refs.xxx.$on('taoTao',this.test)
}
若想讓自定義事件只能觸發一次,可以使用once
修飾符,或$once
方法。
觸發自定義事件:this.$emit('taoTao',資料)
解綁自定義事件this.$off('taoTao')
元件上也可以繫結原生DOM事件,需要使用native
修飾符。
注意:通過this.$refs.xxx.$on('taoTao',回撥)
繫結自定義事件時,回撥要麼設定在methods中,要麼用箭頭函數,否則this指向會出問題!
任意元件間通訊的方法:全域性事件匯流排
前面兩種父傳子,子傳父,也只能解決比較簡單的問題,如果跨級傳遞,或者是兄弟之間傳遞,操作起來就很繁瑣,所以我們就定義出來了一種 全域性事件匯流排的方法來解決任意元件間通訊,說白了就是:
1.全域性事件匯流排的介紹:A元件和B元件是兄弟元件,現在我想把A元件的資料傳遞給B元件進行使用,我們就需要把一個東西作為傀儡(中間人),然後A元件把資料傳給傀儡,B元件從傀儡中獲得A元件傳遞的值,這樣就可以實現任意元件間的通訊,你可能會有疑問,那麼多元件都給傀儡的話,如何區分是哪個元件傳遞的,這是就需要傳遞過來的資料攜帶一個標識,方便使用,使用完要銷燬,不然壓力會很大,這就是全域性事件匯流排的工作流程。那我們應該如何書寫呢?
2.安裝全域性事件匯流排
那我就要給你們細講了:全域性事件匯流排有兩個特點:首先我們得叫所有的元件都能存取到這個事件,其次是能有$emit,$on,$off等這些屬性,我們就會想到Vue或者是VueComponent,其中我們會用
一個重要的內建關係:VueComponent.prototype.__proto__ === Vue.prototype
我們可以這樣定義全域性事件匯流排:
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安裝全域性事件匯流排,$bus就是當前應用的vm
},
......
})
3.使用全域性事件匯流排
3.1 接收資料:A元件想接收資料,則在A元件中給$bus繫結自定義事件,事件的回撥留在A元件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.$bus.$on('xxxx',this.demo)
}
3.2 提供資料:this.$bus.$emit('xxxx',資料)
beforeDestroy
勾點中,用$off去解綁當前元件所用到的事件。一種元件間通訊的方式,適用於任意元件間通訊。
使用步驟:
安裝pubsub:npm i pubsub-js
引入: import pubsub from 'pubsub-js'
接收資料:A元件想接收資料,則在A元件中訂閱訊息,訂閱的回撥留在A元件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.pid = pubsub.subscribe('xxx',this.demo) //訂閱訊息
}
提供資料:pubsub.publish('xxx',資料)
最好在beforeDestroy
勾點中,用PubSub.unsubscribe(pid)
去取消訂閱。
作用:讓父元件可以向子元件指定位置插入html結構,也是一種元件間通訊的方式,適用於 父元件 ===> 子元件 。
分類:預設插槽、具名插槽、作用域插槽
使用方式:
預設插槽:
父元件中:
<Category>
<div>html結構1</div>
</Category>
子元件中:
<template>
<div>
<!-- 定義插槽 -->
<slot>插槽預設內容...</slot>
</div>
</template>
具名插槽:
父元件中:
<Category>
<template slot="center">
<div>html結構1</div>
</template>
<template v-slot:footer>
<div>html結構2</div>
</template>
</Category>
子元件中:
<template>
<div>
<!-- 定義插槽 -->
<slot name="center">插槽預設內容...</slot>
<slot name="footer">插槽預設內容...</slot>
</div>
</template>
作用域插槽:
理解:資料在元件的自身,但根據資料生成的結構需要元件的使用者來決定。(games資料在Category元件中,但使用資料所遍歷出來的結構由App元件決定)
具體編碼:
父元件中:
<Category>
<template scope="scopeData">
<!-- 生成的是ul列表 - ->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!-- 生成的是h4標題 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
子元件中:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//資料在子元件自身
data() {
return {
games:['紅色警戒','穿越火線','勁舞團','超級瑪麗']
}
},
}
</script>
之後再更新..........