目录
组件库
移动端
vue
vant
PC端
react
antd
vue
element
调试:vconsole vs dev tools中的控制台(Console)
vconsole:在真机上调试
构建工具
webpack
原理
Babel:JS编译器(es6->es5,jsx->js)
loader:编译
less-loader:less->css
css-loader:css->js
style-loader:创建style标签,将js中的样式资源插入标签内,并将标签添加到head中生效
ts-loader:打包编译Typescript文件
plugin:压缩
html-webpack-plugin :处理html资源,默认会创建一个空的HTML,自动引入打包输出的所有资源(js/css)
mini-css-extract-plugin: 打包过后的css在js文件里,该插件可以把css单独抽出来
clean-webpack-plugin :每次打包时候,CleanWebpackPlugin 插件就会自动把上一次打的包删除
loader和plugin的区别:loader运行在编译阶段,plugins 在整个周期都起作用
热加载原理:实时看到代码变化
vite(快,简,小)
源文件的处理
resolve :解析 url,找到源文件的绝对路径;
load :加载源文件。
第三方依赖:直接将预构建内容返回给浏览器;
业务代码:继续 transform、parser。
transfrom :对源文件内容做转换,即 ts -> js, less -> css 等。转换完成的内容可以直接返回给浏览器了。
parser: 对转换以后的内容做分析,找到依赖模块,对依赖模块做预转换 - pre transform 操作,即重复 1 - 4。
快:启动/热更新
ESM+unbundle
性能下降:大量http请求,按需动态编译
首屏
懒加载
可视化引擎
移动端
antv f2
PC端
antv
antv G6
Vue2
scss
Echarts
Vue3
radar
React
原生echarts+TS
ListChart(列表切换echarts图表,同类数据为x轴的bar)
ListChart.tsx
ListChart.css
ListChartUtil.tsx
Recharts
D3
移动端需要考虑:轻量级
类似参考链接:搭建一个vue-cli4+webpack移动端框架(开箱即用) - 掘金
浏览器中显示log和调试信息的 JS 库
npm install vconsole
import VConsole from 'vconsole';
if (import.meta.env.MODE === 'development') {
const vConsole = new VConsole();
Vue.prototype.vconsole = vConsole //把这个方法放到vue原型上,方便在页面中调用
}
ctrl+c终止运行(webpack需要重启,vite不需要)
它将根据模块的依赖关系进行静态分析,然后将这些模块( js、css、less )按照指定的规则生成对应的静态资源,减少了页面的请求。Webpack是以公共JS的形式来书写脚本的,方便旧项目进行代码迁移。
Webpack通过一个给定的主文件(如:index.js)开始找到项目的所有依赖文件,
使用loaders处理它们,plugin可以压缩代码和图片,
把所有依赖打包成一个 或多个bundle.js文件(捆bundle)浏览器可识别的JavaScript文件。
将es6、es7、es8等语法转换成浏览器可识别的es5或es3语法,即浏览器兼容的语法,比如将箭头函数转换为普通函数
将jsx转换成浏览器认的js
webpack只认识JS和JSON,所以Loader相当于翻译官,将其他类型资源进行预处理,最终变为js代码。
开发中,会使用less预处理器编写css样式,使开发效率提高)
将css文件变成commonjs模块(模块化的规范)加载到js中,模块内容是样式字符串
Plugin解决loader 无法实现的事情,比如打包优化和代码压缩等。
热加载是通过内置的 HotModuleReplacementPlugin 实现的
源文件的处理
resolve
:解析 url
,找到源文件的绝对路径;load
:加载源文件。transform
、parser
。transfrom
:对源文件内容做转换,即 ts
-> js
, less
-> css
等。转换完成的内容可以直接返回给浏览器了。parser
: 对转换以后的内容做分析,找到依赖模块,对依赖模块做预转换 - pre transform
操作,即重复 1
- 4
。pre transform
是 Vite
做的一个优化点。预转换的内容会先做缓存,等浏览器发起请求以后,如果已经完成转换,直接将缓存的内容返回给浏览器。
启动/热更新
ESM+unbundle
(ES modules 是 JavaScript 官方的标准化模块系统。)
vite源文件之间的依赖通过浏览器对 ESM 规范的支持来解析,不再需要额外打包处理。
请求模块时按需动态编译显示
webpack启动慢主要是因为模块依赖图 - module graph
构建 module graph
的过程中,涉及到大量的文件 IO、文件 transfrom、文件 parse 操作;
分解 module graph
的过程中,需要遍历 module graph
、文件 transform、文件 IO
http
请求dev server
运行期间对源文件做resolve、load、transform、parse
操作Vite把需要在启动过程中完成的工作,转移到响应浏览器请求的过程中
之后reload
页面时,首屏的性能会好很多(缓存)
动态加载的文件,需要做 resolve、load、transform、parse
操作,并且还有大量的 http
请求
移动端使用antv f2
vue使用antv f2
yarn add @antv/f2
yarn add @antv/f-vue
npm install @antv/f2 --save
npm install @antv/f-vue --save
//配置 F2 的 JSX 编译
npm install @babel/plugin-transform-react-jsx --save-dev
F2 使用 JSX 语法来构建图表,所以需要在运行前对 JSX 语法进行编译, JSX 更多细节可参考 React 的官方文档 JSX 简介
Babel 和 TypeScript 都可以编译 JSX 语法,并且在编译时 JSX 语法时,会有 2 种编译模式,在实际项目中可根据自己实际情况选择和使用
如果你希望在 Vue 3 组件中使用普通的 JSX 语法,你可以选择经典的配置方式。这种情况下,你需要设置 jsxFactory
和 jsxFragmentFactory
选项。以下是示例的 tsconfig.json
文件:
{
"compilerOptions": {
"jsx": "preserve", // 保留 JSX 语法
"jsxFactory": "jsx", // 指定 JSX 的工厂函数
"jsxFragmentFactory": "Fragment" // 指定 JSX 片段的工厂函数
}
}
在这种配置下,你需要确保你的 Vue 组件中使用的 JSX 工厂函数和片段工厂函数与你在配置中指定的名称相匹配。
如果你想要使用自动化的 JSX 语法,你可以使用 jsx
和 jsxImportSource
选项。这种情况下,你可以将 AntV F2 的组件库作为 JSX 的导入来源。以下是示例的 tsconfig.json
文件:
{
"compilerOptions": {
"jsx": "react-jsx", // 使用 React 的 JSX 语法
"jsxImportSource": "@antv/f2" // 指定 JSX 的导入来源
}
}
在这种配置下,你可以在 Vue 组件中使用类似 React 的 JSX 语法,不过你需要确保在组件中导入了所需的 AntV F2 组件。
选择哪种配置取决于你更喜欢的语法和使用方式。如果你使用经典配置,你可以继续使用普通的 JSX 语法;如果你使用自动配置,你可以借助 AntV F2 提供的 JSX 语法来创建图表组件。
vue 默认是不支持直接在组件的 中使用 JSX 语法的。
如果你不想使用 JSX,你可以将组件的 部分改为使用 Vue 的选项式 API 或 Composition API (
原生echats官方文档和功能比echarts-for-react全,
但echarts-for-react对react支持更友好,使用更简单
import React, { useEffect, useRef, useState } from 'react';
import { List, Button} from 'antd';
import { LineChartOutlined, BarChartOutlined } from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components';
import * as echarts from "echarts";
import './ListChart.css'
import { LIST_NAME, CHART_OPTION,resize,findSubstrIdx } from '../utils/ListChartUtil';
import { ListChartStatus } from "./ListChartStatus";
const ListChart: React.FC = ({ urlPre, proc_datas, board_name }) => {
const chartRef = useRef(null);
const [selectedIdx, setselectedIdx] = useState(0);
const [isLine, setIsLine] = React.useState(true);
const proc_list = new Array(proc_datas.length).fill(null).map((val, i) => {
return proc_datas[i].proc_name;
});
let chart: any = null;
useEffect(() => {
if (chartRef.current) {
chart = echarts.init(chartRef.current);
const {option,urlSufs}=getOption(proc_datas[selectedIdx])
chart.setOption(option);
resize(chart);
chart.on('click', isLine ? 'xAxis' : 'series', function (params: any) {
const clickDate= isLine ? params.value:params.seriesName;
window.open(urlPre + '/' + urlSufs[findSubstrIdx(urlSufs, clickDate)] + '/index.html', '_blank');
});
}
}, [chartRef, selectedIdx, isLine]);
const initDate_UrlSufs=(proc_data:any)=>{
let urlSufs: string[] = [];
let dates: string[] = [];
proc_data.date_list.forEach((date: string, idx: number) => {
urlSufs.push(date + '/' + proc_data.report_id_list[idx]);
dates.push(date.substring(5));
});
return {dates,urlSufs};
}
const getBarDates=(series:any)=>{
const barDatas: any = [];
LIST_NAME.forEach((_, idx) => {
if (series[idx] && series[idx].length) {
barDatas.push([LIST_NAME[idx], ...series[idx]])
}
})
return barDatas;
}
const getOption=(proc_data:any)=>{
const {dates,urlSufs}=initDate_UrlSufs(proc_data)
const series = [proc_data.avg_list, proc_data.sigma3_up_list, proc_data.sigma3_up_target_list, proc_data.sigma3_down_list, proc_data.max_list, proc_data.min_list]
let option = {
tooltip: CHART_OPTION.tooltip,
legend: CHART_OPTION.legend,
toolbox: CHART_OPTION.toolbox,
yAxis: CHART_OPTION.yAxis,
title: {
text: proc_data ? board_name + ":" + proc_data.proc_name : board_name,
subtext: "点击日期可跳转到详情报告",
},
xAxis: {
type: 'category', // 类型为分类轴
triggerEvent: true, // 是否触发鼠标事件
data: isLine ? proc_data.date_list.map((date: string, idx: number) => {
return dates[idx]
}) : null,
},
series: isLine ? LIST_NAME.map((_, idx) => {
if (series[idx] && series[idx].length) {
return {
name: LIST_NAME[idx],
type: 'line',
data: series[idx],
emphasis: {
focus: 'series'
},
}
}
}) : dates.map((_, idx) => {
return {
name: dates[idx],
type: 'bar',
event: 'click',
emphasis: {
focus: 'series'
},
}
}),
dataset: isLine ? null : {
source: [
['pref', ...dates],
...getBarDates(series)
]
},
};
return {option,urlSufs};
}
return (
setselectedIdx(index)}>
{item} }
/>
} onClick={() => setIsLine(true)} >
} onClick={() => setIsLine(false)}>
)
}
export default ListChart;
.procard {
display: flex;
padding-top: 10px;
}
.procard-list {
overflow-y: scroll;
height: 45vh;
}
.selected {
background-color: #e6f7ff !important;
}
.procard-button{
display: flex;
justify-content: flex-end;
padding-right: 7vw;
}
export const LIST_NAME = ['avg', '3∑-up', '3∑-up-target', '3∑-down', 'max', 'min']
export const CHART_OPTION = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: "shadow"
},
},
legend: {
left: 'center',
width: '35%',
selected: {
'min': false,
'3∑-down': false,
}
},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: { readOnly: false },
// magicType: { type: ['line'] },
restore: {},
saveAsImage: {}
},
right: "10%"
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} '
}
},
}
const dom: any = []; //所有echarts图表的数组
/**
* 当屏幕尺寸变化时,循环数组里的每一项调用resize方法来实现自适应。
* @param {*} eDom
*/
export function resize(eDom: any) {
dom.push(eDom);
window.onresize = () => {
dom.forEach((it: any) => {
it.resize();
})
};
}
export function findSubstrIdx(arr: string[], substr: string): number {
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(substr) !== -1) {
return i;
}
}
return -1;
}
React hooks 封装 ECharts5 通用组件 - 掘金
React+TypeScript封装ECharts_typescript+react 封装调用方法_KzXuanCn的博客-CSDN博客
GitHub - hustcc/echarts-for-react: ⛳️ Apache ECharts components for React wrapper. 一个简单的 Apache echarts 的 React 封装。
是一个基于React封装的库,使用了D3强大的绘图功能,使得使用React进行数据可视化变得更加简单。
优点
Recharts易于使用,因为它具有数量较少的自定义选项。
集成了React的生命周期方法,使它易于添加到React应用程序中,并可支持Redux状态管理器。
轻量级,对内存和CPU的影响较小。
支持多种样式、自定义颜色和动画。
缺点
不支持所有类型的图表,没有Echarts种类繁多。
功能相比于Echarts较少
综上所述,如果需要设计高度自定义的图表并且有足够的开发经验,那么使用Echarts可能更方便。另一方面,Recharts对于快速简单的数据可视化任务可能更适合,并且易于集成到React应用程序中。
是一个基于数据驱动文档的JavaScript库,具有高度灵活性和自定义性,但需要更多的编码工作。