1. 程式人生 > 其它 >vue原始碼學習第五篇--父子元件通訊方式

vue原始碼學習第五篇--父子元件通訊方式

文章目錄

props(父元件向子元件傳值)

vue中父子元件通訊的第一種方式是通過props屬性。是父元件向子元件通訊。
接下來我們通過一個例子,說明父元件如何向子元件傳遞值:在子元件Users.vue中如何獲取父元件App.vue中的資料 users:["Henry","Bucky","Emily"]

//App.vue父元件
<template>
  <div id="app"
> <users :users="users"></users>//前者自定義名稱便於子元件呼叫,後者要傳遞資料名 </div> </template> <script> import Users from "./components/Users" export default { name: 'App', data(){ return{ users:["Henry","Bucky","Emily"] }
}, components:{ "users":Users } }
//users子元件
<template>
  <div class="hello">
    <ul>
      <li v-for="user in users">{{user}}</li>//遍歷傳遞過來的值,然後呈現到頁面
    </ul>
  </div>
</template>
<script>
export default {
  name:
'HelloWorld', props:{ users:{ //這個就是父元件中子標籤自定義名字 type:Array, required:true } } } </script>

$emit(子元件傳送資料)

//相當於又new了一個vue例項,Event中含有vue的全部方法;
var Event = new Vue(); 
Event.$emit(事件名,資料);

接下來我們通過一個例子,說明子元件如何向父元件傳遞值:當我們點選子元件中title資料後,子元件向父元件傳遞值,文字由原來的“傳遞的是一個值”變成“子向父元件傳值”,實現子元件向父元件值的傳遞。

// 子元件
<template>
  <header>
    <h1 @click="changeTitle">{{title}}</h1>//繫結一個點選事件
  </header>
</template>
<script>
export default {
  name: 'app-header',
  data() {
    return {
      title:"Vue.js Demo"
    }
  },
  methods:{
    changeTitle() {
      this.$emit("titleChanged","子向父元件傳值");//自定義事件  傳遞值“子向父元件傳值”
    }
  }
}
</script>
// 父元件
<template>
  <div id="app">
    <app-header v-on:titleChanged="updateTitle" ></app-header>//與子元件titleChanged自定義事件保持一致
   // updateTitle($event)接受傳遞過來的文字
    <h2>{{title}}</h2>
  </div>
</template>
<script>
import Header from "./components/Header"
export default {
  name: 'App',
  data(){
    return{
      title:"傳遞的是一個值"
    }
  },
  methods:{
    updateTitle(e){   //宣告這個函式
      this.title = e;
    }
  },
  components:{
   "app-header":Header,
  }
}
</script>

$on (子元件接收資料)

//相當於又new了一個vue例項,Event中含有vue的全部方法;
var Event = new Vue(); 
Event.$on(事件名,data => {});

假設兄弟元件有三個,分別是A、B、C元件,C元件如何獲取A或者B元件的資料

<div id="itany">
    <my-a></my-a>
    <my-b></my-b>
    <my-c></my-c>
</div>
<template id="a">
  <div>
    <h3>A元件:{{name}}</h3>
    <button @click="send">將資料傳送給C元件</button>
  </div>
</template>
<template id="b">
  <div>
    <h3>B元件:{{age}}</h3>
    <button @click="send">將陣列傳送給C元件</button>
  </div>
</template>
<template id="c">
  <div>
    <h3>C元件:{{name}}{{age}}</h3>
  </div>
</template>
<script>
var Event = new Vue();//定義一個空的Vue例項
var A = {
    template: '#a',
    data() {
      return {
        name: 'tom'
      }
    },
    methods: {
      send() {
        Event.$emit('data-a', this.name);
      }
    }
}
var B = {
    template: '#b',
    data() {
      return {
        age: 20
      }
    },
    methods: {
      send() {
        Event.$emit('data-b', this.age);
      }
    }
}
var C = {
    template: '#c',
    data() {
      return {
        name: '',
        age: ""
      }
    },
    mounted() {//在模板編譯完成後執行
     Event.$on('data-a',name => {
     //箭頭函式內部不會產生新的this,這邊如果不用=>,this指代Event
         this.name = name;
     })
     Event.$on('data-b',age => {
         this.age = age;
     })
    }
}
var vm = new Vue({
    el: '#itany',
    components: {
      'my-a': A,
      'my-b': B,
      'my-c': C
    }
});    
</script>

在這裡插入圖片描述
$on 監聽了自定義事件 data-a和data-b,因為有時不確定何時會觸發事件,一般會在 mounted 或 created 鉤子中來監聽。

$parent / $children與 ref

  • ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子元件上,引用就指向元件例項
  • $parent / $children:訪問父 / 子例項

需要注意的是:這兩種都是直接得到元件例項,使用後可以直接呼叫元件的方法或訪問資料。我們先來看個用 ref來訪問元件的例子:

// component-a 子元件
export default {
  data () {
    return {
      title: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      window.alert('Hello');
    }
  }
}
// 父元件
<template>
  <component-a ref="comA"></component-a>
</template>
<script>
  export default {
    mounted () {
    //通過this.$refs.comA可以獲取到子元件的方法和資料
      const comA = this.$refs.comA; 
      console.log(comA.title);  // Vue.js
      comA.sayHello();  // 彈窗
    }
  }
</script>

不過,這兩種方法的弊端是,無法在跨級或兄弟間通訊。

// parent.vue
<component-a></component-a>
<component-b></component-b>
<component-b></component-b>

我們想在 component-a 中,訪問到引用它的頁面中(這裡就是 parent.vue)的兩個 component-b 元件,那這種情況下,就得配置額外的外掛或工具了,比如 Vuex 和 Bus 的解決方案。

總結

常見使用場景可以分為三類:

父子通訊:

  • 向子傳遞資料是通過 props,子向父是通過 events($emit);通過父鏈 / 子鏈也可以通訊($parent / $children);ref 也可以訪問元件例項;provide / inject API;$attrs/$listeners

兄弟通訊:

  • Bus;Vuex

跨級通訊:

  • Bus;Vuex;provide / inject API、$attrs/$listeners