Vue3 eckharts adaptive solution
actual combat
resize.js
import {nextTick, ref} from "vue"; import {debounce} from 'throttle-debounce'; /*chart Is an example of an echarts diagram*/ export const chart = ref(); /*Detects whether the sidebar zooms*/ let sidebarElm; /*Use the element resize detector to listen for changes in the sidebar*/ const elementResizeDetectorMaker = require("element-resize-detector"); const erd = elementResizeDetectorMaker(); /*Use the anti shake debounce function to reduce the times of resize*/ const chartResizeHandler = debounce(100, false, () => { if (chart.value) { chart.value.resize() } }) /*This function is executed after the sidebar width changes*/ const sidebarResizeHandler = (e) => { nextTick(() => { chartResizeHandler() }) } /*Add window size change monitor*/ const initResizeEvent = () => { window.addEventListener('resize', chartResizeHandler) } /*Remove window size change listener*/ const destroyResizeEvent = () => { window.removeEventListener('resize', chartResizeHandler) } /*Initialize sider listening*/ const initSidebarResizeEvent = () => { /*Get the document of the sidebar*/ sidebarElm = document.getElementsByClassName('sider-content')[0]; if (sidebarElm) { erd.listenTo(sidebarElm, sidebarResizeHandler) } } /*Remove sider listening*/ const destroySidebarResizeEvent = () => { if (sidebarElm) { erd.removeListener(sidebarElm) } } export const mounted = () => { initResizeEvent(); initSidebarResizeEvent(); } export const beforeDestroy = () => { destroyResizeEvent(); destroySidebarResizeEvent(); }
Actual use:
<template> <div style="height: 264px"> <div id="object-line" style="height: 264px;width: 100%"/> </div> </template> <script setup> import * as echarts from 'echarts'; import {nextTick, onBeforeUnmount, onMounted} from "vue"; import {mounted, beforeDestroy, chart} from "../../../../util/resize/resize"; const initLineChart = () => { const lchart = echarts.init(document.getElementById('object-line')); lchart.setOption(option); chart.value = lchart; } onMounted(() => { mounted(); nextTick(() => { initLineChart(); }); }) onBeforeUnmount(() => { beforeDestroy(); }) //x axis const tdata = [ ['2019-11-1', 32], ['2019-11-2', 55], ['2019-11-3', 80], ['2019-11-4', 55], ['2019-11-5', 80], ['2019-11-6', 32], ['2019-11-7', 32], ['2019-11-8', 32], ['2019-11-9', 32], ['2019-11-10', 32], ['2019-11-11', 32], ] const bdata = [ ['2019-11-1', 12], ['2019-11-2', 45], ['2019-11-3', 90], ['2019-11-6', 42], ['2019-11-7', 52], ['2019-11-8', 42], ['2019-11-9', 32], ['2019-11-10', 22], ['2019-11-11', 12], ] const option = { /*Mouse hover*/ tooltip: {}, /*tool*/ toolbox: { feature: { magicType: {show: true, type: ['line', 'bar']}, restore: {show: true}, saveAsImage: { show: true, title: '', } } }, backgroundColor: 'white', legend: { data: ['t2', 't1'], bottom: '2%' }, xAxis: { type: 'time', /*The x-axis is not displayed*/ axisTick: {show: false}, axisLine: { lineStyle: { width: 0 } }, data: [], /*x Axis label style*/ axisLabel: { color: '#888888', fontSize: 12, show: true, showMaxLabel: false, showMinLabel: false, formatter: '{MM}-{dd}', } }, yAxis: { type: 'value', splitLine: { show: true, lineStyle: { color: '#F5F5F5' }, }, axisLabel: { show: false }, }, /*Location of the map*/ grid: { x: 20, y: 40, x2: 20, y2: 40, containLabel: true }, series: [ { name: 't1', data: tdata, type: 'line', symbolSize: 8, lineStyle: { color: '#F62681 ', / / change polyline color width: 3, }, itemStyle: { borderWidth: 12, color: '#F62681 ', / / change inflection point color } }, { name: 't2', data: bdata, type: 'bar', barWidth: 30, itemStyle: { color: '#1CA9C9', borderRadius: [4, 4, 0, 0], } } ] }; </script> <style scoped> </style>
Import package
-
element-resize-detector
Install NPM install element resize detector -- save
-
throttle-debounce
Install NPM install throttle debounce -- save
Throttle debounce description
Let's introduce throttle and debounce. Both of them can be used for function throttling to improve performance, but they still have some differences:
- debounce: combine the events triggered multiple times in a short time into one event response function for execution (usually when the first event or the last event is triggered), that is, the event response function is actually executed only once in this period of time.
- throttle: if the same event is triggered multiple times in a short time, the event response function will be executed every smaller time interval, that is, the event response function may be executed multiple times in this period of time.
Although it takes more than ten minutes to wait for the elevator every day, you can take the elevator as an example:
- debounce: if I'm going to close the door in the elevator and A wants to take the elevator, I'll press the open button out of politeness, and then try to close the door after he enters the elevator; After A enters the elevator, I find that B also wants to take the elevator. Then, out of the same politeness, I will press the open door button and wait for him to enter the elevator. So if someone wants to take the elevator all the time, I will continue to delay the time to press the door close key until no one wants to take the elevator (if I do this in real life, I estimate that I can do nothing but take the elevator every day).
- throttle: actually, I have work to finish every day. I can't wait for others indefinitely in the elevator. Well, this time I'll be more willful. It's stipulated that I'll only wait 30 seconds. No matter if anyone wants to take the elevator, I'll press the door close button and leave.
From the above two examples, we can see that the biggest difference between the two is that as long as an event occurs (someone wants to take the elevator), if the throttle method is used, the event response function will be executed within a period of time (I press the door close key within 30 seconds); If the debounce method is used, it will be executed only after the event stops (I find that no one wants to take the elevator).
throttle
Limit how often callback functions are executed
/** * Throttling (frequency of execution of limit function) * @param delay Delay time * @param noTrailing Whether to execute callback during the last call. true does not execute, false executes * @param callback Target callback function * @param debounceMode */ throttle(delay, noTrailing, callback, debounceMode)
dobounceMode:
If true, execute callback when called. If not called, execute clear after the specified delay. If you continue calling before clear, the timer will be reset;
When it is false, the callback will not be executed when called. The callback will be executed after the specified delay. If the call continues before the callback is executed, the timer will be reset
debounce
The execution frequency of the callback function is limited, but unlike debounce, debounce can ensure that the callback function is executed only once in a series of calls
/** * Debouncing (limit the execution frequency of the function) * @param delay Delay time * @param atBegin * @param callback Target callback function */ debounce(delay, atBegin, callback)
atBegin:
When it is true, the callback will be executed immediately when it is called. If the call continues before the delay time, the callback will not be executed;
When it is false, the callback will not be executed when it is called. The callback will be executed after the delay time. If the call continues before the delay time, the timer will be reset
Problem: if two charts appear on a page, only one will take effect!
Modify resize.js
import {nextTick, ref} from "vue"; import {debounce} from 'throttle-debounce'; export default function () { const chart = ref(); let sidebarElm; const elementResizeDetectorMaker = require("element-resize-detector"); const erd = elementResizeDetectorMaker(); const chartResizeHandler = debounce(100, false, () => { if (chart.value) { chart.value.resize() } }) const sidebarResizeHandler = (e) => { nextTick(() => { chartResizeHandler() }) } const initResizeEvent = () => { window.addEventListener('resize', chartResizeHandler) } const destroyResizeEvent = () => { window.removeEventListener('resize', chartResizeHandler) } const initSidebarResizeEvent = () => { sidebarElm = document.getElementsByClassName('sider-content')[0]; if (sidebarElm) { erd.listenTo(sidebarElm, sidebarResizeHandler) } } const destroySidebarResizeEvent = () => { if (sidebarElm) { erd.removeListener(sidebarElm) } } const mounted = () => { initResizeEvent(); initSidebarResizeEvent(); } const beforeDestroy = () => { destroyResizeEvent(); destroySidebarResizeEvent(); } return { chart, mounted, beforeDestroy, } }
use
<template> <div style="height: 264px"> <div id="object-line" style="height: 264px;width: 100%"/> </div> </template> <script setup> import * as echarts from 'echarts'; import {nextTick, onBeforeUnmount, onMounted} from "vue"; import resize from "../../../../util/resize/resize"; const {chart, mounted, beforeDestroy} = resize(); const initLineChart = () => { const lchart = echarts.init(document.getElementById('object-line')); lchart.setOption(option); chart.value = lchart; } onMounted(() => { mounted(); nextTick(() => { initLineChart(); }); }) onBeforeUnmount(() => { beforeDestroy(); }) //x axis const tdata = [ ['2019-11-1', 32], ['2019-11-2', 55], ['2019-11-3', 80], ['2019-11-4', 55], ['2019-11-5', 80], ['2019-11-6', 32], ['2019-11-7', 32], ['2019-11-8', 32], ['2019-11-9', 32], ['2019-11-10', 32], ['2019-11-11', 32], ] const bdata = [ ['2019-11-1', 12], ['2019-11-2', 45], ['2019-11-3', 90], ['2019-11-6', 42], ['2019-11-7', 52], ['2019-11-8', 42], ['2019-11-9', 32], ['2019-11-10', 22], ['2019-11-11', 12], ] const option = { /*Mouse hover*/ tooltip: {}, /*tool*/ toolbox: { feature: { magicType: {show: true, type: ['line', 'bar']}, restore: {show: true}, saveAsImage: { show: true, title: '', } } }, backgroundColor: 'white', legend: { data: ['t2', 't1'], bottom: '2%' }, xAxis: { type: 'time', /*The x-axis is not displayed*/ axisTick: {show: false}, axisLine: { lineStyle: { width: 0 } }, data: [], /*x Axis label style*/ axisLabel: { color: '#888888', fontSize: 12, show: true, showMaxLabel: false, showMinLabel: false, formatter: '{MM}-{dd}', } }, yAxis: { type: 'value', splitLine: { show: true, lineStyle: { color: '#F5F5F5' }, }, axisLabel: { show: false }, }, /*Location of the map*/ grid: { x: 20, y: 40, x2: 20, y2: 40, containLabel: true }, series: [ { name: 't1', data: tdata, type: 'line', symbolSize: 8, lineStyle: { color: '#F62681 ', / / change polyline color width: 3, }, itemStyle: { borderWidth: 12, color: '#F62681 ', / / change inflection point color } }, { name: 't2', data: bdata, type: 'bar', barWidth: 30, itemStyle: { color: '#1CA9C9', borderRadius: [4, 4, 0, 0], } } ] }; </script> <style scoped> </style>