Vue中的8種組件通訊方式

  Vue是數據驅動視圖更新的框架,因此對於vue來講組件間的數據通訊很是重要。html

  常見使用場景能夠分爲三類:vue

    • 父子組件通訊: props / $emit $parent / $children provide / inject ref $attrs / $listeners程序員

    • 兄弟組件通訊: eventBus Vuex數組

    • 跨級通訊: eventBus Vuex provide / inject $attrs / $listenerssession

 

1、props / $emit (最經常使用的組建通訊方式)

  父組件經過props的方式向子組件傳遞數據,而經過$emit 子組件能夠向父組件通訊。app

  1. 父組件向子組件傳值(props)

    • 傳入一個靜態的值框架

  <blog-post title="My journey with Vue"></blog-post>
    • 傳入一個動態的值,任何類型的值均可以傳給一個 prop。ide

  <blog-post v-bind:title="post.title"></blog-post>
  <blog-post v-bind:likes="42"></blog-post>
  <blog-post v-bind:is-published="false"></blog-post>
  <blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post
  <blog-post
    v-bind:author="{
      name: 'Veronica',
      company: 'Veridian Dynamics'
    }"
  ></blog-post>

     總結:props 只能夠在父子組件中通訊,即單向數據流。並且 props 是只讀的,不能夠被修改,全部修改都會被警告。函數

  2. 子組件向父組件傳值($emit)

  子組件經過 $emit 將參數傳遞給父組件,父組件經過v-on監聽並接收參數。post

Vue.component('welcome-button', {
  template: `
    <button v-on:click="$emit('welcome')">
      Click me to be welcomed
    </button>
  `
})
<div id="emit-example-simple">
  <welcome-button v-on:welcome="sayHi"></welcome-button>
</div>
new Vue({
  el: '#emit-example-simple',
  methods: {
    sayHi: function () {
      alert('Hi!')
    }
  }
})

 

2、 $children / $parent

  $parent 能夠訪問到當前組件的父組件實例,$children 能夠訪問到當前組件的子組件實例。

// 父組件中
<template>
  <div class="hello_world">
    <div>{{msg}}</div>
    <com-a></com-a>
    <button @click="changeA">點擊改變子組件值</button>
  </div>
</template><script>
import ComA from './test/comA.vue'
export default {
  name: 'HelloWorld',
  components: { ComA },
  data() {
    return {
      msg: 'Welcome'
    }
  },
​
  methods: {
    changeA() {
      // 獲取到子組件A
      this.$children[0].messageA = 'this is new value'
    }
  }
}
</script>
// 子組件中
<template>
  <div class="com_a">
    <span>{{messageA}}</span>
    <p>獲取父組件的值爲:  {{parentVal}}</p>
  </div>
</template><script>
export default {
  data() {
    return {
      messageA: 'this is old'
    }
  },
  computed:{
    parentVal(){
      return this.$parent.msg;
    }
  }
}
</script>

  注意:$parent 和 $children 獲得的值不同,$children 的值是數組,而 $parent 是個對象

 

3、provide/ inject

  provide/ inject 就是父組件中經過provide來提供變量, 而後在子組件中經過inject來注入變量。

  provide 是一個對象或返回一個對象的函數。inject 是一個數組對象

  注意: 這裏不論子組件嵌套有多深, 只要調用了inject 那麼就能夠注入provide中的數據,而不侷限於只能從當前父組件的props屬性中獲取數據。

// 父級組件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}
​
// 子組件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

 

4、ref / refs

  ref:在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;用在組件上,引用就指向組件實例,能夠經過實例直接調用組件的方法或訪問數據。

<base-input ref="usernameInput">
    <input ref="input">
</base-input>
<script>
    methods: {
     // 用來從父級組件聚焦輸入框
        focus: function () {
        this.$refs.input.focus()
  }
}
</script>

 

5、eventBus

  eventBus 又稱爲事件總線,在vue中是全部組件共用相同的事件中心,能夠向該中心註冊發送事件或接收事件。

  1. 初始化

  首先須要建立一個事件總線並將其導出, 以便其餘模塊可使用或者監聽它.

