Vue组件之间数据通信12种方式
目錄
1、父組件向子組件傳遞數據 props
2.子組件向父組件傳遞數據($emit的用法)
3.兄弟組件通信
4、ref / $refs
5、eventBus事件總線($emit / $on)
6、依賴注入(provide / inject)
7.$parent / $children
8. $children
9. $root
10.vuex
11. $attrs / $listeners
1、父組件向子組件傳遞數據 props
父組件通過?props?向子組件傳遞數據,子組件通過?$emit?和父組件通信
props的特點:
- props只能是父組件向子組件進行傳值,props使得父子組件之間形成一個單向的下行綁定。子組件的數據會隨著父組件的更新而響應式更新。
代碼演示
父組件:
// 父組件 <template><div id="father"><son :msg="msgData" :fn="myFunction"></son></div> </template><script> import son from "./son.vue"; export default {name: father,data() {msgData: "父組件數據";},methods: {myFunction() {console.log("vue");}},components: {son} }; </script>子組件:
// 子組件 <template><div id="son"><p>{{msg}}</p><button @click="fn">按鈕</button></div> </template> <script> export default {name: "son",props: ["msg", "fn"] }; </script>2.子組件向父組件傳遞數據($emit的用法)
$emit的特點:
- $emit 綁定一個自定義事件,當這個事件被執行的時候就會將參數傳遞給父組件,而父組件通過v-on監聽并接收參數
用法:
父組件:
// 父組件 <template><div class="section"><com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article><p>{{currentIndex}}</p></div> </template><script> import comArticle from './test/article.vue' export default {name: 'comArticle',components: { comArticle },data() {return {currentIndex: -1,articleList: ['紅樓夢', '西游記', '三國演義']}},methods: {onEmitIndex(idx) {this.currentIndex = idx}} } </script>子組件:
//子組件 <template><div><div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{item}}</div></div> </template><script> export default {props: ['articles'],methods: {emitIndex(index) {this.$emit('onEmitIndex', index) // 觸發父組件的方法,并傳遞參數index}} } </script>3.兄弟組件通信
兄弟組件通信可以借助父組件交互
A組件 B組件
1. A組件數據傳遞給共同的父組件 再有父組件接受后傳遞給B組件?
2.?通過 $parent + $refs 以父組件為中間人來獲取到兄弟組件,也可以進行通信。
4、ref / $refs
這種方式也是實現父子組件之間的通信
ref:這個屬性用在子組件上,它的用用就指向了子組件的實例,可以通過實例來訪問組件的數據和方法
用法:
在子組件中:
export default {data () {return {name: 'JavaScript'}},methods: {sayHello () {console.log('hello')}} }在父組件中:
<template> 調用子組件使用ref 獲取子組件實例<child ref="child"></component-a> </template> <script>import child from './child.vue'export default {components: { child },mounted () {console.log(this.$refs.child.name); // JavaScript 獲取子組件數據this.$refs.child.sayHello(); // hello 調用子組件的方法}} </script>5、eventBus事件總線($emit / $on)
eventBus事件總線適用于父子組件、非父子組件等之間的通信,使用步驟如下:
vue事件總線(eventBus),通過創建一個空的vue實例作為全局事件總線,用它來觸發事件和監聽事件,從而實現任何組件間的通信,包括父子、隔代、兄弟組件
(1)創建事件中心管理組件之間的通信
(2)發送事件 假設有兩個組件home About
?
(3)接收事件
在上述代碼中,這就相當于將count值存貯在了事件總線中,在其他組件中可以直接訪問。事件總線就相當于一個橋梁,不用組件通過它來通信。雖然看起來比較簡單,但是這種方法也有不變之處,如果項目過大,使用這種方式進行通信,后期維護起來會很困難。
vue3不再使用 廢除了
6、依賴注入(provide / inject)
這種方式就是vue中依賴注入,該方法用于 父子組件之間 的通信。當然這里所說的父子不一定是真正的父子,也可以是祖孫組件,在層數很深的情況下,可以使用這種方式來進行傳值。就不用一層一層的傳遞數據了。
provide和inject是vue提供的兩個鉤子,和data、methods是同級的。并且provide的書寫形式和data一樣。
provide 鉤子用來發送數據或方法。
inject鉤子用來接收數據或方法
用法:
父組件中:
?
子組件中:
inject: ['num']還有另一種寫法,這種寫法可以訪問父組件中的所有屬性:
provide() {return {app: this}; } data() {return {num: 1}; }inject: ['app'] console.log(this.app.num)7.$parent / $children
- 使用$parent可以讓組件訪問父組件的實例(訪問的是上一級父組件的屬性和方法)。
- 使用 $children 可以讓組件訪問子組件的實例,但是, $children 并不能保證順序,并且訪問的數據也不是響應式的。
用法:
子組件中:
<template><div><span>{{message}}</span><p>獲取父組件的值為: {{parentVal}}</p></div> </template><script> export default {data() {return {message: 'Vue'}},computed:{parentVal(){return this.$parent.msg;}} } </script>8. $children
父組件中:
<template><div class="hello_world"><div>{{msg}}</div><child></child><button @click="change">點擊改變子組件值</button></div> </template><script> import child from './child.vue' export default {components: { child },data() {return {msg: 'Welcome'}},methods: {change() {// 獲取到子組件this.$children[0].message = 'JavaScript'}} } </script>在上面的代碼中,子組件獲取到了父組件的parentVal值,父組件改變了子組件中message的值。
注意:
通過 $parent 訪問到的是上一級父組件的實例,可以使用 $root 來訪問根組件的實例
在組件中使用$children拿到的是所有的子組件的實例,它是一個數組,并且是無序的
在根組件 #app 上拿 $parent 得到的是 new Vue()的實例,在這實例上再拿 $parent 得到的是undefined,而在最底層的子組件拿 $children 是個空數組
$children 的值是數組,而 $parent是個對象
?
9. $root
掛在2在根組件實例上的data數據 ---不推薦
子組件通過this.$root.xxx 可以訪問
任意子組件訪問
?
10.vuex
11. $attrs
12.?$listeners
$attrs
用于父組件給孫組件傳遞數據
$listeners
用于孫組件給父組件傳遞數據
考慮一種場景,如果A是B組件的父組件,B是C組件的父組件。如果想要組件A給C組件傳遞數據,這種隔代傳數據的情況該使用哪種方式呢?
如果是用props/ $emit 來一級一級的傳遞,確實可以完成,但是比較復雜;如果使用事件總線,在多人開發或者項目較大的時候,維護起來很麻煩;如果使用vuex,如果僅僅是傳遞數據,那可能有點浪費了。
針對上述情況,vue引入了 $attrs / $listeners,實組件之間的跨代通信。
$attrs:繼承所有的父組件屬性(除了props傳遞的屬性、class 和 style),一般用在子組件的子元素上
$listeners:該屬性是一個對象,里面包含了作用在這個組件上的所有監聽器,可以配合 v-on=" $listeners " 將所有的事件監聽器指向這個組件的某個特定的子元素。(相當于子組件繼承父組件的事件)
?
$attrs / $listeners的用法:
parent組件
son1組件
Son2組件
在上述代碼中:
- C組件中能直接觸發test的原因在于 B組件調用C組件時 使用 v-on 綁定了$listeners 屬性
- 在B組件中通過v-bind 綁定$attrs屬性,C組件可以直接獲取到A組件中傳遞下來的props(除了B組件中props聲明的)
?
總結
以上是生活随笔為你收集整理的Vue组件之间数据通信12种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《17天搞定GRE单词》
- 下一篇: vue-cli项目引入highchart