一起來學習Vue的組件間通信方式
props
父組件可以通過props向下傳遞數(shù)據(jù)給子組件
靜態(tài)的Props
通過為子組件在父組件中的占位符添加特性的方式來達到傳值的目的
動態(tài)Props
在模版中要動態(tài)的綁定父組件的數(shù)據(jù)到子模版的props,與綁定任何普通的HTML特性相類似,用v-bind,每當父組件的數(shù)據(jù)發(fā)生變化的時候,該變化會傳導給子組件
props驗證
可以為組件的props指定驗證規(guī)則,如果傳入的數(shù)據(jù)不符合規(guī)則,Vue會發(fā)出警告
props: { // 基礎類型檢測 (`null` 意思是任何類型都可以) propA: Number, // 多種類型 propB: [String, Number], // 必傳且是字符串 propC: { type: String, required: true }, // 數(shù)字,有默認值 propD: { type: Number, default: 100 }, // 數(shù)組/對象的默認值應當由一個工廠函數(shù)返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定義驗證函數(shù) propF: { validator: function (value) { return value > 10 } } }
type 可以是(String
,Number
,Boolean
,Function
,Object
,Array
,Symbol
)原生構造器
type也可以是自定義構造函數(shù),使用instenceof檢測
prop是當先綁定的,當父組件的屬性變化是,將傳導給子組件,但是不會反過來,這是為了防止子組件無意修改了父組件的狀態(tài)。
修改prop數(shù)據(jù)
- prop 作為初始值傳入后,子組件想把他當作局部數(shù)據(jù)來用
- prop 作為初始值傳入,有子組件處理成其他數(shù)據(jù)輸出
- 注意:js中對象和數(shù)組是引用類型,指向同一個內存空間,如果prop是一個對象或數(shù)組,在子組件內部改變它會影響父組件的狀態(tài)
- 處理方法1:這個時候需要定義一個局部變量,并用prop初始化它,但是局部變量只能接受prop初始值,當父組件的值發(fā)生變化的時候,無法接收到最新值
- 處理方法2:定義一個計算屬性,處理prop值并返回
- 初始方法3:使用變量存儲prop的初始值,并使用watch來觀察prop的值的變化,當發(fā)生變化的時候更新變量的值
$emit
$emit(‘自定義時間名’,要傳送的數(shù)據(jù))觸發(fā)當前實例上的事件
父組件
<template> <children @addCount="addCount" :count="count"/> <template> <script> import children from "./children"; export default { name:'index', components: {Children}, data () { return { count:0 } }, methods:{ addCount(data){ this.count = data.count; } } } </script>
子組件
<template> <div> <h3>計數(shù)器:{{count}}</h3> <button @click='add'>+++</button> </div> </template> <script> export default { name:'children', props:['count'], // 用來接收父組件傳給子組件的數(shù)據(jù) methods:{ add() { // 觸發(fā)父組件的方法 this.$emit('addCount',{count: count + 1}); } } } </script>
$on
$on(‘事件名’,callback)監(jiān)聽事件,監(jiān)聽當前實例上的自定義事件
父組件
<template> <div> <span>{{count}}</span> <children/> </div> <template> <script> import { bus } from '../main.js'; import children from "./children"; export default { name:'index', components: {Children}, data () { return { count:0 } }, mounted(){ bus.$on('addCount',(val)=>{ this.count++; }) } } </script>
子組件
<template> <button @click='add'>count+++</button> </template> <script> import { bus } from '../main.js'; export default { name:'children', methods:{ add() { // 觸發(fā)父組件的方法 bus.$emit('addCount',{}); } } } </script>
main文件
export var bus = new Vue();
注意: e m i t 和 emit和 emit和on的事件必須在一個公共的實例上, e m i t 觸 發(fā) 的 事 件 emit觸發(fā)的事件 emit觸發(fā)的事件on才能監(jiān)聽到。
$parent(不常用)
指向當前組件樹的根實例,如果當前實例沒有父實例,則實例將會指向自己。
- $parent既可以接受父組件數(shù)據(jù),又可以修改父組件數(shù)據(jù),是雙向的。
- $parent可以調用父組件的方法
子組件
<template> <button @click='actionParent'>觸發(fā)父組件發(fā)方法</button> </template> <script> export default { name:'children', methods:{ actionParent() { console.log(this.$parent.name); this.$parent.parentPrint(); // 觸發(fā)父組件的方法 } } } </script>
$children(不常用)
指向當前實例的直接子組件,返回的是一個組件的集合。
需要注意: children 并 不 保 證 順 序 , 也 不 是 響 應 式 的 。 如 果 你 發(fā) 現(xiàn) 自 己 正 在 嘗 試 使 用 children并不保證順序,也不是響應式的。如果你發(fā)現(xiàn)自己正在嘗試使用 children并不保證順序,也不是響應式的。如果你發(fā)現(xiàn)自己正在嘗試使用children進行數(shù)據(jù)綁定,考慮使用一個數(shù)組配合v-for來生成子組件,并且使用Array作為真正的來源。
for(let i=0; i<this.$children.length; i++){ console.log(this.$children[i].name); // 輸出子組件的name }
$attrs
包含了父作用域中不作為prop被識別(且獲取)的特性綁定(class,style除外)。當一個組件沒有聲明任何prop時,這里會包含所有父作用域的綁定,并且可以通過v-bind="$attrs"傳入內部組件–在創(chuàng)建高級別的組件時非常有用。
簡單說:接收除了props聲明外的所有綁定屬性(calss,style除外)
上圖的$attrs中只有age,gender兩個屬性{ age: “20”, gender: “man” }
在grandson上通過v-bind="$attrs",可以將屬性繼續(xù)向下傳遞,讓grendson也能訪問到父組件的屬性。
這種方式當傳遞多個屬性時會顯得很便捷,不需要一條一條進行綁定。
如果想要添加其他屬性,可繼續(xù)綁定屬性,注意:繼續(xù)綁定的屬性和$attr中的屬性有重復時,繼續(xù)綁定的屬性優(yōu)先級會更高
$listeners
包含了父級作用域中的(不含.native修飾器的)v-on事件監(jiān)聽器,他可以通過v-on="$listeners"傳入內部組件–在創(chuàng)建更高層次的組件時非常有用。
簡單說:接收除了帶有.native事件修飾符的所有事件監(jiān)聽器
child組件綁定了帶有.native的click事件和一個自定義事件,$listeners輸出的結果為:{customEvent:fn}
通過v-on=" listeners"將事件監(jiān)聽器繼續(xù)向下傳遞,讓grandson訪問到事件。并且可以使用emit觸發(fā)傳遞下來的事件。
如果想要添加其他事件監(jiān)聽器,可以繼續(xù)綁定事件
注意:繼續(xù)綁定的事件和$listeners中的事件有重復的時候,不會被覆蓋。當grandson觸發(fā)customEvent時,child和parent的事件都會被觸發(fā),觸發(fā)順序類似于冒泡。
使用場景
- 組件傳值時使用,父親,兒子,孫子三級傳遞參數(shù)交互。
- 對一些UI庫進行二次封裝的時候使用,比如element-ui中的組件不能滿足自己的使用場景時,會二次封裝,但是又想保留它自己的屬性和方法,這個時候使用。
$refs
this.$refs是一個對象,持有當前組件中注冊過ref特性的所有DOM元素和子組件實例
注意:$refs只有在組件渲染完成之后才填充,在初始渲染的時候不能訪問他們,并且它是非響應式的,因此不能用它在模版中做數(shù)據(jù)綁定。
父組件
<template> <div> <div ref="testDom">123</div> <child ref="child" /> <button @click="openChild" >觸發(fā)子組件</button> </div> </template> <script> import Child form './child.vue' export default { components:{ Child }, mounted(){ console.log(this.$refs.testDom) // <div>123</div> console.log(this.$refs.child.name) // 粉刷匠 }, methods:{ openChild(){ this.$refs.child.open(); } } } </script>
子組件
<template> <div>{{name}}</div> </template> <script> export default { data(){ return { name:"粉刷匠" } }, methods:{ open(){ alter("點擊了") } } } </script>
注意:當ref和v-for一起使用的時候,獲取到的將會是一個數(shù)組,包含循環(huán)數(shù)組源。
provide && inject
provide/inject是vue2.2版本之后新增的高級組件,這兩個組件要一起使用。
允許一個祖先組件向其所有的子孫后代注入一個依賴。無論組件層次有多深,并在其上下游關系成立的事件里始終有效。類似于React的上下文。
provide選項是一個對象 或返回一個對象的函數(shù)。該對象包含可注入其子孫的property。
inject有下面兩種:
- 一個字符串數(shù)組
- 一個對象
- 對象的key是本地的綁定名,
- value
- 在可用的注入內容中搜索用的key(字符串/Symbol)
- 或一個對象
- from property是在可用的注入內容中搜索用的key(字符串/Symbol)
- default property是降級情況下使用的value
provide和inject綁定并不是可響應的,這是vue官方刻意為之的。如果你傳入一個可監(jiān)聽的對象,那么其對象的property還是可響應的。
缺點:在任意層級都能訪問導致數(shù)據(jù)追蹤比較難,所以provide/inject能不使用就不使用,盡量使用vuex。在組件庫開發(fā)的可以使用
副組件
<template> <div class="test"> <son prop="data"></son> </div> </template> <script> export default { name: 'Father', provide: { chontrol: this } data(){ return { name:"啊哈哈" } } }
// 某一級子組件/孫子組件
<template> <div> {{name}} </div> </template> <script> export default { name: 'son', inject: ["chontrol"] props: { name: { type: Object, default: () => ({}), }, } }, } </script>
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
Vue——解決報錯 Computed property "****" was assigned to but it ha
這篇文章主要介紹了Vue——解決報錯 Computed property "****" was assigned to but it has no setter.的方法,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12vue中的vue-router?query方式和params方式詳解
這篇文章主要介紹了vue中的vue-router?query方式和params方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08