組件 (Component) 是 Vue.js 最強大的功能之一。組件能夠擴展 HTML 元素,封裝可重用的代碼。javascript
Vue自定義組件分爲兩種:全局註冊和局部註冊,全局組件能夠在任何地方引用,局部組件只能在當前Vue實例使用。vue
全局註冊 放在經過new建立的Vue實例當中java
Vue.component('my-component', { template: '<p>我是被全局註冊的組件</p>' }) /* Vue.component(組件名稱[字符串], 組件對象) */ new Vue({ el: '#app', template: '<my-component></my-component>' })
局部註冊vuex
const child = { template: '<p>我是局部註冊的組件</p>' } /* 經過components選項屬性進行局部註冊: components: { 組件名稱[字符串]: 組件對象 } */ new Vue({ el: '#app', template: '<my-component></my-component>', components: { 'my-component': child } })
經過$emit(event)觸發一個自定義事件app
而後經過$on(event,callback) 去執行對應的callback(回調函數)ide
(兩個event是字符串,且必須名稱相同)函數
但$on不能在父組件中監聽子組件拋出的事件,因此咱們要作到這一點,能夠在父組件的模板中使用到子組件的時候,直接用v-on綁定 (和$on做用效果一致)ui
組件是 vue.js 最強大的功能之一,而組件實例的做用域是相互獨立的,這就意味着不一樣組件之間的數據沒法相互引用。通常來講,組件能夠有如下幾種關係:this
如上圖所示,A 和 B、B 和 C、B 和 D 都是父子關係,C 和 D 是兄弟關係,A 和 C 是隔代關係(可能隔多代)。spa
針對不一樣的使用場景,如何選擇行之有效的通訊方式?這是咱們所要探討的主題。本文總結了 vue 組件間通訊的幾種方式,如 props、$emit
/$on
、vuex、$parent
/ $children
、$attrs
/$listeners
和 provide/inject等
父組件 A 經過 props 的方式向子組件 B 傳遞,B to A 經過在 B 組件中 $emit, A 組件中 v-on 的方式實現。
父組件向子組件傳值
//App.vue父組件 <template> <div id="app"> <users v-bind: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>
子組件向父組件傳值
子組件經過 events 給父組件發送消息,實際上就是子組件把本身的數據發送到父組件。
<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>
這種方法經過一個空的 Vue 實例做爲中央事件總線(事件中心),用它來觸發事件和監聽事件,巧妙而輕量地實現了任何組件間的通訊,包括父子、兄弟、跨級。當咱們的項目比較大時,能夠選擇更好的狀態管理解決方案 vuex。
例子
<div id="app"> <v-about></v-about> <hr /> <v-more></v-more> </div> <template id="about"> <div> 我是about組件 <button @click="toMore">我要把about中的數據傳給more</button> </div> </template> <template id="more"> <div> 我是more組件 </div> </template> <script src="../vue.js"></script> <script> //about------>more const eventBus = new Vue(); //中央事件總線 const More = { template: `#more`, data() { return { msg: '我是用來接收從about傳過來的數據' }; }, mounted() { eventBus.$on('FormAboutToMore', function(data) { this.msg = data; console.log(this.msg); }); } }; const About = { template: `#about`, data() { return { msg: '我是about中的數據' }; }, methods: { toMore() { eventBus.$emit('FormAboutToMore', this.msg); } } }; const app = new Vue({ el: '#app', data() { return { msg: '我是根組件的數據' }; }, methods: {}, components: { 'v-about': About, 'v-more': More } }); </script>