前端那些事之源码调试
小编从2017年入行,到现在已经六年的时间了,最开始会的东西也少,对于需求做起来都很费劲,而且那时候很多浅显的东西,去网上一找一大片。随着做的项目增加和突破了一个又一个的技术壁垒。小编也在成长,特别是最近小编遇到的一个性能问题,昨天晚上花了一晚上的时间,整理了一下自己针对element-ui源码的调试过程,希望大家能一起进步。
主要是小编在使用element-ui做项目的时候,里面有个功能模块,需要用的下拉树,为了项目进度,小编就找了一个开源的el-select-tree。github地址:https://github.com/yujinpan/el-select-tree
当然,这个下拉树的优点在于可以支持element-ui中Select和Tree的全部的props、methods和events,这就让我把这个融入到项目里很省心。根据官方的demo,先写出了这样的代码
main.js【全局注册el-select-tree】
import Vue from 'vue';import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';import ElSelectTree from 'el-select-tree';...Vue.use(ElementUI);Vue.use(ElSelectTree);...
App.vue【使用el-select-tree组件。详细props可以参考element-ui官网】
<template><el-select-treewidth="120px"placeholder="请选择内容"show-checkbox:data="treeData"v-model="value"filterablemultiple></el-select-tree></template><script>export defalut{name:'app',data(){return {value: [], // 因为组件中添加了multiple属性,绑定的时候需要是数组,官网给的是int类型数据,小编因为这个控制台报错还找了好久treeData: [{value: 1,label: 'text1',children: [{ value: 5, label: 'text5' },{ value: 6, label: 'text6' }]},{ value: 2, label: 'text2' },{ value: 3, label: 'text3' },{ value: 4, label: 'text5' }]}}}</script>
当时,项目中的数据结构和和组件的结构不一样,项目中的组件,需要用到props属性对数据进行转换,返回数据大概是这样
{code:'000000',data:[{code:'1000000',name:'长春市',id:'a',children:[{code:'1000001',name:'南关区',id:'a1',},{code:'1000002',name:'朝阳区',id:'a2',},...]},{code:'2000000',name:'吉林市',id:'b',children:[{code:'2000001',name:'船营区',id:'b1',},{code:'2000002',name:'昌邑区',id:'b2',},...]},],msg:'数据加载成功'}
在element-ui中,Tree默认的props是这样的

很显然,后端返回的数据不符合默认格式,这个时候,我就在el-select-tree组件中添加了props,就变成了这样
<template><el-select-treewidth="120px"placeholder="请选择内容"show-checkbox:data="treeData"v-model="value"filterablemultiple:props="{label:(data) => {return data.code+'-'+data.name}, children:'children'}"></el-select-tree></template>
又这样相安无事了一段时间,后来随着数据的增加,返回到前端的数据数量和层级都越来越多,前端的压力也越来越重,对于一些客户端电脑性能不好的,经常能看到他们浏览器【无响应】。作为前端,其实给出最好的建议就是懒加载,但是后端说这个接口是公共接口,不能轻易改动,卑微的小编只能默默的自己看看源码,看看能不能从中间得到一些启示
于是小编打开了node_modules下的elemen-ui/package/tree/src/node.js文件。其中这段代码引起了小编的注意

这段代码的意思就是将el-tree中的props循环一遍,我一想,那是不是tree上的props越少,在实例化Node的时候,性能开销就不会那么大了呢?不管那么多,小编先将el-select-tree中的props去掉,然后通过js重新规范了一下数据,将code和name拼接后直接赋值给组件,刷新浏览器之后,小编感觉性能已经有了很大的提升。但是小编只是停留在猜测上,有没有什么办法能直接对node_modules中的代码进行调试呢?于是小编开始了对npm包中的内容展开了探索
说到这,小编先对项目内的package.json文件做个简单的说明
{"name": "my-project", // 包名,唯一,在Vue项目入口文件的import Element from 'element-ui'就来自这"version": "1.5.0", // 版本"description": "Express server project using compression", // 描述"main": "src/index.js", // 入口文件,相当整个包的入口,我们后续使用npm link创建链接的时候,需要改动内容"scripts": { // 脚本文件,每次npm run <CMD> 就是在这里面"start": "node index.js","dev": "nodemon","lint": "eslint **/*.js"},"dependencies": { // 依赖,每次npm install <packageName> --save 就会记录在这个位置"express": "^4.16.4","compression": "~1.7.4"},"devDependencies": { // 开发依赖,每次npm install <packageName> --save-dev 就会记录在这个位置"eslint": "^5.16.0","nodemon": "^1.18.11"},"repository": { // 代码仓库"type": "git","url": "https://github.com/osiolabs/example.git"},"author": "Jon Church", // 作者"contributors": [{"name": "Amber Matz","email": "example@example.com","url": "https://www.osiolabs.com/#team"}],"keywords": [ // 关键字"server","osiolabs","express","compression"]}
平时我们使用npm install <packageName>和 npm run <CMD>命令比较多。今天我们熟悉一下npm link命令。具体详情,可以参考 https://docs.npmjs.com/cli/v6/commands/npm-link/
在《前端架构师》一书中,已经介绍了npm link命令的使用场景和实例
为依赖项创建全局软链npm link。一个符号链接,简称软链,是一个快捷方式,指向系统上的其它目录或文件。
小编主要是从以下几个步骤进行调试
1、复制node_modules下element-ui文件夹到桌面
2、进入~/Desktop/element-ui目录下,执行npm link命令
3、回到项目中,进入项目根目录,执行npm link element-ui
这个时候,在~/Desktop/element-ui/package中打断点的时候,并不会有效果,查看了一下~/Desktop/element-ui/package.json文件中的main,指向的并不是~/Desktop/element-ui/package/index.js文件,这个时候,我们修改一下~/Desktop/element-ui/package.json中入口文件地址即可
4、这个时候我们可以debugger,或者console,都很方便,能让我们更深层次的理解源码和对第三方库的使用。
5、我们需要断开链接的时候,使用npm unlink即可
写在最后
小编在找资料的时候,还发现了https://github.com/niesk/el-virtual-tree。据说可以通过虚拟滚动的方式解决tree的性能问题;
还发现了可以通过element-ui源码,生成sourceMap的方式通过浏览器调试;
还发现了一个叫 patch-package 的包,据说可以紧急解决第三方库的缺陷问题
还有文中说的懒加载处理Tree数据,小编都将在后续的文章持续更新,希望大家持续关注,也可以推送给身边的小伙伴!
