詳解vue元件之間的通訊
阿新 • • 發佈:2020-08-31
說明:下面我總結了比較常用的vue元件之前通訊的方式,最近準備面試,所以有些總結貼上來分享
props和$emit
只有父子關係才可以用這種方式,父元件向子元件傳遞引數用props,子向父傳遞使用觸發$emit自定義事件
1.props
<!-- parent.vue,可以傳遞`靜態`的props和`動態`的props,靜態的引數只能是個String型別的,如果是其他型別的一定要記得加`:`來表示這是一個 js 表示式而不是一個字串 --> <Child :name="name" :age="18" address="xxxxx"></Child> ... data () { return { name: 'marry' } } <!-- 傳一個引數所有props,雖然目前我沒有這個需求,使用不帶引數的 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 --> ... //以字串陣列形式列出的 prop props: ['name','age','address'] //prop驗證,當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制檯的警告 //注意:以下型別不能寫成'String'這種帶引號的形式 props: { // 基礎的型別檢查 (`null` 和 `undefined` 會通過任何型別驗證) propA: Number,// 多個可能的型別 propB: [String,Number],// 必填的字串 propC: { type: String,required: true },// 帶有預設值的數字 propD: { type: Number,default: 100 },// 帶有預設值的物件 propE: { type: Object,// 物件或陣列預設值必須從一個工廠函式獲取 default: function () { return { message: 'hello' } } },// 自定義驗證函式 propF: { validator: function (value) { // 這個值必須匹配下列字串中的一個 return ['success','warning','danger'].indexOf(value) !== -1 } } } //注意那些 prop 會在一個元件例項建立之前進行驗證,所以例項的 property (如 data、computed 等) 在 default 或 validator 函式中是不可用的。
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(移除自定義事件監聽器)
方法一:
可以在main.js中,在Vue的原型上掛載一個公共的Vue例項 $bus,這樣全域性任何一個地方都可以使用
Vue.prototype.$bus = new Vue()
然後在需要的地方註冊自定義事件和接收引數的回撥函式
this.$bus.$on('changeName',name => { this.name = name })
在需要改變的時候觸發事件並丟擲引數
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 }) //另一個檔案丟擲引數 bus.$emit('changeName','wzj')
vuex
對於專案比較複雜,多元件共享狀態,不同層級需要通訊
核心概念:
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 函式接受一個與 store 例項具有相同方法和屬性的 context 物件,因此你可以呼叫 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters */ actions: { //非同步函式,但還是要通過提交commit觸發mutations函式操作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')
方法二:使用輔助函式對映到本地,這裡只列舉了簡便的方式,更多查閱官網咖
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 事件監聽器。它可以通過 v-on="$listeners" 傳入內部元件——在建立更高層次的元件時非常有用。
例子:
//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優化和簡便了傳遞過程中書寫,而且在傳遞的過程中,任何一個聲明瞭 $listeners的元件都可以觸發裡面的所有事件,而聲明瞭$attrs的元件只能使用之前未用props宣告的剩下的屬性。
以上就是vue元件之間的通訊的詳細內容,更多關於vue 元件通訊的資料請關注我們其它相關文章!