Vue 2.x折腾记 - (18) 用Vue的Inject Provide结合Event Bus来实现局部的状态维护

简介: 原型有个东西,看着是几个功能组件的组合体;想拆分成对应的组件(全部写在一起是贼恐怖的事情),又不想用Vuex这类来实现。那最终的方案就是Vue的eventbus了, 这只是一种方案的实现。具体业务请具体分析是否可以用这个来维护多组件数据的


前言


原型有个东西,看着是几个功能组件的组合体;


想拆分成对应的组件(全部写在一起是贼恐怖的事情),又不想用Vuex这类来实现。


那最终的方案就是Vueeventbus了, 这只是一种方案的实现。


具体业务请具体分析是否可以用这个来维护多组件数据的通讯!


效果图


只展示部分功能,实际原型要复杂的多;



原型大体是这样的



实现原理


其实就是各个组件独立维护自己的状态,组件的默认值从外部传入;


而内部通过watchimmediate立即触发复制一份到data,

watch data回调$emit,而对于聚拢所有数据,我们就用event bus来实现;


如何局部状态化,就用到了inject provide了,在当前组件下provide,该分支的所有子组件都能inject;


ng有这个概念,reactcontext也是差不多的玩意


代码参考


依旧如前两篇文章,基于antd design vue来实现的,当然还有部分自定义组件是自己封装的


所以呢,看看用法就好,一般来说你们跑步起来


eventbus.js


import Vue from 'vue';
export const eventBus = new Vue();


BasicSetting.vue(父组件)


记得在组件生命周期销毁!!这是个好习惯!!!


<template>
  <a-card :bodyStyle="{ position: 'relative' }">
    <template #extra>
      <btn-popconfirm
        size="default"
        :text="isEdit ? '关闭编辑' : '开启编辑'"
        :message="`确定要${isEdit ? '关闭编辑' : '开启编辑'}续期配置?`"
        @change="onEdit"
      />
      <btn-popconfirm
        size="default"
        type="primary"
        text="确定配置"
        :disabled="!isEdit"
        :message="`确定要更新配置?操作需谨慎!`"
        @change="onUpdate"
      />
    </template>
    <div class="basic-setting">
      <a-col v-bind="{ xs: 24, sm: 24, md: 24, lg: 24, xxl: 6 }">
        <pivot-card :defaultValue="pivotData" :bordered="false" />
      </a-col>
      <a-col v-bind="{ xs: 24, sm: 24, md: 24, lg: 24, xxl: 18 }">
        <product-item />
      </a-col>
    </div>
    <div class="overlay" v-if="!isEdit" />
  </a-card>
</template>
<script>
import PivotCard from './PivotCard';
import ProductItem from './ProductItem';
import { eventBus } from '@/utils/eventBus';
export default {
  name: 'BasicSetting',
  provide: function() {
    return {
      bus: eventBus
    };
  },
  components: {
    PivotCard,
    ProductItem
  },
  created() {
    eventBus.$on('pivot', this.getPivotData);
    eventBus.$on('productItem', this.getProductItemData);
  },
  beforeDestroy() {
    eventBus.$off('pivot');
  },
  data() {
    return {
      isEdit: false, // 是否开启编辑
      pivotData: {
        // 基准信息
        minMoney: 200, // 最低金额
        maxMoney: 4000, // 最高金额
        defaultAmount: 2000 // 默认额度
      }
    };
  },
  methods: {
    onEdit(e) {
      // 开启关闭编辑
      if (e) {
        this.isEdit = !this.isEdit;
      }
    },
    onUpdate(e) {
      // 更新提交
    },
    getPivotData(e) {
      console.log('我是基准表单的值回调: ', JSON.stringify(e));
      // 获取基准信息的回调
    },
    getProductItemData(e) {
      console.log('我是产品项的值回调: ', JSON.stringify(e));
    }
  }
};
</script>
<style lang="scss" scoped>
.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(230, 229, 229, 0.24);
  z-index: 999;
}
</style>


PivotCard.vue子组件


<template>
  <a-card>
    <template #title>
      最低金额、最高金额、默认额度
    </template>
    <a-row type="flex" justify="start" align="middle" style="margin:10px 0;">
      <a-col :sm="24" :md="10">
        <span style="padding:5px 0">最低金额</span>
      </a-col>
      <a-col :sm="24" :md="14">
        <a-input-number
          :min="0"
          v-model="fields.minMoney"
          :formatter="value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
          :parser="value => value.replace(/\¥\s?|(,*)/g, '')"
        />
      </a-col>
    </a-row>
    <a-row type="flex" justify="start" align="middle" style="margin:10px 0;">
      <a-col :sm="24" :md="10"> <span style="padding:5px 0">最高金额</span></a-col>
      <a-col :sm="24" :md="14">
        <a-input-number
          :min="0"
          :formatter="value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
          :parser="value => value.replace(/\¥\s?|(,*)/g, '')"
          v-model="fields.maxMoney"
        />
      </a-col>
    </a-row>
    <a-row type="flex" justify="start" align="middle" style="margin:10px 0;">
      <a-col :sm="24" :md="10"> <span style="padding:5px 0">默认额度</span></a-col>
      <a-col :sm="24" :md="14">
        <a-input-number
          :min="0"
          :max="100"
          v-model="fields.defaultAmount"
          :formatter="value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
          :parser="value => value.replace(/\¥\s?|(,*)/g, '')"
        />
      </a-col>
    </a-row>
  </a-card>
</template>
<script>
export default {
  inject: ['bus'],
  data() {
    return {
      fields: {}
    };
  },
  props: {
    defaultValue: {
      // 默认值
      type: Object,
      default: function() {
        return {
          minMoney: 200,
          maxMoney: 4000,
          defaultAmount: 2000
        };
      }
    }
  },
  watch: {
    defaultValue: {
      // 把默认值初始化了
      immediate: true,
      deep: true,
      handler(newValue, oldValue) {
        if (newValue) {
          this.fields = newValue;
        }
      }
    },
    fields: {
      // 监听变动回调给父
      immediate: true,
      deep: true,
      handler(newValue, oldValue) {
        console.log('newValue, oldValue: ', newValue, oldValue);
        if (newValue) {
          this.bus.$emit('pivot', newValue);
        }
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.ant-input-number {
  min-width: 150px;
}
</style>
目录
相关文章
|
4天前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
41 1
|
2月前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
115 60
|
15天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
2月前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
33 1
|
2月前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
42 1
|
2月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
2月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
46 1
vue学习第一章
|
2月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
32 1
|
2月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
39 1
vue学习第四章
|
2月前
|
JavaScript 前端开发 算法
vue学习第7章(循环)
欢迎来到瑞雨溪的博客,一名热爱JavaScript和Vue的大一学生。本文介绍了Vue中的v-for指令,包括遍历数组和对象、使用key以及数组的响应式方法等内容,并附有综合练习实例。关注我,将持续更新更多优质文章!🎉🎉🎉
30 1
vue学习第7章(循环)

热门文章

最新文章