共计 7871 个字符,预计需要花费 20 分钟才能阅读完成。
原文地址:应用 Vue+DataV+Echarts 打造新冠肺炎疫情数据大屏 (可动静刷新)
源码
查看:https://blog.lanweihong.com/posts/29267/
效果图
演示
仅适配 1080P 屏幕,应用浏览器拜访后按 F11 进入全屏可看最佳显示成果。
- 疫情实在数据演示地址:演示地址 - 实在数据
- 模仿数据演示地址:演示地址 - 模仿数据
前端框架和类库
- Vue.js
- Apache ECharts
- DataV
- axios
- Element
- Mock
代码实现
创立我的项目
应用 Vue Cli 创立 Vue 我的项目,没有 Vue Cli 的应用以下命令装置:
npm install -g @vue/cli
创立我的项目:
vue create datav-covid-19
装置依赖
# 装置 DataV
npm install @jiaminghi/data-view
# 装置 echarts
npm install echarts -S
# 装置 element-ui
npm i element-ui -S
# 装置 vue-router
npm install vue-router
# 装置 mockjs
npm install mockjs --save-dev
# 装置 axios
npm install axios
# 装置 echarts-liquidfill
npm i echarts-liquidfill
引入注册
在我的项目中引入,编辑 main.js
:
import Vue from 'vue'
import App from './App.vue'
import dataV from '@jiaminghi/data-view'
import * as echarts from 'echarts'
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios'
// 引入 echarts 水球图
import 'echarts-liquidfill'
import VueRouter from 'vue-router'
import {Icon, Row, Col, Table, TableColumn, Button, Dialog, Link} from 'element-ui';
// 注册 echarts
Vue.prototype.$echarts = echarts
Vue.config.productionTip = false
// 注册 axios
Vue.prototype.axios = axios
// 注册 dataV
Vue.use(dataV)
// 注册路由
Vue.use(VueRouter)
// 按需注册其余 element-ui 组件
Vue.use(Icon)
Vue.use(Row)
Vue.use(Col)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(Button)
Vue.use(Dialog)
Vue.use(Link)
new Vue({render: h => h(App),
}).$mount('#app')
编写组件
因为篇幅无限,为了浏览体验,这里以 累计排名 组件为例,其余的组件请看 Github 上的代码。
累计排名组件
效果图
累计排名组件采纳 ECharts 的柱状图来显示,实现代码如下:
<template>
<div
ref="provinceRankingBarChart"
style="width: 100%; height: 100%"
/>
</template>
<script>
import * as echarts from 'echarts'
let chart = null
export default {
props: {
data: {
type: Object,
default () {
return {provinceList: [],
valueList: []}
}
}
},
methods: {initChart () {if (null != chart && undefined != chart) {chart.dispose()
}
chart = this.$echarts.init(this.$refs.provinceRankingBarChart)
this.setOptions()},
setOptions() {
var salvProValue = this.data.valueList;
var salvProMax = [];
for (let i = 0; i < salvProValue.length; i++) {salvProMax.push(salvProValue[0])
}
let option = {
grid: {
left: '2%',
right: '2%',
bottom: '2%',
top: '2%',
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {type: 'none'},
formatter: function (params) {return params[0].name + ':' + params[0].value
}
},
xAxis: {
show: false,
type: 'value'
},
yAxis: [{
type: 'category',
inverse: true,
axisLabel: {
show: true,
textStyle: {color: '#fff'},
},
splitLine: {show: false},
axisTick: {show: false},
axisLine: {show: false},
data: this.data.provinceList
}, {
type: 'category',
inverse: true,
axisTick: 'none',
axisLine: 'none',
show: true,
axisLabel: {
textStyle: {
color: '#ffffff',
fontSize: '12'
},
},
data: salvProValue
}],
series: [{
name: '值',
type: 'bar',
zlevel: 1,
itemStyle: {
normal: {
barBorderRadius: 30,
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [{
offset: 0,
color: 'rgb(2,163,254,1)'
}, {
offset: 1,
color: 'rgb(125,64,255,1)'
}]),
},
},
barWidth: 20,
data: salvProValue
},
{
name: '背景',
type: 'bar',
barWidth: 20,
barGap: '-100%',
data: salvProMax,
itemStyle: {
normal: {color: 'rgba(24,31,68,1)',
barBorderRadius: 30,
}
},
},
]
}
chart.setOption(option)
}
},
watch: {
data: {handler(newList, oldList) {if (oldList != newList) {this.setOptions()
}
},
deep: true
}
}
}
</script>
在页面中引入应用:
<template>
<div class="demo">
<province-ranking-bar-chart
ref="rankChart"
:data="dataList"
style="width: 100%; height: 380px"
/>
</div>
</template>
<script>
// 引入组件
import ProvinceRankingBarChart from '../components/ProvinceRankingBarChart'
export default {
components: {ProvinceRankingBarChart},
data () {
return {
// 定义数据
dataList: {provinceList: ['湖北', '台湾'],
valueList: [68188, 15379]
}
}
},
mounted() {
// 创立图表并初始化
this.$refs.rankChart.initChart()}
}
</script>
<style>
.demo {
width: 500px;
height: 600px;
}
</style>
其余组件的代码就不在这里写了,残缺代码已上传 Github,须要的能够去查看。
残缺的组件构造如下:
筹备模仿数据
我的项目中提供了两种数据提供形式,一是申请实在后盾地址,返回的数据格式参考 data
目录下的 json 文件;二是在本地应用 Mock 生成模仿数据。这里仅介绍应用 Mock 生成模仿数据形式。
应用 Mock 生成模仿数据
在我的项目根目录下创立文件夹 mock
,别离创立 covid19.js
和 index.js
;
编写 mock 服务
covid19.js
代码如下,代码中应用到一些 Mock 的语法,具体应用办法请查看 Mock 的文档。
// 从本地读取 json 数据
const provinceData = require('../data/covid19-province.json')
const dailyData = require('../data/covid19-daily-list.json')
// 引入 mockjs
const Mock = require('mockjs')
// 应用 mockjs 的 Random 生成随机数据
const Random = Mock.Random
module.exports = [
{
url: '/api/covid-19/overall',
type: 'get',
response: config => {
return {
success: true,
code: 200,
message: "操作胜利",
data: {confirmedCount: Random.integer(110000, 120000),
confirmedIncr: 72,
curedCount: Random.integer(100000, 110000),
curedIncr: 173,
currentConfirmedCount: Random.integer(3000, 4000),
currentConfirmedIncr: -110,
deadCount: Random.integer(4000, 6000),
deadIncr: 12,
importedCount: Random.integer(6000, 8000),
importedIncr: 23,
noInFectCount: Random.integer(400, 600),
noInFectIncr: 8,
suspectIncr: 0,
suspectCount: 2,
updateTime: "2021-07-15 20:39:11",
curedRate: Random.float(90, 95, 0, 9),
deadRate: Random.float(1, 5, 0, 9)
}
}
}
},
{
url: '/api/covid-19/area/latest/list',
type: 'get',
response: config => {return provinceData}
},
{
url: '/api/covid-19/list',
type: 'get',
response: config => {return dailyData}
}
]
注册 mock 服务
编辑 index.js
,这里次要是注册 mock 服务,调用办法 initMockData()
实现注册;
const Mock = require('mockjs')
// 引入写好的 mock 服务
const covid19 = require('./covid19')
const mocks = [...covid19]
function param2Obj(url) {const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {const index = v.indexOf('=')
if (index !== -1) {const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
const initMockData = () => {
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
if (this.responseType) {this.custom.xhr.responseType = this.responseType}
}
this.proxy_send(...arguments)
}
function XHR2ExpressReqWrap(respond) {return function(options) {
let result = null
if (respond instanceof Function) {const { body, type, url} = options
result = respond({
method: type,
body: JSON.parse(body),
query: param2Obj(url)
})
} else {result = respond}
return Mock.mock(result)
}
}
for (const i of mocks) {Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
}
}
module.exports = {
mocks,
initMockData
}
应用 mock 服务
在 main.js
中引入:
const {initMockData} = require('../mock')
// 实现注册
initMockData()
而后在页面中应用 request.get('/api/covid-19/list')
就能申请获取到数据,这里的 request.get()
是我用 axios
封装写的办法。
封装数据接口
封装 axios
我的项目中的数据申请都是应用 axios
为方便使用,我简略封装了一个工具类 request.js
:
import axios from "axios"
import sysConst from '../libs/const'
const fetch = (method = 'GET', url, param = '') => {
// 解决 url
url = `${sysConst.baseUrl}${url}`
return new Promise((resolve, reject) => {
axios({
method: method,
url: url,
changeOrigin: true,
data: JSON.stringify(param)
}).then((res) => {resolve(res.data)
}, error => {reject(error)
}).catch((error) => {reject(error)
})
})
}
const get = (url) => {return fetch('GET', url)
}
const post = (url, data) => {return fetch('POST', url, data)
}
const put = (url, data) => {return fetch('PUT', url, data)
}
const remove = (url, data) => {return fetch('DELETE', url, data)
}
export {
get,
post,
put,
remove
}
这里引入的 const.js
代码如下:
let baseUrl = ''if (process.env.NODE_ENV ==='development') {
// 批改你的 API 地址
baseUrl = ''
} else {
// 你的 API 地址
baseUrl = ''
}
export default {baseUrl}
封装数据接口
在我的项目根目录下新建文件夹 api
,用于保留编写数据接口,在该目录下新增文件 covid19.js
,用于封装申请获取数据:
import * as request from '@/utils/request'
/**
* 接口封装
*/
export default {getOverall() {let url = `/api/covid-19/overall?_=${Math.random()}`
return request.get(url)
},
getProvinceDataList() {let url = `/api/covid-19/area/latest/list?_=${Math.random()}`
return request.get(url)
},
getDailyList() {let url = `/api/covid-19/list?t=${Math.random()}`
return request.get(url)
}
}
调用数据接口获取数据并更新图表展现
// 引入
import covid19Service from '../api/covid19'
// 应用
let self = this
covid19Service.getOverall().then((res) => {if (!res.success) {console.log('谬误:' + res.info)
return
}
// 批改数据,图表组件检测到数据变动会触发 setOptions() 办法更新显示 ( setOptions() 在图表组件中已定义好 )
self.basicData = res.data
})
我的项目构造
残缺的我的项目构造如下:
├─build
├─data # 本地模仿数据目录
├─mock # mock 配置
├─public
└─src
├─api # 接口封装目录
├─assets
├─components # 组件目录
│ ├─About # 对于
│ ├─BasicDataItemLabel # 根本数据显示标签
│ ├─BasicProportionChart # 占比图表
│ ├─BasicTrendChart # 趋势图表
│ ├─ChartCard # 图表面板
│ ├─CuredAndDeadRateChart # 治愈率和死亡率图表
│ ├─CurrentConfirmedCompareBarChart # 最近一周累计治愈图表
│ ├─DataMap # 数据地图
│ └─ProvinceRankingBarChart # 累计排名图表
├─libs # 一些罕用的配置
├─router # 路由配置
├─utils # 工具类
└─views # 视图
具体构造:
总结
- 采纳组件化封装各个展现图表,能更好的图表展现及复用;
- 应用
axios
申请后盾服务或本地 mock 服务获取数据,而后从新赋值图表中指定的数据;
我的项目源码:本我的项目源码已上传至 Github,在我的博客中可查看到地址:应用 Vue+DataV+Echarts 打造新冠肺炎疫情数据大屏 (可动静刷新)
这个我的项目是集体学习作品,能力无限,难免会有 BUG 和谬误,敬请体谅。如有更好的倡议或想法,请指出,谢谢