前言碎语:近期做了股票走势图,对基本配置进行了分离(也是编写可维护js代码一书中所提倡的配置和逻辑分离)。这里给大家简要分享我的编程思维
tips:因为项目是用ts编写的,所以会出现ts代码,主要是用于类型检测
(this as any)[instance] = echarts.init(this.$refs[ref] as HTMLBaseElement); //创建实例
注1:instance,ref是变量需要外部传入,在最后createEchart函数中会出现,所以在这里先有个印象。
注2 this.$refs[ref] as HTMLBaseElement 把ref 作为HTMLBaseElement 类型,如果不懂HTMLBaseElement 是什么你也可以as为any 例如: this.$refs[ref] as any
在没有ts的Vue单页面中上面代码,写成如下形式
this[instance] = echarts.init(this.$refs[ref]); //创建实例
//把股票图的基本配置通过es6 import形式导入。
//注意:导入的变量全为大写,说明是常量(配置文件在下文)
import ECHARTSOPTIONSCONFIG from './config/echartConfig';
(this as any)[instance].setOption(ECHARTSOPTIONSCONFIG); //使用导入的基本配置
在没有ts的Vue单页面中上面代码,写成如下形式
this[instance].setOption(ECHARTSOPTIONSCONFIG); //使用导入的基本配置
配置文件,在这里我把该配置文件起名echartConfig 放于config文件夹中,用const声明 用export default导出
const ECHARTSOPTIONSCONFIG = {
tooltip: {
trigger: 'axis', //坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用
axisPointer: {//坐标轴指示器
type: 'cross'
},
borderWidth: 1,
borderColor: null,
backgroundColor: 'rgba(0, 0, 0, 0.75)',
padding: 12,
textStyle: { color: '#FFFFFF' },
transitionDuration:0,//防止页面抖动
confine:true,//防止页面抖动
formatter: function (param: any) {
return param
.map((item: any) => {
if (item.seriesIndex === 0) {//tooltip提示的内容
return `${item.name}
开盘: ${item.data[1]}
收盘: ${item.data[2]}
最低: ${item.data[3]}
最高: ${item.data[4]}
`;
}
// if (item.seriesIndex === 1) {
// return `
// 总量:${item.data[1]}
// `;
// }
})
.join('');
}
},
grid: [{//股票图gird
show: true,
borderWidth :1,
// borderColor:'#E3E6E9',
containLabel: true,
top: '1%',
left: '0',
width: '100%',
height: '60%',
},
{//柱形图grid
show:true,
containLabel: true,
top: '70%',
left: '0',
width: '100%',
height: '15%'
}],
axisPointer: {
link: { xAxisIndex: 'all' },
label: { backgroundColor: '#777' }
},
visualMap: {//分段型视觉映射组件
type: 'piecewise',
show: false,
seriesIndex: 1, //指定取哪个系列的数据
dimension: 2,
pieces: [{ value: 1,color: '#009933' },{ value: -1,color: '#ec0000' }]//对柱形图按照1和-1进行颜色划分,因此出现红色和绿色两种颜色柱形图
},
xAxis: [{//股票的x轴
type: 'category',
scale: true,
boundaryGap: false, //刻度和标签居中,不在band中间。
gridIndex: 0, //x 轴所在的 grid 的索引,默认位于第一个 grid
splitLine: {//x轴分割线
show: true,
lineStyle: {
color: ['#E3E6E9'] //分割线颜色
}
},
axisLine: {//x轴坐标线不显示
show: false,
},
axisTick: {
show: false //不显示X轴刻度
},
axisPointer: {
show:true,
z: 100
},
axisLabel: {
showMinLabel:false,//不显示最小刻度
},
},
{//柱形图x轴
type: 'category',
scale: true,
boundaryGap: false,
gridIndex: 1,
splitLine: {//x轴分割线
show: true,
lineStyle: {
color: ['#E3E6E9'] //分割线颜色
}
},
axisTick: {
show: false //不显示X轴刻度
},
axisLabel: {//x轴刻度标签
show: false
},
axisLine: {//x轴坐标线不显示
show: false,
}
}],
yAxis: [{//股票y轴
scale: true,
gridIndex: 0, //y 轴所在的 grid 的索引,默认位于第一个 grid
boundaryGap: false, //刻度和标签居中,不在band中间。
axisLine: { show:false },
axisLabel: {
margin: 0,
inside: true, //刻度标签朝内。
showMinLabel:false,//不显示最小刻度
verticalAlign:'top'
},
splitLine: {//y轴分割线
show: true,
lineStyle: {
color: ['#E3E6E9'] //分割线颜色
}
},
},
{//柱形图y轴
scale: true,
gridIndex: 1,
axisLabel: { show: false },
splitLine: {//x轴分割线
show: true
}
}],
dataZoom: [//区域缩放
{
type: 'inside', //内置
xAxisIndex: [0, 1]
},
{
type: 'slider', //外置
show: true,
xAxisIndex: [0, 1],
backgroundColor: 'rgba(255, 255, 255, 1)' //组件的背景颜色
}
],
series: [{
name: 'K',
type: 'candlestick',
xAxisIndex: 0,
yAxisIndex: 0,
large: true,
itemStyle: {
color: '#fff', //阳线图形的颜色
color0: '#009933', //阴线 图形的颜色#ec0000
borderColor: '#ec0000', //阳线图形的颜色
borderColor0: '#009933', //阴线 图形的颜色
borderWidth: 1,
opacity: 1
}
},
{
name: 'Volume',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
}]
};
export default ECHARTSOPTIONSCONFIG;
注:基本配置并没有牵涉到数据配置,只是外观或显示数据的配置
//X轴
(this as any)[instance].setOption({
xAxis: [{ data: arg[0].xAxis[0] }, { data: arg[0].xAxis[1] }]//按照数组中数据顺序,分别对股票和柱形图赋值数据
});
//数据
(this as any)[instance].setOption({
series: [{ data: arg[0].series[0] }, { data: arg[0].series[1] }]//按照数组中数据顺序,分别对股票和柱形图赋值数据
});
注:根据传入的arg变量对x轴和series进行数据设置,其中arg是传入的变量在后面createEchart函数出现,这里先有个印象
在没有ts的Vue单页面中上面代码,写成如下形式
//X轴
this[instance].setOption({
xAxis: [{ data: arg[0].xAxis[0] }, { data: arg[0].xAxis[1] }]//按照数组中数据顺序,分别对股票和柱形图赋值数据
});
//数据
this[instance].setOption({
series: [{ data: arg[0].series[0] }, { data: arg[0].series[1] }]//按照数组中数据顺序,分别对股票和柱形图赋值数据
});
stockInstance = undefined; //stock echarts 实例对象。用在createEchart函数中存储实例
/**
* @description createEchart 生成股票图的函数
* @param { string } instance 实例对象
* @param { string } ref 要挂载dom的ref
* @param { any } arg 数据
* @returns { void }
*/
createEchart(instance: string, ref: string, ...arg: any):void {
if (
(this as any)[instance] !== null &&
(this as any)[instance] !== '' &&
(this as any)[instance] !== undefined
) {
(this as any)[instance].dispose(); //销毁实例
}
(this as any)[instance] = echarts.init(this.$refs[ref] as HTMLBaseElement); //创建实例
(this as any)[instance].setOption(ECHARTSOPTIONSCONFIG); //基本配置
//X轴
(this as any)[instance].setOption({
xAxis: [{ data: arg[0].xAxis[0] }, { data: arg[0].xAxis[1] }]
});
//数据
(this as any)[instance].setOption({
series: [{ data: arg[0].series[0] }, { data: arg[0].series[1] }]
});
}
createEchart函数用来画股票图,其中 首先要对存放实例对象的变量instance 进行判断,是否有值。如果有值销毁echarts实例,重新生成,如果没有把生成的实例赋值给实例对象变量。(该判断用在切换股票图 重新渲染数据的情况下,例如下图)
在没有ts的Vue单页面中上面代码,写成如下形式
stockInstance = undefined; //stock echarts 实例对象。用在createEchart函数中存储实例
/**
* @description createEchart 生成股票图的函数
* @param { string } instance 实例对象
* @param { string } ref 要挂载dom的ref
* @param { any } arg 数据
* @returns { void }
*/
createEchart(instance, ref, ...arg){
if (
this[instance] !== null &&
this[instance] !== '' &&
this[instance] !== undefined
) {
this[instance].dispose(); //销毁实例
}
this[instance] = echarts.init(this.$refs[ref]); //创建实例
this[instance].setOption(ECHARTSOPTIONSCONFIG); //基本配置
//X轴
this[instance].setOption({
xAxis: [{ data: arg[0].xAxis[0] }, { data: arg[0].xAxis[1] }]
});
//数据
this[instance].setOption({
series: [{ data: arg[0].series[0] }, { data: arg[0].series[1] }]
});
}
在这里演示一下如何使用该函数,其中rawData 数据为演示数据不是真实数据
let rawData = [//示例数据
['2017/10/1', [2320.26, 2302.6, 2287.3, 2362.94]],
['2017/10/2', [2300, 2291.3, 2288.26, 2308.38]],
['2017/10/3', [2295.35, 2346.5, 2295.35, 2346.92]],
['2017/10/4', [2347.22, 2358.98, 2337.35, 2363.8]],
['2017/10/5', [2360.75, 2382.48, 2347.89, 2383.76]],
['2017/10/6', [2383.43, 2385.42, 2371.23, 2391.82]],
['2017/10/7', [2377.41, 2419.02, 2369.57, 2421.15]],
['2017/10/8', [2425.92, 2428.15, 2417.58, 2440.38]],
['2017/10/9', [2411, 2433.13, 2403.3, 2437.42]],
['2017/10/10', [2432.68, 2434.48, 2427.7, 2441.73]],
['2017/10/11', [2430.69, 2418.53, 2394.22, 2433.89]],
['2017/10/12', [2416.62, 2432.4, 2414.4, 2443.03]],
['2017/10/13', [2441.91, 2421.56, 2415.43, 2444.8]],
['2017/10/14', [2420.26, 2382.91, 2373.53, 2427.07]],
['2017/10/15', [2383.49, 2397.18, 2370.61, 2397.94]],
['2017/10/16', [2378.82, 2325.95, 2309.17, 2378.82]],
['2017/10/17', [2322.94, 2314.16, 2308.76, 2330.88]],
['2017/10/18', [2320.62, 2325.82, 2315.01, 2338.78]],
['2017/10/19', [2313.74, 2293.34, 2289.89, 2340.71]],
['2017/10/20', [2297.77, 2313.22, 2292.03, 2324.63]],
['2017/10/21', [2322.32, 2365.59, 2308.92, 2366.16]],
['2017/10/22', [2364.54, 2359.51, 2330.86, 2369.65]],
['2017/10/23', [2332.08, 2273.4, 2259.25, 2333.54]],
['2017/10/24', [2274.81, 2326.31, 2270.1, 2328.14]],
['2017/10/25', [2333.61, 2347.18, 2321.6, 2351.44]],
['2017/10/26', [2340.44, 2324.29, 2304.27, 2352.02]],
['2017/10/27', [2326.42, 2318.61, 2314.59, 2333.67]],
['2017/10/28', [2314.68, 2310.59, 2296.58, 2320.96]],
['2017/10/29', [2309.16, 2286.6, 2264.83, 2333.29]],
['2017/10/30', [2282.17, 2263.97, 2253.25, 2286.33]],
['2017/11/1', [2320.26, 2302.6, 2287.3, 2362.94]],
['2017/11/2', [2300, 2291.3, 2288.26, 2308.38]],
['2017/11/3', [2295.35, 2346.5, 2295.35, 2346.92]],
['2017/11/4', [2347.22, 2358.98, 2337.35, 2363.8]],
['2017/11/5', [2360.75, 2382.48, 2347.89, 2383.76]],
['2017/11/6', [2383.43, 2385.42, 2371.23, 2391.82]],
['2017/11/7', [2377.41, 2419.02, 2369.57, 2421.15]],
['2017/11/8', [2425.92, 2428.15, 2417.58, 2440.38]],
['2017/11/9', [2411, 2433.13, 2403.3, 2437.42]],
['2017/11/10', [2432.68, 2434.48, 2427.7, 2441.73]],
['2017/11/11', [2430.69, 2418.53, 2394.22, 2433.89]],
['2017/11/12', [2416.62, 2432.4, 2414.4, 2443.03]],
['2017/11/13', [2441.91, 2421.56, 2415.43, 2444.8]],
['2017/11/14', [2420.26, 2382.91, 2373.53, 2427.07]],
['2017/11/15', [2383.49, 2397.18, 2370.61, 2397.94]],
['2017/11/16', [2378.82, 2325.95, 2309.17, 2378.82]],
['2017/11/17', [2322.94, 2314.16, 2308.76, 2330.88]],
['2017/11/18', [2320.62, 2325.82, 2315.01, 2338.78]],
['2017/11/19', [2313.74, 2293.34, 2289.89, 2340.71]],
['2017/11/20', [2297.77, 2313.22, 2292.03, 2324.63]],
['2017/11/21', [2322.32, 2365.59, 2308.92, 2366.16]],
['2017/11/22', [2364.54, 2359.51, 2330.86, 2369.65]],
['2017/11/23', [2332.08, 2273.4, 2259.25, 2333.54]],
['2017/11/24', [2274.81, 2326.31, 2270.1, 2328.14]],
['2017/11/25', [2333.61, 2347.18, 2321.6, 2351.44]],
['2017/11/26', [2340.44, 2324.29, 2304.27, 2352.02]],
['2017/11/27', [2326.42, 2318.61, 2314.59, 2333.67]],
['2017/11/28', [2314.68, 2310.59, 2296.58, 2320.96]],
['2017/11/29', [2309.16, 2286.6, 2264.83, 2333.29]],
['2017/11/30', [2282.17, 2263.97, 2253.25, 2286.33]]
];
//createEchart函数第一个变量为声明的存储实例的变量(只不过是字符串形式),第二个变量为要把echarts图挂载到哪里的ref。
//最后的对象是用户渲染页面的数据,最终通过es6的解构赋值 以arg数组形式存在和访问
this.createEchart('stockInstance', 'stockEchart', {
xAxis: [
rawData.map(function (item) {
return item[0];
}),
rawData.map(function (item) {
return item[0];
})
],
series: [
rawData.map((item) => {
return item[1];
})
rawData.map((item, index) => {
return [index, item[1][3], item[1][0] > item[1][1] ? 1 : -1];
})
]
});
在编写createEchart函数时主要用到了一下几点
①:配置文件和逻辑分离
②:单一职责原则(一个对象/方法只做一件事):createEchart 函数只用来画股票图
③:没有分发对象,使用函数传参的形式,调用变量
不足:①:有些变量没有做类型检测
如果有什么问题,欢迎交流