Vue狀態管理之Bus

通常在項目中,狀態管理都是使用Vue官方提供的Vuexjavascript

當在多組件之間共享狀態變得複雜時,使用Vuex,此外也能夠使用Bus來進行簡單的狀態管理html

1.1 父組件與子組件之間的通訊

vue.config.js文件內容vue

const path = require('path')
const resolve = dir => path.join(__dirname,dir)
const BASE_URL = process.env.NODE_ENV === 'production' ? '/iview-admin':'/'

module.exports = {
    lintOnSave: false,
    baseUrl: BASE_URL,
    chainWebpack:config =>{
        config.resolve.alias
        .set('@',resolve('src'))    // 用 @ 符號來替代 src 這個路徑
        .set('_c',resolve('src/components'))        // 用 _c 來替代 src/components這個目錄
    },
    productionSourceMap:false,       // 打包時不生成 .map文件,減小打包的體積同時加快打包速度
    devServer:{         // 跨域配置,告訴開發服務器將任何沒有匹配到靜態文件的請求都代理到proxy指定的URL
        proxy:'http://localhost:8000'
    }
}

src/components/AInput.vue文件內容java

<template>
    <input @input="handleInput" :value="value">
</template>
<script>
export default {
    name:"AInput",
    props:{
        value:{
            type:[String,Number],
            default:''
        }
    },
    methods:{
        handleInput (event){
            const value = event.target.value
            this.$emit('input',value)
        }
    }
}
</script>

src/views/store.vue文件內容跨域

<template>
    <div>
        <a-input v-model="inputValue"></a-input>
        <p>{{inputValue}}</p>
    </div>
</template>

<script>
import AInput from '_c/AInput.vue'      // 引入 AInput組件

export default {
    name:'store',
    data () {
        return {
            inputValue:''
        }
    },
    components:{
        AInput      // 註冊AInput組件,而後就能夠使用 AInput組件了
    }
}
</script>

src/router/router.vue文件內容瀏覽器

import Home from '@/views/Home.vue'

export default [
    ...     // 此處省略
    {
        path:'/store',
        component:() => import('@/views/store.vue')
    }
]

瀏覽器打開URL:http://localhost:8080/#/store,顯示效果以下服務器

首先在AInput.vue文件中,爲input標籤綁定handleInput事件當input框中的數據改變時就會觸發handleInput事件,input標籤中顯示的數據就是value的值app

store.vue文件中,a-input標籤使用v-model進行雙向綁定,v-model是一個語法糖iview

v-model的效果等同於以下 src/views/store.vue文件內容工具

<template>
    <div>
        <a-input :value="inputValue" @input="handleInput"></a-input>
        <p>{{inputValue}}</p>
    </div>
</template>

<script>
import AInput from '_c/AInput.vue'

export default {
    name:'store',
    data () {
        return {
            inputValue:''
        }
    },
    components:{
        AInput
    },
    methods:{
        handleInput(val){
            this.inputValue = val
        }
    }
}
</script>

相比於上面的代碼方式,v-model方便不少

vue中,單向數據流通訊:

父組件向子組件傳值必定是經過屬性,子組件想修改父組件傳遞的值時,必定要經過事件,把要修改的值以參數的形式經過事件提交給父組件,而後在父組件中綁定事件接收消息知道子組件要修改父組件中的數據,最後就能夠在子組件中修改數據了,這就是父子組件之間的通訊

1.2 單頁面中多組件(兄弟組件)中的通訊

src/components目錄下新建AShow.vue文件 src/components/AShow.vue文件內容

<template>
    <div>
        <p>AShow: {{ content }}</p>
    </div>
</template>
<script>
export default {
    props: {
        content: {
            type: [String, Number],
            default: ''     // content的值默認爲空
        }
    }
}
</script>

修改src/components/store.vue文件內容

<template>
    <div>
        <a-input @input="handleInput"></a-input>
        <a-show :content="inputValue"></a-show>
    </div>
</template>
<script>
import AInput from '_c/AInput.vue'      // 引入 AInput組件
import AShow from '_c/AShow.vue'      // 引入 AShow組件

export default {
    name:'store',
    data () {
        return {
            inputValue:''
        }
    },
    components:{
        AInput,      // 註冊AInput組件,而後就能夠使用 AInput組件了
        AShow       // 註冊AShow組件
    },
    methods: {
        handleInput(val){
            this.inputValue = val
        }
    }
}
</script>

瀏覽器打開URL: http://localhost:8080/#/store,顯示效果以下

能夠看到,在父組件store中給子組件AInput綁定事件handleInput,handleInput觸發以後,把AInput組件中輸入的數據賦值給this.inputValue

最後再把this.inputValue的值傳遞給AShow組件的content屬性,以達到單頁面下多組件傳值的目的。

1.3 使用Bus進行多組件的通訊

src/lib目錄下新建'bus.js'文件 src/lib/bus.js文件內容

import Vue from 'vue'
const Bus = new Vue()
export default Bus

src/main.js文件中引入bus.js文件 src/main.js文件內容

import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
import store from './store/index'
import Bus from '@/lib/bus'     // 引入Bus組件

Vue.config.productionTip = false
Vue.prototype.$bus = Bus    // 註冊到vue的根實例裏,給vue原生對象上添加bus屬性

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

src/views/view1.vue文件內容

<template>
    <div class="div2">
        <button @click="handleClick" name="button">按鈕一</button>
    </div>
</template>
<script>
    export default {
        methods: {
            handleClick() {
                this.$bus.$emit('changeValue', 'hello')  // 把on-click事件提交給 bus
            }
        },
        mounted () {
            console.log(this.$bus)      // 打印出 this.$bus對象
        }
    }
</script>
<style>
    .div2 {
        border: 1px solid green;
    }
</style>

src/views/view2.vue文件內容

<template>
    <div class="div1">
        <p>{{ message }}</p>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                message: ''
            }
        },
        mounted() {
            this.$bus.$on('changeValue', msg => {
                this.message = msg
            })  // 監聽bus的 on-click 事件
        }
    }
</script>
<style>
    .div1 {
        border:1px solid red;
    }
</style>

src/router/router.js文件內容

import Home from '@/views/Home.vue'

export default [
    {
        path:'/named_view',
        components:{
            default: () => import('@/views/child.vue'),
            view1: () => import('@/views/view1.vue'),
            view2: () => import('@/views/view2.vue'),
        }
    }
    ...
]

瀏覽器打開URL: http://localhost:8080/#/named_view,在瀏覽器的調試工具中能夠看到打印的this.$bus對象

頁面渲染結果爲

點擊頁面上的'按鈕一',效果以下

在上面的例子裏,按鈕一全部的綠色框所在就是view1組件,紅色框所在就是view2組件

view1.vue組件中,$emit方法會在當前組件view1上把changeValue事件changeValue是綁定在this.$bus這個vue實例上,而後獲取changeValue事件的返回值'hello'

而後在view2組件中,在this.$bus這個實例上監聽changeValue事件,獲得changeValue事件的返回值'hello',而後把返回值賦值給 message,並在p標籤上顯示出來,這樣就實現了不一樣組件之間的通訊。

原文出處:https://www.cnblogs.com/renpingsheng/p/11210223.html

相關文章
相關標籤/搜索