前言
原型有個東西,看著是幾個功能元件的組合體;
想拆分成對應的元件(全部寫在一起是賊恐怖的事情),又不想用Vuex
這類來實現。
那最終的方案就是Vue
的eventbus
了
效果圖
只展示部分功能,實際原型要複雜的多;
原型大體是這樣的
實現原理
其實就是各個元件獨立維護自己的狀態,元件的預設值從外部傳入;
而內部通過watch
在immediate
立即觸發複製一份到data
,
再watch data
回撥$emit
,而對於聚攏所有資料,我們就用event bus
來實現;
如何區域性狀態化,就用到了inject provide
了,在當前元件下provide
,該分支的所有子元件都能inject
;
ng
有這個概念,react
的context
也是差不多的玩意
程式碼參考
依舊如前兩篇文章,基於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>
複製程式碼
總結
到這裡,我們結合Vue
提供的一些特性實現了,可能某些特性有些小夥伴用的少;
這裡有用到新的slot
語法,還有比較冷門的provide | inject
;
有不對之處請留言,會及時修正,謝謝閱讀