vue原始碼學習第五篇--父子元件通訊方式
阿新 • • 發佈:2021-01-30
文章目錄
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