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>
目录
相关文章
|
8月前
|
JavaScript 前端开发 算法
Vue 3 和 Vue 2 的区别及优点
Vue 3 和 Vue 2 的区别及优点
|
7月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
1751 0
|
9月前
|
JavaScript 前端开发 UED
vue2和vue3的响应式原理有何不同?
大家好,我是V哥。本文详细对比了Vue 2与Vue 3的响应式原理:Vue 2基于`Object.defineProperty()`,适合小型项目但存在性能瓶颈;Vue 3采用`Proxy`,大幅优化初始化、更新性能及内存占用,更高效稳定。此外,我建议前端开发者关注鸿蒙趋势,2025年将是国产化替代关键期,推荐《鸿蒙 HarmonyOS 开发之路》卷1助你入行。老项目用Vue 2?不妨升级到Vue 3,提升用户体验!关注V哥爱编程,全栈开发轻松上手。
588 2
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
549 60
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
310 58
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
253 56
|
9月前
|
JavaScript 前端开发 API
管理数据必备;侦听器watch用法详解,vue2与vue3中watch的变化与差异
一篇文章同时搞定Vue2和Vue3的侦听器,是不是很棒?不要忘了Vue3中多了一个可选项watchEffect噢。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
JavaScript 测试技术 容器
Vue2+VueRouter2+webpack 构建项目
1). 安装Node环境和npm包管理工具 检测版本 node -v npm -v 图1.png 2). 安装vue-cli(vue脚手架) npm install -g vue-cli --registry=https://registry.
1233 0
|
3月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
311 2
|
2月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
288 137