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