This blog is also inspired by the company’s project, because I used to write React a lot. Although I always remember to use the framework, developers do not want to operate the DOM native, but when the React mainstream scaffolding CRA converts the virtual DOM into the real DOM, Also use the document. The getElementById

React is written to look a lot like native JavaScript, so I probably wasn’t in awe of this warning until a few days ago when I was writing the company’s Vue stack project requirements.

1 Problem Description

I reused a component called < lay-bar-Graphs > in my project that uses Echarts. , roughly as follows:

<div class="template-bewteen">
    <lay-bar-graphs :num="1"></lay-bar-graphs>
    <lay-bar-graphs :num="2"></lay-bar-graphs>
</div>
Copy the code

The inside of the component looks something like this (just a container div and a div that contains an Echarts rendering) :

<template> <div class="layGraphs-container"> <div id="layBarGraphs" ref="layBarGraphs" style="width:100%; height:100%;" > </div> </div> </template>Copy the code

The effect I want is like this (internal screenshots cannot be transferred to the Internet, small paste) :

But what I get is this (it looks like only one < lay-bar-Graphs > component is successfully rendered)

The < lay-bar-Graphs > component is rendered twice, but there is only one

in the DOM tree (we all know echarts renders elements as canvas)

2 Solving problems

2.1 Focusing Problems

Then we realized that the problem was with the rendering, and confirmed by console and other means that Echarts did render twice.

If you’ve used Echarts, you’ll know that echarts needs to obtain the DOM

import * as echarts from 'echarts'; Var chartDom = document.getelementById ('main'); Var myChart = echarts.init(chartDom); // Initialize var option = {... }; // configure option && mychart.setoption (option); / / renderingCopy the code

So we immediately focused on getting the DOM, and it was a snap of mind.

CSS is global. Libraries such as Vue and React are componentized, but only simulate component effects by means of closuresid ,classIt’s still global. This is why scaffolding now uses less/sass/ CSS Modules for local style isolation.

By the way, we’ve heard a lot about web components in browsers these days. They support componentization without frameworks, and they don’t need to worry about style conflicts.

2.2 Solutions

When you get the DOM in the framework, you can definitely think of using ref. So why isn’t there a problem with ref? So let me go back.

The element marked by ref becomes an attribute of the component instance, and each use of the component creates a new instance, so that even if the attribute names are the same, they can distinguish which is which, so that echarts renders are not the same element.

3 develop

How do native HTML and JS reuse Echarts components? After discussion with colleagues and the elder brother in the group, we wrote some code, everyone can paste themselves to try ~

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta Width =device-width, initial-scale=1.0"> <title>Document</title> <style> div{border: black solid 1px; width: 400px; height: 400px; } .bule { background-color: #00f; width: 3oopx; height: 300px; } .green { background-color: #0f0; width: 3oopx; height: 300px; } </style> </head> <body> <div id="t1"></div><div id="t2"></div> <script type="text/javascript" SRC = "https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js" > < / script > < script > function fn (color) {let obj = document.createElement('p'); Obj. ClassName = color Height = '300px' var myChart = echarts.init(obj); var option; option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [ { data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line', smooth: true } ] }; option && myChart.setOption(option); return obj; } document.getElementById('t1').appendChild( fn('green') ); document.getElementById('t2').appendChild( fn('bule') ); </script> </body> </html>Copy the code

The trick is that createElement encapsulates a function that creates a new element each time it is executed. There is no rendering of the same element. In addition in the Vue can also through the document. The getElementsByClassName for DOM, because is an array class! When you reuse a component, you pass in an argument that specifies which DOM to render (but it’s definitely easy to use ref).