Vue 組件通信的 8 種方式
前言
做了半年的公司系統,終於就在前天上線了。後期改 BUG 時間拖得太長了,出現的大部分 BUG 是 前端 與 後端 信息不對稱導致的,邏輯性錯誤很不多,用戶體驗上稍微差點,畢竟第一次做這麼大的系統 (100w+),通過這次系統的開發,總結了不少經驗,如何更好的跟後端人員協作開發以及如何設計來提高用戶體驗上,之前自己做開發沒關注這方面,只注重功能實現,後期的這塊多補補。
項目上線後,接下來就是後期的維護更新了,最近時間終於不是之前那麼忙碌了,簡單的對系統做了下覆盤。由於項目採用的技術棧是Vue
, 平常開發只注重功能實現了,接下來陸續會對 Vue
深入分析, 來封裝常用業務組件,以及Vue源碼解析
本章將是對 Vue 組件通信的 8 方法總結,日常開發組件通信密切,熟悉組件通信可以更好的開發業務。
Vue
組件之間傳值
1. 父組件 向 子組件 傳遞值
-
在父組件中引入子組件
-
註冊子組件
-
在頁面中使用,子組件標籤上 動態綁定傳入動態值 / 靜態值
-
在子組件中,使用 props 來接受 父組件 傳遞過了的值
子組件接收的父組件的值分爲引用類型和普通類型兩種:
-
普通類型:字符串(String)、數字(Number)、布爾值(Boolean)、空(Null)
-
引用類型:數組(Array)、對象(Object)
#父組件
<template>
<div>
<!-- 傳遞值 -->
<Test
:obj="obj"
info="測試"/>
</div>
</template>
<script>
// 引入子組件
import Test from "../components/Test.vue";
export default {
name: "about",
// 註冊子組件
components: {
Test,
},
data() {
return {
obj: {
code: 200,
title: "前端自學社區",
},
};
},
};
</script>
<template>
<div>
<h1>{{obj.code}}</h1><br>
<h2>{{obj.title}}</h2>
<h3>{{info}}</h3>
</div>
</template>
<script>
export default {
name:'test',
props:{
obj:Object,
info: [String,Number] //info值爲其中一種類型即可,其他類型報警告
}
}
</script>
由於 Vue
是 單向數據流, 子組件
是不能直接 修改 父組件
的 值。
2. 子組件 向父組件傳遞值
子組件通過綁定事件,通過 this.$emit('函數名',傳遞參數)
#父組件
<Test
:obj="obj"
info="測試"
@modify="modifyFatherValue"/>
<script>
// 引入子組件
import Test from "../components/Test.vue";
export default {
name: "about",
// 註冊子組件
components: {
Test,
},
data() {
return {
msg:'我是父組件'
};
},
methods:{
// 接受子組件傳遞來的值,賦值給data中的屬性
modifyFatherValue(e){
this.msg = e
}
}
};
</script>
# 子組件
<button @click="modifyValue">修改父組件的值</button>
<script>
export default {
name:'test',
methods:{
modifyValue(){
this.$emit('modify','子組件傳遞過來的值')
}
}
}
</script>
3. 父組件 通過 $refs
/ $children
來獲取子組件值
$refs
:
-
獲取 DOM 元素 和 組件實例來獲取組件的屬性和方法。
-
通過在 子組件 上綁定
ref
,使用this.$refs.refName.子組件屬性 / 子組件方法
$children
:
- 當前實例的子組件,它返回的是一個子組件的集合。如果想獲取哪個組件屬性和方法,可以通過
this.$children[index].子組件屬性/f方法
示例 Text 組件
<script>
export default {
name:'test',
data() {
return {
datas:"我是子組件值"
}
},
props:{
obj:Object,
info: [String,Number]
},
methods:{
getValue(){
console.log('我是Test1')
}
}
}
</script>
示例 Text2 組件
<template>
<div>
<h1>我是Test2</h1>
</div>
</template>
<script>
export default {
name:'test',
data() {
return {
datas:"我是Test2"
}
},
created(){
console.log( this.$parent.obj )
this.$parent.getQuery()
},
methods:{
getTest2(){
console.log(this.datas)
}
}
}
</script>
refs
<template>
<div>
// 給子組件上綁定 ref
<Test
ref="son"
/>
<Test2/>
</div>
</template>
// 通過 $refs 示例來獲取 子組件的屬性和方法
console.log( this.$refs.son.datas)
this.$refs.son.getValue()
$children
// 通過 $children 來獲取 子組件的屬性和方法
this.$children[0].getValue(); // 我是 Test1
this.$children[1].getTest2(); //我是 Test2
console.log(`---------${this.$children[1].datas}`); //我是Test2
4. 子組件 通過 $parent
來獲取父組件實例的屬性和方法
<script>
export default {
name:'test',
created(){
console.log( this.$parent.obj )
this.$parent.getQuery()
},
}
</script>
5. $attrs
和 $listeners
獲取父組件實例屬性和方法 (組件嵌套情況下使用)
$attrs
:包含了父作用域中不被認爲 (且不預期爲) props
的特性綁定 (class 和 style 除外),並且可以通過 v-bind=” $attrs
” 傳入內部組件。當一個組件沒有聲明任何 props
時,它包含所有父作用域的綁定 (class 和 style 除外)。
$listeners
:包含了父作用域中的 (不含 .native 修飾符) v-on 事件監聽器。它可以通過 v-on=”$listeners
” 傳入內部組件。它是一個對象,裏面包含了作用在這個組件上的所有事件監聽器,相當於子組件繼承了父組件的事件。
使用場景:多層嵌套組件的情況下使用,可以避免使用 Vuex 來做數據處理, 使用 v-bind="$attrs" v-on="$listeners"
很方便達到業務數據傳遞。
父組件
<template>
<div>
<Test3
:status="status"
:title="title"
@getData="getData" />
</div>
</template>
<script>
import Test3 from "../components/Test3.vue";
export default {
name:'person',
data(){
return {
title:'personal 組件',
status: false
}
},
methods:{
getData(){
console.log(this.title)
}
},
components:{
Test3
}
}
</script>
子組件 1
<template>
<div>
<h1>Test3 組件</h1>
<br /><br />
// 通過 $attrs(屬性,除了【props中定義的屬性】) 和 $listeners(方法) 來給嵌套子組件傳遞父組件的屬性和方法
<Test4 v-bind="$attrs" v-on="$listeners"/>
</div>
</template>
<script>
// 引入子子組件
import Test4 from "../components/Test4";
export default {
name: "test3",
props: ["title"],
components: {
Test4,
},
created() {
console.log(this.$attrs); //{status: false}
console.log("-----------");
console.log(this.$listeners); // {getData: ƒ}
},
};
</script>
嵌套子組件
<template>
<div>
<h1>Test4 組件</h1>
</div>
</template>
<script>
export default {
name:'test4',
created(){
console.log('-----Test4------')
console.log(this.$attrs) //{status: false}
console.log(this.$listeners) // {getData: ƒ}
}
}
</script>
6. 跨組件之間傳值
通過新建一個 js
文件,導入 vue
, 導出 vue
實例;然後通過 給導出的實例 上綁定事件 $emit
事件 , 然後再通過 $on
監聽觸發的事件,這樣就可以達到全局組件數據共享。
使用場景:
它可以滿足任意場景傳遞數據, 父子組件傳值
, 子父傳值
, 兄弟組件之間傳值
, 跨級組件之間傳值
.
通信數據比較簡單時,可以採用這種 方案,項目比較龐大,可以採用 Vuex
.
vue .js
/*
* @Description:
* @Author: ZhangXin
* @Date: 2021-01-22 15:48:56
* @LastEditTime: 2021-01-22 15:51:24
* @LastEditors: ZhangXin
*/
import Vue from 'vue'
export default new Vue()
組件 A
<!--
* @Description:
* @Author: ZhangXin
* @Date: 2021-01-22 14:44:17
* @LastEditTime: 2021-01-22 16:25:33
* @LastEditors: ZhangXin
-->
<template>
<div>
<button @click="changeValue">改變</button>
</div>
</template>
<script>
import zxVue from '../util/newVue.js';
export default {
name:'person',
data(){
return {
title:'personal 組件',
status: false
}
},
methods:{
changeValue(){
// 通過給 vue實例綁定事件
zxVue.$emit("getTitle", this.title)
}
}
}
</script>
組件 C
<!--
* @Description:
* @Author: ZhangXin
* @Date: 2021-01-22 15:07:30
* @LastEditTime: 2021-01-22 16:26:38
* @LastEditors: ZhangXin
-->
<template>
<div>
<h1>Test4 組件</h1>
<h1>{{ title }}</h1>
</div>
</template>
<script>
import zxVue from "../util/newVue";
export default {
name: "test4",
data() {
return {
title: "test4",
};
},
mounted(){
// 通過 vue 實例.$on 監聽事件名,來接收跨級組件傳遞過來的值
zxVue.$on("getTitle", (item) => {
this.title = item;
console.log(item)
});
}
};
</script>
7. Vuex
這裏就不介紹了,完了單獨寫一篇文章精講 Vuex
8. provide
和 inject
實現父組件向子孫孫組件傳值。(層級不限)
provide
和 inject
這對選項需要一起使用,以允許一個祖先組件向其所有子孫後代注入一個依賴,不論組件層次有多深,並在起上下游關係成立的時間裏始終生效。
provide
:
-
是一個對象或返回一個對象的函數
-
該對象包含可注入其子孫的屬性。
inject
:
-
是一個字符串數組 或者是一個對象
-
用來在子組件或者子孫組件中注入
provide
提供的父組件屬性。
使用場景:
provide/inject可以輕鬆實現跨級訪問父組件的數據
# provide
//對象
provide:{
name:'測試'
}
//返回對象的函數
provide(){
return {
name: '測試'
}
}
#inject
inject:['name']
父組件
<!--
* @Description:
* @Author: ZhangXin
* @Date: 2021-01-22 23:24:16
* @LastEditTime: 2021-01-22 23:49:50
* @LastEditors: ZhangXin
-->
<template>
<div>
<h1>我是父組件</h1>
<Son />
</div>
</template>
<script>
import Son from '../components/son/SonOne'
export default {
name:'father',
provide(){
return {
titleFather: '父組件的值'
}
},
components:{
Son
},
data(){
return{
title:'我是父組件 '
}
},
}
</script>
子組件
<template>
<div>
<h1>我是子孫組件</h1>
</div>
</template>
<script>
import SonTwo from '../son/SonTwo'
export default {
name:'sonone',
components:{
SonTwo
},
inject:['titleFather'],
created(){
console.log(`${this.titleFather}-----------SonTwo`)
},
data(){
return{
title:'我是子組件 '
}
},
}
</script>
子孫組件
<template>
<div>
<h1>我是子孫組件</h1>
</div>
</template>
<script>
import SonTwo from '../son/SonTwo'
export default {
name:'sonone',
components:{
SonTwo
},
inject:['titleFather'],
created(){
console.log(`${this.titleFather}-----------SonTwo`)
},
data(){
return{
title:'我是子組件 '
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/dWV5pIpY7Gm2w5vE3ZkeJQ