原型有个东西,看着是几个功能组件的组合体;javascript
想拆分红对应的组件(所有写在一块儿是贼恐怖的事情),又不想用Vuex
这类来实现。css
那最终的方案就是Vue
的eventbus
了, 这只是一种方案的实现。html
具体业务请具体分析是否能够用这个来维护多组件数据的通信!vue
只展现部分功能,实际原型要复杂的多;java
原型大致是这样的react
其实就是各个组件独立维护本身的状态,组件的默认值从外部传入;antd
而内部经过watch
在immediate
当即触发复制一份到data
,ide
再watch data
回调$emit
,而对于聚拢全部数据,咱们就用event bus
来实现;flex
如何局部状态化,就用到了inject provide
了,在当前组件下provide
,该分支的全部子组件都能inject
;ui
ng
有这个概念,react
的context
也是差很少的玩意
依旧如前两篇文章,基于antd design vue
来实现的,固然还有部分自定义组件是本身封装的
因此呢,看看用法就好,通常来讲大家跑步起来
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>
复制代码
到这里,咱们结合Vue
提供的一些特性实现了,可能某些特性有些小伙伴用的少;
这里有用到新的slot
语法,还有比较冷门的provide | inject
;
有不对之处请留言,会及时修正,谢谢阅读