zoukankan      html  css  js  c++  java
  • vue跨组件通信的几种方法

    http://www.tuicool.com/articles/jyM32mA

    在开发组件的时候,一定会遇到组件的通信,比如点击一个图标出现弹窗和蒙层,这三个分别是不同的组件。管理他们之间的状态就成了问题。

    props双向绑定

    官方文档在这 ,通过 sync 双向绑定,属性变化会同步到所有组件,这也是最简单的实现方式,缺点是属性会比较多。实现方式如下

    App.vue 文件

    <template>
      <div id="app">
        <mask :hide-mask.sync="hideMask"></mask>
        <dialog :hide-dialog.sync="hideDialog" :hide-mask.sync="hideMask"></dialog>
        <dialog-icon :hide-dialog.sync="hideDialog" :hide-mask.sync="hideMask"></dialog-icon>
      </div>
    </template>
    
    <script>
    import mask from './components/mask/index'
    import dialog from './components/dialog/index'
    import dialogIcon from './components/dialog-icon/index'
    
    export default {
      components: {
        mask,
        dialog,
        dialogIcon
      },
      data () {
        return {
          hideMask: true,
          hideDialog: true
        }
      }
    }
    </script>

    component/dialog/index.vue 文件

    <template>
      <section class="dialog" :class="{ 'hide': hideDialog }">
        <div class="dialog-close" @click="hide()"></div>
      </section>
    </template>
    
    <script>
    export default {
      props: ['hideDialog', 'hideMask'],
      methods: {
        hide () {
          this.hideDialog = !this.hideDialog
          this.hideMask = !this.hideMask
        }
      }
    }
    </script>

    component/dialog-icon/index.vue 文件

    <template>
      <section class="dialog-icon" @click="show()">点击出现弹窗</section>
    </template>
    
    <script>
    export default {
      props: ['hideDialog', 'hideMask'],
      methods: {
        show () {
          this.hideDialog = !this.hideDialog
          this.hideMask = !this.hideMask
        }
      }
    }
    </script>

    component/mask/index.vue 文件

    <template>
      <div class="mask" :class="{ 'hide': hideMask }"></div>
    </template>
    
    <script>
    export default {
      props: ['hideMask']
    }
    </script>

    自定义事件

    官方文档在这 ,子组件 $dispatch() 派发事件传递给父组件,父组件 $broadcast() 广播事件传递给子组件,这种方式虽然减少了props的使用,但是需要额外定义几个事件,状态多了就会变得很复杂,实现方法如下

    App.vue 文件

    <template>
      <div id="app">
        <mask></mask>
        <dialog></dialog>
        <dialog-icon></dialog-icon>
    </template>
    
    <script>
    import mask from './components/mask/index'
    import dialog from './components/dialog/index'
    import dialogIcon from './components/dialog-icon/index'
    
    export default {
      components: {
        mask,
        dialog,
        dialogIcon
      },
      data () {
        return {
          hideMask: true,
          hideDialog: true
        }
      },
      events: {
        'dialog-dispatch' () {
          this.hidedialog = !this.hidedialog
          this.$broadcast('dialog-broadcast')
        },
        'mask-dispatch' () {
          this.hideMask = !this.hideMask
          this.$broadcast('mask-broadcast')
        }
      }
    }
    </script>

    component/dialog-icon/index.vue 文件

    <template>
      <section class="dialog-icon" @click="show()">点击出现弹窗</section>
    </template>
    
    <script>
    export default {
      methods: {
        show () {
          this.$dispatch('dialog-dispatch')
          this.$dispatch('mask-dispatch')
        }
      },
      events: {
        'dialog-broadcast' () {
          this.hideDialog = !this.hideDialog
        }
      },
      data () {
        return {
          hideDialog: this.$parent.hideDialog,
          hideMask: this.$parent.hideMask
        }
      }
    }
    </script>

    component/dialog/index.vue 文件

    <template>
      <section class="dialog" :class="{ 'hide': hideDialog }">
        <div class="dialog-close" @click="hide()"></div>
      </section>
    </template>
    
    <script>
    export default {
      methods: {
        hide () {
          this.$dispatch('dialog-dispatch')
          this.$dispatch('mask-dispatch')
        }
      },
      events: {
        'dialog-broadcast' () {
          this.hideDialog = !this.hideDialog
        }
      },
      data () {
        return {
          hideDialog: this.$parent.hideDialog,
          hideMask: this.$parent.hideMask
        }
      }
    }
    </script>

    component/mask/index.vue 文件

    <template>
      <div class="mask" :class="{ 'hide': hideMask }"></div>
    </template>
    
    <script>
    export default {
      data () {
        return {
          hideMask: this.$parent.hideMask
        }
      },
      events: {
        'mask-broadcast' () {
          this.hideMask = !this.hideMask
        }
      }
    }
    </script>

    Vuex

    官方文档在这里 ,状态统一放store管理,修改状态通过mutations,组件通过action调用mutations,虽然有点绕,但是所有东西放一起后期会更好维护,实现方法如下

    App.vue 文件

    <template>
      <div id="app">
        <mask></mask>
        <dialog></dialog>
        <dialog-icon></dialog-icon>
      </div>
    </template>
    
    <script>
    import mask from './components/mask/index'
    import dialog from './components/dialog/index'
    import dialogIcon from './components/dialog-icon/index'
    
    export default {
      components: {
        mask,
        dialog,
        dialogIcon
      }
    }
    </script>

    component/dialog/index.vue 文件

    <template>
      <section class="storehouse dialog" :class="{ 'hide': isHideDialog }">
        <div class="dialog-close" @click="hideDialog()"></div>
      </section>
    </template>
    
    <script>
    import { hideDialog } from '../../vuex/actions'
    
    export default {
      vuex: {
        state: {
          isHideDialog: state => state.isHideDialog
        },
        actions: {
          hideDialog
        }
      }
    }
    </script>

    component/dialog-icon/index.vue 文件

    <template>
      <section class="storehouse-icon" @click="hideDialog()">点击出现弹窗</section>
    </template>
    
    <script>
    import { hideDialog } from '../../vuex/actions'
    
    export default {
      vuex: {
        actions: {
          hideDialog
        }
      }
    }
    </script>

    component/mask/index.vue 文件

    <template>
      <div class="mask" :class="{ 'hide': isHideMask }"></div>
    </template>
    
    <script>
    export default {
      vuex: {
        state: {
          isHideMask: state => state.isHideMask
        }
      }
    }
    </script>

    vuex/store.js 文件

    import Vue from 'vue'
    import Vuex from 'vuex'
    import mutations from './mutations'
    
    Vue.use(Vuex)
    
    const state = {
      isHideMask: true,
      isHideDialog: true
    }
    
    const store = new Vuex.Store({
      state,
      mutations
    })
    
    if (module.hot) {
      module.hot.accept(['./mutations'], () => {
        const mutations = require('./mutations').default
        store.hotUpdate({
          mutations
        })
      })
    }
    
    export default store

    vuex/mutations.js 文件

    import {
      HIDEDIALOG
    }
    from './mutation-types'
    
    export
    default {
      [HIDEDIALOG] (state) {
        state.isHideDialog = !state.isHideDialog
        state.isHideMask = !state.isHideMask
      }
    }

    vuex/mutations-types.js 文件

    export const HIDEDIALOG = 'HIDEDIALOG'

    vuex/action.js 文件

    import { HIDEDIALOG } from './mutation-types'
    
    export const hideDialog = ({ dispatch }) => dispatch(HIDEDIALOG)
  • 相关阅读:
    什么是JDBC的最佳实践?
    如何将jquery对象转换为js对象?
    JQuery有几种选择器?
    jQuery 库中的 $() 是什么
    JS 中 == 和 === 区别是什么?
    有两张表;请用SQL查询,所有的客户订单日期最新的前五条订单记录?
    根据你以往的经验简单叙述一下MYSQL的优化?
    数据库MySQL分页时用的语句?
    LeetCode231-2的幂(水题,考察是否粗心)
    LeetCode191-位1的个数(题目有问题)
  • 原文地址:https://www.cnblogs.com/zzcit/p/6053313.html
Copyright © 2011-2022 走看看