下图是初版,火山图的代码。可以看出,里面的变量,逻辑,函数存在冗余,基本上都是改了参数,同样的get和set,去刷新图表;对于往后继续开发十几二十个图表,会很麻烦。因此需要将这一些基本配置:字体,颜色,样式,大小,下拉色卡 / Vuex的相关参数,方法进行代码封装。
- 封装
fontSetting
组件,将图表标题,x轴标题,y轴标题,x轴标签,y轴标签的自定义配置,进行统一管理
vue
<!--父组件使用fontSetting-->
<!--
传入参数:
chart-type:用于判断图表类型,如果是饼图是没有x,y轴的相关参数的
settings:echarts的一些配置信息,具体来说就是一个对象里面,包含了之前的所有"fontSize, fontFamily ... ..."
-->
<font-settings :chart-type="'GeenLen'" :settings="geenLenOptions.settings" />
<!--子组件,fontSetting.vue-->
<div class="itemList">
<div class="item" v-for="(item, index) in fontSettings" :key="index">
<div class="font-title">{{ item.label }}</div>
<div class="font-controls">
<div class="control-item" v-if="item.textKey">
<span>文本:</span>
<el-input
v-model="settings[item.textKey]"
size="medium"
@input="value => handleFontChange(item.textKey, value)"
></el-input>
</div>
<div class="control-item">
<span>字体:</span>
<el-select
v-model="settings[item.familyKey]"
size="large"
@change="value => handleFontChange(item.familyKey, value)"
>
<el-option
v-for="font in fontFamilies"
:key="font.value"
:label="font.label"
:value="font.value"
></el-option>
</el-select>
</div>
<div class="control-item">
<span>大小:</span>
<el-input-number
v-model="settings[item.sizeKey]"
:min="8"
:max="72"
size="medium"
@change="value => handleFontChange(item.sizeKey, value)"
></el-input-number>
</div>
<div class="control-item">
<span>颜色:</span>
<el-color-picker
v-model="settings[item.colorKey]"
size="medium"
@change="value => handleFontChange(item.colorKey, value)"
></el-color-picker>
</div>
<div class="control-item">
<span>样式:</span>
<el-switch
v-model="settings[item.styleKey]"
active-value="italic"
inactive-value="normal"
active-text="斜体"
@change="value => handleFontChange(item.styleKey, value)"
></el-switch>
</div>
</div>
</div>
</div>
js
//子组件的相关参数和方法
//接收父组件的传值
props: {
settings: {
type: Object,
required: true
},
chartType: {
type: String,
required: true
}
},
//自定义参数配置
data() {
return {
fontSettings: [
{
label: '图表标题',
textKey: 'title',
familyKey: 'titleFontFamily',
sizeKey: 'titleFontSize',
colorKey: 'titleFontColor',
styleKey: 'titleFontStyle'
},
{
label: 'X轴标题',
textKey: 'xAxisTitle',
familyKey: 'xAxisTitleFontFamily',
sizeKey: 'xAxisTitleFontSize',
colorKey: 'xAxisTitleFontColor',
styleKey: 'xAxisTitleFontStyle'
},
{
label: 'Y轴标题',
textKey: 'yAxisTitle',
familyKey: 'yAxisTitleFontFamily',
sizeKey: 'yAxisTitleFontSize',
colorKey: 'yAxisTitleFontColor',
styleKey: 'yAxisTitleFontStyle'
},
{
label: 'X轴标签字体',
familyKey: 'xAxisLabelFontFamily',
sizeKey: 'xAxisLabelFontSize',
colorKey: 'xAxisLabelFontColor',
styleKey: 'xAxisLabelFontStyle'
},
{
label: 'Y轴标签字体',
familyKey: 'yAxisLabelFontFamily',
sizeKey: 'yAxisLabelFontSize',
colorKey: 'yAxisLabelFontColor',
styleKey: 'yAxisLabelFontStyle'
}
],
fontFamilies: [
{ label: 'Arial', value: 'Arial' },
{ label: 'Times New Roman', value: 'Times New Roman' },
{ label: '微软雅黑', value: 'Microsoft YaHei' },
{ label: '宋体', value: 'SimSun' },
{ label: '黑体', value: 'SimHei' }
]
};
},
//判断哪些图表不需要x/y轴配置
mounted() {
if (this.chartType === 'GeenLen') {
this.fontSettings = this.fontSettings.filter(item => item.label == '图表标题');
}
},
methods: {
...mapActions('echartEncapsulation', ['updateStyle', 'setOptions', 'setSetting']),
handleFontChange(key, value) {
//change事件触发时,更新父组件的settings对象,并且将修改后的值更新到Vuex中
this.$emit('update:settings', {
...this.settings,
[key]: value
});
this.updateStyle({
target: 'readsRegion',
key,
value
});
}
}
js
//vuex
updateStyle({ commit }, { key, value }) {
commit('SET_STYLE', { key, value });
},
SET_STYLE(state, { key, value }) {
state.insertSizeOptions.settings[key] = value;
},
封装色卡组件
colorList
,实现在多个图表中,切换整体色系风格。色卡选择器的代码和上一篇博文是一致的,区别就是:传入chart-type
参数,用于触发不同的事件回调函数。
this.$emit(``change${this.chartType},
selectedColors.colors);
vue
<!--父组件使用colorList-->
<ColorList :chart-type="'GeenLen'" @changeGeenLen="handleColorChange"></ColorList>
js
<!--兄弟组件中,对于$emit触发的函数,进行处理-->
this.$bus.$on('updateColorGoBar', (colors) => {
this.colorList = colors
});
beforeDestroy() {
// 组件销毁前移除事件监听
this.$bus.$off('updateColorGoBar');
},
vue
<!--子组件colorList-->
<template>
<div class="color-template-select">
<el-select
v-model="selectedValue"
:placeholder="placeholder"
@change="handleTemplateChange"
:style="{ width: width }"
ref="selectRef"
>
<el-option
v-for="(template, index) in colorTemplates"
:key="index"
:label="template.name"
:value="template.name"
>
<div style="display: flex; gap: 5px">
<div
v-for="(color, colorIndex) in template.colors"
:key="colorIndex"
class="color-box"
:style="{
backgroundColor: color,
width: '20px',
height: '20px',
}"
></div>
</div>
</el-option>
</el-select>
</div>
</template>
<script>
export default {
name: 'ColorTemplateSelect',
props: {
width: {
type: String,
default: '250px'
},
placeholder: {
type: String,
default: ''
},
chartType: {
type: String,
default: ''
}
},
data() {
return {
selectedValue: '',
selectSVG: '',
colorTemplates: [],
},
],
};
},
mounted() {
const defaultColors = this.colorTemplates[0].colors;
// this.$emit('changeGoBar', defaultColors);
this.$emit(`change${this.chartType}`, defaultColors);
this.getSvgString(defaultColors);
},
methods: {
handleTemplateChange() {
const selectedColors = this.colorTemplates.find(
(template) => template.name === this.selectedValue
);
if (selectedColors) {
// console.log(this.chartType,"-----");
this.$emit(`change${this.chartType}`, selectedColors.colors);
// this.$emit('changeGoBar', selectedColors.colors);
this.selectedValue = "";
this.getSvgString(selectedColors.colors);
}
},
}
};
</script>
- 全局更新
js
this.$store.dispatch("echartEncapsulation/setSetting", {
target: "goBar",
settings: initialSettings,
});
setSetting({ commit }, { target, settings }) {
commit('SET_SETTINGS', { target, settings });
}
SET_SETTINGS(state, { target, settings }) {
state[`${target}Options`].settings = settings;
}
相当于此前,一个图表的配置,相关函数,重复逻辑可能会有上千行,如果存在十几二十个图表,对于后期维护极差,在封装后,基本能够减少80%的代码量,并且减少后续开发投入的精力