vue元件間通訊
阿新 • • 發佈:2020-07-31
父元件通過props傳遞資料給子元件
父元件通過props屬性向子元件傳遞資料,子元件利用元件例項的props屬性定義元件需要接收的引數,在使用元件時通過attribute的方式傳入引數,如:
// 在子元件內定義元件接收一個引數 name
{
props: ['name']
}
// 父元件使用元件時傳遞引數 name
<child :name="name"></child>
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <parent></parent> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> //定義了元件 parent,在元件中使用 <child></child> 引用元件,並用 attribute 的方式將 name 傳遞給元件 child Vue.component('parent', { template: '<child :name="name"></child>', data() { return { name: '句號' } } }) //定義了元件 child,並用 props 接收一個引數 name。 Vue.component('child', { template: '<div>{{name}}</div>', props: ['name'] }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
定義props的型別和預設值
上面props接收一個元件引數陣列,實際上,props也可以接收一個物件,物件key為元件接收引數的引數名,其值是一個物件,屬性type用來指定引數的型別,屬性default用來指定引數預設值。
{
props: {
name: {
type: String,
default: '句號'
}
}
}
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <parent></parent> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> //定義了元件 parent,在元件中使用 <child></child> 兩次引用元件,<child :name="name" /> 的方式傳遞 name 值,<child/> 使用預設的 name 值。 Vue.component('parent', { template: '<div><child :name="name" /><child/></div>', data() { return { name: '慕課網' } } }) //定義了元件 child,並用 props 接收一個字串型別的引數 name,其預設值是:句號。 Vue.component('child', { template: '<div>{{name}}</div>', props: { name: { type: String, default: '句號' } } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
元件parent,在元件中使用
兩次引用元件, 的方式傳遞 name 值, 使用預設的 name 值。
注意,給陣列和物件型別的props設定預設值的時候,需要安裝以下的寫法:
props: {
detail: {
type: Object,
default: () => {
return {
name: '句號'
}
}
},
loves: {
type: Array,
default: () => {
return []
}
}
}
子元件通過$emit傳遞資料給父元件
子元件通過$emit傳遞事件給父元件,父元件通過$on監聽事件:
// 子元件定義事件
this.$emit('事件名稱', '傳遞的引數') //例: this.$emit('add', 111)
// 父元件監聽事件的觸發
<child @事件名稱="事件觸發的方法"/>
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<parent></parent>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
//定義了元件 parent,在元件中使用 <child :name="name" :age="age" @add="add"/> 引用元件,並繫結 add 事件,當事件 add 觸發時呼叫 methods 中的 add 函式。
Vue.component('parent', {
template: '<div><child :name="name" :count="count" @add="add"/></div>',
data() {
return {
name: '句號',
count: 18
}
},
methods: {
// 父元件通過 @事件名 監聽
// count 表示事件觸發傳遞的引數
add(count) {
this.count = count
}
}
})
//定義了元件 child,該元件接收兩個引數:1. 字串型別的 name,預設值為:句號。2. 數字型別的 age,預設值為 18。元件模版中,通過按鈕點選事件觸發 add 方法,該方法內部通過 $emit 觸發事件 add,並將 age + 1 的值作為引數傳遞。
Vue.component('child', {
template: '<div>我是:{{name}}, 我今年 {{count}}歲。<button @click="add">加一歲</button></div>',
props: {
name: {
type: String,
default: '句號'
},
count: {
type: Number,
default: 18
}
},
methods: {
add(){
// add -> 觸發的事件名
// this.count + 1 -> 觸發事件時傳遞的引數
this.$emit('add', this.count + 1)
}
}
})
var vm = new Vue({
el: '#app',
data() {
return {}
}
})
</script>
</html>
非父子元件間資料傳遞
- 對於兄弟元件的資料通訊:它們有共同的父元件,我們可以通過父元件傳遞的方式實現資料通訊。
- 對於子孫元件的資料通訊:可以通過 props 的方式向下逐層傳遞下去,也可以通過 $emit 將事件向上逐層傳遞。
- 對於非關係元件的資料通訊:通過使用一個空的Vue例項作為中央事件匯流排。
通過公有的父元件進行非父子元件間的通訊
假設現在有三個元件分別是
、 、 ,其中元件 是 和 的父元件, 和 為兄弟元件, 和 元件間的通訊可以藉助 來間接傳遞。它的流程大致是這樣:
通過$emit將資料傳遞給 , 再通過props將資料傳遞給 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<person @modify="modify"></person>
<!-- 將 name 和 age 傳遞給元件 detail。 -->
<detail :name="name" :count="count"/>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
//定義了元件 person,它通過 $emit 將元件內輸入的 name 和 age 傳遞給父元件。
Vue.component('person', {
template: '<div><div>姓名:<input type="text" v-model="name"/></div><div>年齡:<input type="text" v-model="count"/></div><button @click="modify">修改</button></div>',
data() {
return {
name: '句號',
count: 18
}
},
methods: {
modify() {
this.$emit('modify', {name: this.name, count: this.count})
}
}
})
//定義了元件 detail,它從父元件接收 name 和 age 兩個引數。
Vue.component('detail', {
template: '<div>我是:{{name}}, 我今年 {{count}}歲。</div>',
props: {
name: {
type: String,
default: '句號'
},
count: {
type: Number,
default: 18
}
},
methods: {
}
})
//接收了元件 person 傳遞過來的事件,並修改 name 和 age。
var vm = new Vue({
el: '#app',
data() {
return {
name: '句號',
count: 18
}
},
methods: {
modify(detail) {
this.name = detail.name
this.count = parseInt(detail.count)
}
}
})
</script>
</html>
通過使用一個空的 Vue 例項作為中央事件匯流排
在Vue中可以使用 EventBus 來作為溝通橋樑的概念,就像是所有元件共用相同的事件中心,可以向該中心註冊傳送事件或接收事件,所以元件都可以上下平行地通知其他元件。
首先我們需要做的是建立事件匯流排,並將它掛載到Vue原型上,在例項中通過this.bus.$emit傳送事件,通過this.bus.$on接收事件。
// 定義事件匯流排
let bus = new Vue()
Vue.prototype.bus = bus
// 定義傳送事件
this.bus.$emit('事件名稱', data)
// 定義接收事件 並在回撥中接收引數
this.bus.$on('事件名稱', (data) => {
})
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<person></person>
<detail />
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
//通過 new Vue() 建立一個 vue 例項,並將它掛載在 Vue 的原型上。這樣,在 vue 元件中可以通過 this.bus 訪問到這個例項物件。
let bus = new Vue()
Vue.prototype.bus = bus
//定義了元件 person,當點選修改按鈕的時候通過 this.bus.$emit 傳送一個名為 modify 的事件,並將元件內輸入的 name 和 age 作為引數傳遞。
Vue.component('person', {
template: '<div><div>姓名:<input type="text" v-model="name"/></div><div>年齡:<input type="text" v-model="count"/></div><button @click="modify">修改</button></div>',
data() {
return {
name: '句號',
count: 18
}
},
methods: {
modify() {
this.bus.$emit('modify', {name: this.name, count: this.count})
}
}
})
//定義元件 detail,在元件內部通過 this.bus.$on 監聽名為 modify 的事件,當事件觸發時執行修改操作。
Vue.component('detail', {
template: '<div>我是:{{name}}, 我今年 {{count}}歲。</div>',
data() {
return {
name: '句號',
count: 18
}
},
mounted() {
this.bus.$on('modify', (detail) => {
this.name = detail.name
this.count = detail.count
})
}
})
var vm = new Vue({
el: '#app',
methods: {
}
})
</script>
</html>