// event-bus.js
​
import Vue from 'vue'
export const EventBus = new Vue()

  2. 發送事件

  假設你有兩個組件: additionNum 和 showNum, 這兩個組件能夠是兄弟組件也能夠是父子組件;這裏咱們以兄弟組件爲例:

<template>
  <div>
    <show-num-com></show-num-com>
    <addition-num-com></addition-num-com>
  </div>
</template><script>
import showNumCom from './showNum.vue'
import additionNumCom from './additionNum.vue'
export default {
  components: { showNumCom, additionNumCom }
}
</script>
  1. // addtionNum.vue 中發送事件 ​ <template> <div> <button @click="additionHandle">+加法器</button> </div> </template>
  1. <script> import {EventBus} from './event-bus.js' console.log(EventBus) export default { data(){ return{ num:1 } }, ​ methods:{ additionHandle(){ EventBus.$emit('addition', { num:this.num++ }) } } } </script>

  3. 接收事件

// showNum.vue 中接收事件
​
<template>
  <div>計算和: {{count}}</div>
</template><script>
import { EventBus } from './event-bus.js'
export default {
  data() {
    return {
      count: 0
    }
  },
​
  mounted() {
    EventBus.$on('addition', param => {
      this.count = this.count + param.num;
    })
  }
}
</script>

  這樣就實現了在組件addtionNum.vue中點擊相加按鈕, 在showNum.vue中利用傳遞來的 num 展現求和的結果.

  4. 移除事件監聽者

  若是想移除事件的監聽, 能夠像下面這樣操做:

import { eventBus } from 'event-bus.js'
EventBus.$off('addition', {})

 

6、Vuex

  Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,主要解決的是開發大型單頁面項目的組件通訊問題。

  若是你還想對Vuex 有更多的瞭解,能夠看個人另外一篇博客:http://www.javashuo.com/article/p-dlxvbznm-ey.html

 

7、$attrs與 $listeners

  爲了解決該需求,引入了$attrs 和$listeners , 新增了inheritAttrs 選項。 默認狀況下,父做用域中不做爲 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外),將會「回退」且做爲普通的HTML特性應用在子組件的根元素上。接下來看一個跨級通訊的例子:

// app.vue
// index.vue
​
<template>
  <div>
    <child-com1
      :name="name"
      :age="age"
      :gender="gender"
      :height="height"
      title="程序員成長指北"
    ></child-com1>
  </div>
</template>
<script>
const childCom1 = () => import("./childCom1.vue");
export default {
  components: { childCom1 },
  data() {
    return {
      name: "zhang",
      age: "18",
      gender: "",
      height: "158"
    };
  }
};
</script>
// childCom1.vue
​
<template class="border">
  <div>
    <p>name: {{ name}}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
const childCom2 = () => import("./childCom2.vue");
export default {
  components: {
    childCom2
  },
  inheritAttrs: false, // 能夠關閉自動掛載到組件根元素上的沒有在props聲明的屬性
  props: {
    name: String // name做爲props屬性綁定
  },
  created() {
    console.log(this.$attrs);
     // { "age": "18", "gender": "女", "height": "158", "title": "程序員成長指北" }
  }
};
</script>
// childCom2.vue
​
<template>
  <div class="border">
    <p>age: {{ age}}</p>
    <p>childCom2: {{ $attrs }}</p>
  </div>
</template>
<script>
​
export default {
  inheritAttrs: false,
  props: {
    age: String
  },
  created() {
    console.log(this.$attrs); 
    // { "gender": "女", "height": "158", "title": "程序員成長指北" }
  }
};
</script>

 

8、localStorage / sessionStorage

  經過 window.localStorage.getItem(key) 獲取數據,經過 window.localStorage.setItem(key,value) 存儲數據。

 

  總結:

  1. props / $emit 是使用最多,也最推薦的方式。適用於父子組件通訊。

  2. Vuex 是 Vue 官方提供的組件通訊方式,適用於構建大型單頁面項目。

  3. $children / $parent ,ref ,$attr / $listener 主要是經過操做父子組件的實例來獲取組件的數據,實現組件通訊。

相關文章
相關標籤/搜索