这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
前言
本集锦在前后端分离的架构下,webpack打包、vue.js框架的技术下遇到的使用问题集锦。
(绘图问题集锦详见另一篇:juejin.cn/post/708329… )
在 webpack 中使用 ECharts 详见官方文档: echarts.baidu.com/tutorial.ht…
一、vue的keep-alive导致echarts获取不到dom
keep-alive的用法
官方文档:
https://cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%9C%A8%E5%8A%A8%E6%80%81%E7%BB%84%E4%BB%B6%E4%B8%8A%E4%BD%BF%E7%94%A8-keep-alive
https://cn.vuejs.org/v2/api/#keep-alive
https://cn.vuejs.org/v2/guide/migration.html#keep-alive-%E5%B1%9E%E6%80%A7-%E6%9B%BF%E6%8D%A2
注意点
1、和<transition>
连用
和 <transition>
一起使用时,确保把内容包裹在内:
<transition>
<keep-alive>
<component v-bind:is="view"></component>
</keep-alive>
</transition>
可以理解为,因为keep-alive和router-view是连一起用的,拆开就没有保持缓存的作用了!!!
就连当前页面watch监控'$route'都会出错……
2、和echarts一起用
若当前路由A用到echarts,然后想使用keep-alive保持缓存。
在清空浏览器缓存后,初次登录当前页面A没有问题。
跳转离开,再次进入A,发现echarts图形无法正常绘制,报错获取不到dom的高度和宽度。
通过Element查看当前dom的高宽是存在的。
费解……
于是在生命周期钩子函数activated中获取dom节点查看高宽确实为0,即便使用setTimeout延迟获取dom节点查看高宽仍然为0。直到去掉keep-alive,一切恢复正常。
所以……
keep-alive还是不要用在有echarts的地方了。
二、echarts的div高度一定要定义
高度不定义可能会导致加载了但没显示出来!
eecharts的div高度一定要定义!!
当然了宽度最好也定义!!
三、elementUI的tab页中画echarts图形问题
elementUI的tab页通过v-show控制tab页存在但不展示(v-if不存在v-show存在),但是非当前tab的高宽没有!
导致不能够一次性把所有tab页的图画上,会提示dom高宽未定义!!!
所以可通过切换tab页时将当前数值传递给echarts进行绘制。
四、主题json引入问题
1、json引入和import导入
obj = JSON.parse('/static/***.json')
parse不能这么引入json,于是我import一下吧
import from '/static/***.json'
并没有用啊,谁告诉你import这么用的!!!
2、那试试jquery读json文件咯
jQuery.getJSON("/static/***.json", "", function(response) {
obj = JSON.parse(response)
})
还是报错,因为response已经是对象了!不需要再JSON.parse!
3、于是直接注册主题吧
jQuery.getJSON("/static/***.json", "", function(response) {
echarts.registerTheme('themeName', response)
})
let myChart = echarts.init(document.getElementById('test'), 'themeName')
还是没用啊,不对是页面闪现了一下,因为jquery异步,又回到默认了。
4、所以将init放到jQuery处理后
如下总算能引入自定义的主题色了
jQuery.getJSON("/static/***.json", "", function(response) {
echarts.registerTheme('themeName', response)
echarts.init(document.getElementById('test'), 'themeName')
})
5、最后其实import很好用啊,这里有了import还要什么jquery。
import chartOpt from './***.json'
let self = this
echarts.registerTheme('themeName', chartOpt)
self.initChart()
呵呵呵,其实这样就好了。
五、echarts3D图引入需要额外下载安装echarts-gl
package.json中的dependencies,添加"echarts-gl": "^1.1.1",会有提示尚未安装
去项目所在根目录执行命令npm install echarts-gl --save
webpack会去下载包save指令会将下载的详情保存至package-lock.json文件中
在使用echarts的时候import 'echarts-gl'即可。
六、echarts缓存问题
当series[]中包含多个对象多组data[]时:
以折线图为例,能实现一条折线到两条的增加,但是当series[]中data[]减少为一条折线数据时,仍然会显示之前的两条折线。
思考过程:
找到this.myChart.setOption(this.currentData)处,打印this.currentData
其中series[]明明只有一个,但是会画出两条甚至多条折线图!!!
猜想是不是有缓存,百度echarts缓存清理得知,需要在setOption之前调用clear方法,即:
this.myChart.clear()
this.myChart.setOption(this.currentData)
果然问题解决。
七、echarts宽度变化后重绘的问题
window.onresize监听宽度变化毛线用没有
定时器定时查询echarts外层div的宽度不建议使用
addEventListener加载监听事件到echarts外层div总是失效
所以,可以在最外层加addEventListener宽度,变化了存起来,然后computed属性读取vuex里面存的宽度,然后watch全局宽度变量变化了就重新绘制echarts。
但是我还是喜欢定时器哈哈哈哈哈
定时器:
- 用完一定要记得关闭,用之前最好先clearTimeout!!!
- 用完一定要记得关闭,用之前最好先clearTimeout!!!
- 用完一定要记得关闭,用之前最好先clearTimeout!!!
记住这样:
somefuntion () {
// 需要定时执行的方法
clearTimeout(this.timer)
this.timer = setTimeout(somefuntion, 30000)
}
destroyed () {
clearTimeout(this.timer)
}
解释: 写在setTimeout()之前的清除,只是为了保证当前定时器只开启了一个。
先清除缓存中的定时器,然后开启一个30s后执行一次的定时器,30s后先清除还有没有定时器(一般没有),新建一个定时器,以此循环。
比起setInterval建议使用setTimeout只是延迟执行一次
八、myChart对象定义位置的区别
自己定义的echarts组件,通常把myChart = echarts.init(document.getElementById(this.id), 'theme-mychart')挂在
data () {
return {
myChart: null
}
}
同事说这样导致vue对象太大??不太理解
但是经同事建议将myChart定义在外部,如下:
let myChart = []
export default {
methods: {
echartsShow () {
echarts.registerTheme('theme-mychart', chartTheme)
myChart = echarts.init(document.getElementById(this.id), 'theme-mychart')
},
echartsResize () {
// 重绘图像
myChart.resize()
}
}
}
这有个问题,同一路由下多个echarts组件引入,后面的myChart会覆盖前面的,导致重绘图像只能操作最后一个myChart!
最后借鉴隔壁项目组将同一路由下的myChart放到数组中定义在外部,myChart是临时变量,重绘时遍历数组如下即可:
let myChartArr = []
methods: {
echartsShow () {
echarts.registerTheme('theme-mychart', chartTheme)
let myChart = echarts.init(document.getElementById(this.id), 'theme-mychart')
// 清理echarts缓存
myChart.clear()
// 绘制图像
myChart.setOption(this.currentData)
// 判断是否需要往数组里添加myChart对象
let replace = null
for (let i = 0; i < myChartArr.length; i++) {
if (myChartArr[i]._dom.id === this.id) {
replace = i
break
}
}
if (replace !== null) {
myChartArr.splice(replace, 1, myChart)
} else {
myChartArr.push(myChart)
}
},
echartsResize () {
// 重绘图表
for (let i = 0; i < myChartArr.length; i++) {
if (this.id === myChartArr[i]._dom.id) {
myChartArr[i].resize()
break
}
}
}
}
九、动态追加数据效果
修改series中的data再重新绘制echarts会导致动画从头到尾重新绘制。
比如说随着时间推移数据追加,如果重新绘制echarts会导致动画从第一个数值开始刷新到最后一个,体验很不好。
参考官方案例:
echarts.apache.org/examples/zh…
关键点在:
不要重新创建echarts对象,只需对原来的echarts对象.setOption(newOption)即可。