• Vue状态管理之Bus


    一般在项目中,状态管理都是使用Vue官方提供的Vuex

    当在多组件之间共享状态变得复杂时,使用Vuex,此外也可以使用Bus来进行简单的状态管理

    1.1 父组件与子组件之间的通信

    vue.config.js文件内容

    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文件内容

    <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的值

    store.vue文件中,a-input标签使用v-model进行双向绑定,v-model是一个语法糖

    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标签上显示出来,这样就实现了不同组件之间的通信。

  • 相关阅读:
    redis基本数据结构-集合set
    redis基本数据结构-列表
    redis基本数据结构-散列
    redis基本数据结构-字符串
    redis基础
    关于HTTP调用WCF传递DataTable参数的处理
    解决WCF跨域问题,及DataTable参数问题
    让WCF支持Http调用
    分页方法,始终只生成指定数量的页码
    CVE-2021-1675漏洞复现
  • 原文地址:https://www.cnblogs.com/renpingsheng/p/11210223.html
Copyright © 2020-2023  润新知