1.旧代码:echarts
analyzeRadar().then(result => { if (res.code === 200) { this.setEcharts({ indicator: indicator, seriesData: seriesData }) } }
setEcharts (data) { const dom = this.$refs.echart let myChart = echarts.init(dom) const option = {…} myChart.setOption(option) this.$once('hook:beforeDestroy', () => { window.removeEventListener('resize', myChart.resize) myChart.clear() myChart.dispose() }) window.addEventListener('resize', myChart.resize) }
2.加上定时器,报错dom
analyzeRadar().then(result => { if (res.code === 200) { this.setEcharts({ indicator: indicator, seriesData: seriesData }) this.timer = setTimeout(() => { this.getData() }, 5000) } }
缘由分析:一进入页面,定时器执行一次,过了this.second * 1000s以后,定时器又执行一次,总共两次,切换到其余页面,执行销毁钩子,清理第一个定时器正常,清理第二个的时候myChart在上一次已经被清理,为undefined,执行clear()方法报错this
3.修改成以下代码:(正确)spa
setEcharts (data) { const dom = this.$refs.echart // echarts.getInstanceByDom(dom)只有init以后dom上才会有echart实例,不然为undefined,即第一次进入,那么才进行初始化,第二次以后dom上就有echart实例了,就不用初始化,能够直接setOption构图了 let myChart = echarts.getInstanceByDom(dom) // 获取 dom 容器上的实例。 if (!myChart) { // 若不存在则代表是首次加载组件,需初始化 myChart = echarts.init(dom) // 跟if触发无关,只是为了首次进入使用mychart不会报错,触发条件是一离开页面就触发 this.$once('hook:beforeDestroy', () => { // 只会在首次的时候入栈一个 clearTimeout(this.timer) window.removeEventListener('resize', myChart.resize) myChart.clear() myChart.dispose() }) window.addEventListener('resize', myChart.resize) } const option = {…} myChart.setOption(option) } }
4.如下想法是错误的:hook:beforeDestroy执行的次数与定时器执行的次数相同,myChart.clear()没问题,第二次就undefined.clear()报错,因此应该只在首次入栈一次code
if (!myChart) { // 若不存在则代表是首次加载组件,需初始化 myChart = echarts.init(dom) } else { // 有myChart才去清,报错 this.$once('hook:beforeDestroy', () => { // 定时次执行几回,它就入栈几回,最终销毁的时候执行几回 clearTimeout(this.timer) window.removeEventListener('resize', myChart.resize) myChart.clear() myChart.dispose() }) window.addEventListener('resize', myChart.resize) }