詳解vue組件之間的通信
說明:下面我總結了比較常用的vue組件之前通信的方式,最近準備面試,所以有些總結貼上來分享
props和$emit
只有父子關系才可以用這種方式,父組件向子組件傳遞參數(shù)用props,子向父傳遞使用觸發(fā)$emit自定義事件
1.props
<!-- parent.vue, 可以傳遞`靜態(tài)`的props和`動態(tài)`的props, 靜態(tài)的參數(shù)只能是個String類型的,如果是其他類型的一定要記得加`:`來表示這是一個 js 表達式而不是一個字符串 --> <Child :name="name" :age="18" address="xxxxx"></Child> ... data () { return { name: 'marry' } } <!-- 傳一個參數(shù)所有props, 雖然目前我沒有這個需求,使用不帶參數(shù)的 v-bind --> <blog-post v-bind="post"></blog-post> post: { id: 1, title: 'My Journey with Vue' } //等價于下面 <blog-post v-bind:id="post.id" v-bind:title="post.title" ></blog-post> <!-- child.vue --> ... //以字符串數(shù)組形式列出的 prop props: ['name', 'age', 'address'] //prop驗證, 當 prop 驗證失敗的時候,(開發(fā)環(huán)境構建版本的) Vue 將會產生一個控制臺的警告 //注意:以下類型不能寫成'String'這種帶引號的形式 props: { // 基礎的類型檢查 (`null` 和 `undefined` 會通過任何類型驗證) propA: Number, // 多個可能的類型 propB: [String, Number], // 必填的字符串 propC: { type: String, required: true }, // 帶有默認值的數(shù)字 propD: { type: Number, default: 100 }, // 帶有默認值的對象 propE: { type: Object, // 對象或數(shù)組默認值必須從一個工廠函數(shù)獲取 default: function () { return { message: 'hello' } } }, // 自定義驗證函數(shù) propF: { validator: function (value) { // 這個值必須匹配下列字符串中的一個 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } //注意那些 prop 會在一個組件實例創(chuàng)建之前進行驗證,所以實例的 property (如 data、computed 等) 在 default 或 validator 函數(shù)中是不可用的。
2.$emit
<!-- parent.vue --> <Child @my-event="myEvent"></Child> ... methods: { myEvent(name){ this.name = name } } <!-- child.vue --> <div> <button @click="$emit('my-event', name)"></button> </div> //使用自定義事件將子組件的值拋給父組件
中央事件總線 bus
用于解決跨級和兄弟組件通信問題,巧妙的使用一個公共的vue實例,利用$on, $emit, $off(移除自定義事件監(jiān)聽器)
方法一:
可以在main.js中,在Vue的原型上掛載一個公共的Vue實例 $bus,這樣全局任何一個地方都可以使用
Vue.prototype.$bus = new Vue()
然后在需要的地方注冊自定義事件和接收參數(shù)的回調函數(shù)
this.$bus.$on('changeName', name => { this.name = name })
在需要改變的時候觸發(fā)事件并拋出參數(shù)
this.$bus.$emit('changeName', 'wzj')
方法二:
定義一個util.js文件
import Vue from 'vue' const bus = new Vue() export default bus
在需要用到bus的文件中引入
import bus from '../util' //文件路徑不一定 //在一個文件定義事件 bus.$on('changeName', name => { this.name = name }) //另一個文件拋出參數(shù) bus.$emit('changeName', 'wzj')
vuex
對于項目比較復雜,多組件共享狀態(tài),不同層級需要通信
核心概念:
state, getter, mutation, action, module
//store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export dafault new Vuex.Store({ state: { name: '', age: 0 }, getters: { tranName(state){ return 'name: ' + state.name } }, mutations: { changeName(state, name){ state.name = name } }, /*Action 函數(shù)接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調用 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters */ actions: { //異步函數(shù),但還是要通過提交commit觸發(fā)mutations函數(shù)操作state changeName(context, name){ context.commit('changeName', name) } }, modules: {} })
在組件中使用
方法一:
//訪問state屬性 this.$store.state.name //訪問getters屬性 this.$store.getters.tranName //訪問mutations this.$store.commit('changeName', 'wzj') //訪問actions this.$store.dispatch('changeName', 'wzj')
方法二:使用輔助函數(shù)映射到本地,這里只列舉了簡便的方式,更多查閱官網(wǎng)吧
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex' //state 和 getters 映射到本地的computed屬性中,作為計算屬性使用 computed: { ...mapState(['name', 'age']), ...mapGetters(['tranName']) } //mutations 和 actions methods: { // 將 `this.changeName()` 映射為 `this.$store.commit('changeName')` ...mapMutations(['changeName']) // 將 `this.changeName()` 映射為 `this.$store.dispatch('changeName')` ...mapActions(['changeName']) }
$attrs 和 $listeners
父組件與后代組件,用以上方法有點大材小用或者第一種有些不方便
- $attrs 包含了父作用域中不作為 prop 被識別 (且獲取) 的 attribute 綁定 ( class 和 style 除外)。當一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 ( class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內部組件。
- $listeners 包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。它可以通過 v-on="$listeners" 傳入內部組件——在創(chuàng)建更高層次的組件時非常有用。
例子:
//app.vue <div> <One name="wzj" :age="age" address="xian" @changeAge="changeAge"></One> </div> ... data(){ return { age: 10 } }, methods: { changeAge(age){ this.age = age } } //one.vue <div> <div>姓名:{{ name }}</div> <div>年齡:{{ age }}</div> <Two v-bind="$attrs" v-on="$listeners"></Two> <button @click="change">點我2</button> </div> ... props: ['name', 'age'], //two.vue <div> <div>{{ address }}</div> <button @click="change">點我2</button> </div> ... props: ['address'], //用$attrs傳遞到最后的屬性,在使用的時候還是要聲明props methods: { change(){ this.$emit('changeAge', 30) } }
理解:其實祖先組件的屬性和事件還是一層層往下傳,不過用$attrs 和 $listeners優(yōu)化和簡便了傳遞過程中書寫,而且在傳遞的過程中,任何一個聲明了 $listeners的組件都可以觸發(fā)里面的所有事件,而聲明了$attrs的組件只能使用之前未用props聲明的剩下的屬性。
以上就是vue組件之間的通信的詳細內容,更多關于vue 組件通信的資料請關注腳本之家其它相關文章!
相關文章
Vue.js:使用Vue-Router 2實現(xiàn)路由功能介紹
本篇文章主要介紹了Vue.js:使用Vue-Router 2實現(xiàn)路由功能介紹,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02vue el-tree 默認展開第一個節(jié)點的實現(xiàn)代碼
這篇文章主要介紹了vue el-tree 默認展開第一個節(jié)點的實現(xiàn)代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05Element UI 上傳組件實現(xiàn)文件上傳并附帶額外參數(shù)功能
在使用 ElementUI 的上傳組件 el-upload 實現(xiàn)文件上傳功能時,如果單文件上傳是比較簡單的,但是在實際需求中,往往會在上傳文件時伴隨著一些其他參數(shù),怎么操作呢,下面通過示例代碼講解感興趣的朋友一起看看吧2023-08-08