1. 程式人生 > 程式設計 >八種Vue元件間通訊方式合集(推薦)

八種Vue元件間通訊方式合集(推薦)

前言

Vue 提供了各種各樣的通訊,其中包括 兄弟間 的通訊和 非兄弟間 的通訊,藉此機會做個總結,查閱起來方便。如果喜歡的話可以幫忙點個贊 :+1: 或者關注一下 :yum:

1、props

目錄結構

components
 ├── Parent.vue // 父親
 ├── Son1.vue  // 兒子1

程式碼結構

在父親元件中使用兒子元件,給兒子通過 :date="xxx" 單向傳值

<template>
 <div>
 <div>爸爸:{{date}}</div>
 <Son1 :date="date"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },data() {
 return {
  date: 1,};
 },};
</script>

兒子元件通過 props 接受父元件傳過來的值

<template>
 <div>兒子:{{date}}</div>
</template>
<script>
export default {
 props: {
 date: {
  type: Number,//校驗型別
  default: "1",},};
</script>

2、$emit

目錄結構

components
 ├── Parent.vue // 父親
 ├── Son1.vue  // 兒子1

程式碼結構

子元件通過觸自身的方法來觸發 $emit 方法,再觸發父元件的方法,通過 回撥傳參

的方式將修改的內容傳遞給父元件

<template>
 <div>
 <div>兒子:{{date}}</div>
 <button @click="changeNum">修改</button>
 </div>
</template>
<script>
export default {
 props: {
 date: {
  type: Number,default: "1",methods: {
 changeNum() {
  this.$emit("changeNum",2);
 },};
</script>

父元件接受回撥 params 引數,即爸爸需要給兒子綁定了一個自定義的事件, $on("changeNum",params)

<template>
 <div>
 <div>爸爸:{{date}}</div>
 <Son1 :date="date" @changeNum="changeNum"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },methods: {
 changeNum(params) {
  this.date = params;
 },};
</script>

.sync

目錄結構

components
 ├── Parent.vue // 父親
 ├── Son1.vue  // 兒子1

程式碼結構

子元件通過 $emit("update:xxx") 發射事件

<template>
 <div>
 <div>兒子:{{date}}</div>
 <button @click="changeNum">修改</button>
 </div>
</template>
<script>
export default {
 props: {
 date: {
  type: Number,methods: {
 changeNum() {
  this.$emit("update:date",};
</script>

父元件通過 :xxx.sync="xxx" 接受引數

<template>
 <div>
 <div>爸爸:{{date}}</div>
 <Son1 :date.sync="date"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },};
</script>
<Son1 :date.sync="date"></Son1>
//這個寫法是上面的替代品 預設元件內部觸發 update:count 規定寫法
<Son1 :date="date" @update:date="val=>date=val"></Son1>

v-model

目錄結構

components
  ├── Parent.vue  // 父親
  ├── Son1.vue   // 兒子1

程式碼結構

子元件觸發的事件只能是 input 事件,接收 props 的屬性名只能叫 value

<template>
 <div>
  <div>兒子:{{value}}</div>
  <button @click="changeNum">修改</button>
 </div>
</template>
<script>
export default {
 props: {
  value: {
   type: Number,default: 1,methods: {
  changeNum() {
   this.$emit("input",2);
  },};
</script>

父元件通過 v-model 接收引數

<template>
 <div>
  <div>爸爸:{{value}}</div>
  <Son1 v-model="value"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },data() {
  return {
   value: 1,};
</script>
<Son1 :value="value" @input="val=>value=val"></Son1>
//這個寫法是上面的替代品 預設元件內部觸發 input 規定寫法
<Son1 v-model="value"></Son1>

v-model 侷限只能傳遞一個屬性 如果只有一個 可以使用 v-model 多個依然需要使用 .sync

3、 $parent和 $children

目錄結構

components
  ├── Parent.vue  // 父親
  ├── Son1.vue   // 兒子1
  ├── Grandson1.vue //孫子1

程式碼結構

如下場景:孫子想要給爺爺傳遞資料,孫子需要找到爺爺身上的事件去傳遞 $parent.$emit

<template>
 <div>
  <div>孫子{{value}}</div>
  <button @click="$parent.$emit('change',3)">修改</button>
 </div>
</template>
<script>
export default {
 props: {
  value: {
   type: Number,default: "",};
</script>

兒子元件使用孫子元件

<template>
 <div>
  <div>兒子:{{value}}</div>
  <grandson1 :value="value"></grandson1>
 </div>
</template>
<script>
import grandson1 from "./grandson1";
export default {
 components: {
  grandson1,props: {
  value: {
   type: Number,};
</script>

爸爸身上給孫子自定義change事件

<template>
 <div>
  <div>爸爸:{{value}}</div>
  <Son1 @change="val=>value=val" :value="value"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },};
</script>

如果層級很深那麼就會出現 $parent.$parent..... 我們可以封裝一個 $dispatch 方法向上進行派發

Vue.prototype.$dispatch = function $dispatch(eventName,data) {
 let parent = this.$parent;
 while (parent) {
  parent.$emit(eventName,data);
  parent = parent.$parent;
 }
};

相同的道理,如果既然能夠向上尋找父親,就能向下尋找兒子,也可以封裝一個向下派發的方法 $broadcast

Vue.prototype.$broadcast = function $broadcast(eventName,data) {
 const broadcast = function () {
  this.$children.forEach((child) => {
   child.$emit(eventName,data);
   if (child.$children) {
    $broadcast.call(child,eventName,data);
   }
  });
 };
 broadcast.call(this,data);
};

4、 $attrs和 $listeners

目錄結構

components
  ├── Parent.vue  // 父親
  ├── Son1.vue   // 兒子1
  ├── Grandson1.vue //孫子1

$attrs 批量向下傳入屬性

<template>
 <div>
  <div>爸爸:{{value}}</div>
  <Son1 @change="val=>value=val" :value="value"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },};
</script>

在兒子元件中使用 $attrs屬性,配合 v-bind 可以將屬性繼續向下傳遞

<template>
 <div>
  <div>兒子:{{$attrs.value}}</div>
  <grandson1 v-bind="$attrs"></grandson1>
 </div>
</template>
<script>
import grandson1 from "./grandson1";
export default {
 components: {
  grandson1,mounted() {
  console.log(this.$attrs);
 },};
</script>

注意一點:在使用 $attrs的時候,如果元件中使用了 props 就會將屬性從當前 attrs 移除掉

在孫子元件中使用 $attrs屬性,可以將屬性繼續向下傳遞

<template>
 <div>
  <div>孫子{{$attrs.value}}</div>
 </div>
</template>
<script>
export default {
 //props: {
 // value: Number,//},};
</script>

如果爸爸傳遞給兒子元素,兒子有三個屬性用不到, 孫子傳遞給孫子,但是不想在頁面上這個屬性,可以設定 inheritAttrs: false

$listeners 批量向下傳入方法

<template>
 <div>
  <div>爸爸:{{value}}</div>
  <Son1 @click="change" :value="value"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },methods: {
  change() {
   this.value = 2;
  },};
</script>

可以在son1元件中使用 $listeners 屬性,配合 v-on 可以將方法繼續向下傳遞

<template>
 <div>
  <div>兒子:{{$attrs.value}}</div>
  <grandson1 v-bind="$attrs" v-on="$listeners"></grandson1>
 </div>
</template>
<script>
import grandson1 from "./grandson1";
export default {
 components: {
  grandson1,mounted() {
  console.log(this.$attrs);
  console.log(this.$listeners);
 },};
</script>

孫子元件可以直接使用 $listeners 上的方法

<template>
 <div>
  <div>孫子{{$attrs.value}}</div>
  <button @click="$listeners.click"></button>
 </div>
</template>
<script>
export default {
 mounted() {
  console.log(this.$attrs);
  console.log(this.$listeners);
 },};
</script>

5、Provide & Inject

目錄結構

app.vue
components
  ├── Parent.vue  // 父親
  ├── Son1.vue   // 兒子1
  ├── Grandson1.vue //孫子1

程式碼結構

在父級宣告一個公共資料

export default {
 provide() {
  return { vm: this };
 },};

在子元件中可以注入原理,會將資料掛載在當前例項上

<template>
 <div>
  <div>孫子</div>
 </div>
</template>
<script>
export default {
 inject: ["vm"],mounted() {
  console.log(this);
 },};
</script>

八種Vue元件間通訊方式合集(推薦)

注意事項:這個方法使用之後比較混亂,它一般 不會在業務程式碼中使用,經常是在元件庫或者多級通訊,為了方便你可以使用 provide

6、ref

目錄結構

components
  ├── Parent.vue  // 父親
  ├── Son1.vue   // 兒子1

程式碼結構

ref 獲取的是真實的dom元素,如果放到元件上代表的是 當前元件的例項 。 父元件中可以直接獲取子元件的方法或者資料。

<template>
 <div>
  <div>爸爸</div>
  <Son1 ref="son"></Son1>
 </div>
</template>
<script>
import Son1 from "./son1";
export default {
 components: { Son1 },mounted() {
  this.$refs.son.show();
 },};
</script>
<template>
 <div>
  <div>兒子</div>
 </div>
</template>
<script>
export default {
 methods: {
  show() {
   console.log(1);
  },};
</script>

注意事項: ref 不要 重名,但是當且僅當使用 v-for 的時候會導致出現 陣列 情況

7、EventBus

目錄結構

main.js
components
  ├── Grandson1.vue  // 孫子1
  ├── Son2.vue   // 兒子2

程式碼結構

EventBus 可用於 跨元件 通知(不復雜的專案可以使用這種方式)

Vue.prototype.$bus = new Vue();

Grandson1元件和Son2相互通訊

<template>
 <div>孫子1</div>
</template>
<script>
export default {
 mounted() {
  this.$nextTick(() => {
   this.$bus.$emit("test","go");
  });
 },};
</script>

這裡的兒子2元件只能使用 $on 來觸發Grandson1元件事件

<template>
 <div>兒子2</div>
</template>
<script>
export default {
 mounted() {
  this.$bus.$on("test",(data) => {
   console.log(data);
  });
 },};
</script>

8、Vuex

Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。

八種Vue元件間通訊方式合集(推薦)

具體文件查閱

結尾

到此這篇關於八種Vue元件間通訊方式合集(推薦)的文章就介紹到這了,更多相關八種Vue元件間通訊方式合集(推薦)內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!