澳门新葡亰亚洲在线Javascript

XCel 项目总:Electron 与 Vue 的属性优化

2017/03/01 · 基础技术 ·
Javascript,
算法

正文作者: 伯乐在线 –
刘健超-J.c
。未经作者许可,禁止转载!
迎接加入伯乐在线 专栏撰稿人。

XCEL 是出于京东用户体验设计部凹凸实验室推出的一个 Excel
数据清洗工具,其经过可视化的办法给用户轻松地对 Excel 数据开展筛选。

XCEL 基为 Electron 和 Vue 2.x,它不仅超越平台(windows 7+、Mac 和
Linux),而且充分利用 Electron 多进程任务处理等功用,使该性出色。

落地页:https://xcel.aotu.io/ ✨✨✨
列地址:https://github.com/o2team/xcel ✨✨✨

路背景

用户研究的定量研究和轻量级数据处理着,均需要对数码开展保洁处理,以去异常数据,保证数据结果的信度和效度。目前因调研数据和轻量级数据的多变性,对轻量级数据清洗往往采取人工清洗,缺少统一、标准的清洗流程,但对此调研以及轻量级的数额往往是得保证数据稳定性的,因此,在对数据进行清洗时最好有格的洗涤方法。

特色一览

  • 冲 Electron 研发并打包成原生应用,用户体验好;
  • 可视化操作 Excel 数据,支持文件之导入导出;
  • 装有单列运算逻辑、多排运算逻辑与双列范围逻辑三栽筛选方式,并且只是经过“且”、“或”和“编组”的方自由组合。

思路及实现

冲用研组的需,利用 Electron 和 Vue 的表征对拖欠工具进行开发。

技巧选型

  • Electron:桌面端跨平台框架,为 Web
    提供了原生接口的权。打包后的顺序兼容 Windows 7 及以上、Mac、Linux
    的 32 / 64 位系统。详情>>
  • Vue 全家桶:Vue
    拥有多少让视图的特征,适合再数据交互的应用。详情>>
  • js-xlsx:兼容各种电子表格格式的解析器和生成器。纯 JavaScript
    实现,适用于 Node.js 和 Web
    前端。详情>>

心想事成思路

  1. 通过 js-xlsx 将 Excel 文件分析为 JSON 数据
  2. 因筛选标准对 JSON 数据进行筛过滤
  3. 将过滤后底 JSON 数据易成为 js-xlsx 指定的数据结构
  4. 动 js-xlsx 对易后底数生成 Excel 文件

张上得来算觉浅,绝知此事一经躬行

系技术

假如对有起技术比较熟悉,则只是略读/跳了。

Electron

Electron 是什么?

Electron 是一个可以用 JavaScript、HTML 和 CSS
构建桌面应用程序的。这些应用程序能于包及 Mac、Windows 和 Linux
系统上运行,也能够上架到 Mac 和 Windows 的 App Store。

  • JavaScript、HTML 和 CSS 都是 Web
    语言,它们是做网站的如出一辙部分,浏览器(如
    Chrome)懂得怎么用这些代码转为可视化图像。
  • Electron 是一个库房:Electron
    对根代码进行抽象和包,让开发者能够于这之上构建项目。

胡它如此重要?

普通来说,每个操作系统的桌面应用还是因为个别的原生语言进行编辑,这象征要
3 个团队分别吗该行使编写相应版本。而 Electron 则允许你用 Web
语言编写一破即可。

  • 原生(操作系统)语言:用于开发主流操作系统应用之原生语言的对应关系(大多数气象下):Mac
    对承诺 Objective C、Linux 对许 C、Windows 对许 C++。

她由什么做?

Electron 结合了 ChromiumNode.js 和用于调用操作系统本地功能的
API(如打开文件窗口、通知、图标等)。

  • Chromium:Google 创造的一个开源库,并用于 Google 的浏览器
    Chrome。
  • Node.js(Node):一个每当服务器运行 JavaScript
    的运行时(runtime),它具备访问文件系统和网权限(你的微机也可是同样华服务器!)。

澳门新葡亰亚洲在线 1

支出体验如何?

基于 Electron 的付出就像在付出网页,而且能够无缝地 使用
Node
。或者说:在构建一个 Node 应用的同时,通过 HTML 和 CSS
构建界面。另外,你才需要呢一个浏览器(最新的
Chrome
)进行规划(即无需考虑兼容性等)。

  • 使用 Node:这还不是通!除了整体的 Node API,你还得利用托管在
    npm 上过 350,000 个的模块。
  • 一个浏览器:并非有浏览器还提供相同的体制,Web
    设计师以及开发者经常用要只能费还多的生气,让网站于不同浏览器上呈现一样。
  • 最新的 Chrome:可采取过 90% 的 ES2015 特性和另很酷的性状(如
    CSS 变量)。

区区独过程(重点)

Electron
有少数栽进程:『主进程』和『渲染进程』。部分模块只能以两岸有上运行,而有点则无论界定。主进程更多地充当幕后角色,而渲染进程则是应用程序的相继窗口。

流动:可由此任务管理器(PC)/活动监视器(Mac)查看过程的有关消息。

  • 模块:Electron 的 API 是基于它们的用途进行分组。例如:dialog
    模块拥有具备原生 dialog 的 API,如打开文件、保存文件以及警戒等弹窗。

主进程

主进程,通常是一个命名吧 main.js 的公文,该公文是每个 Electron
应用的输入。它决定了应用之生命周期(从打开到关闭)。它既是会调用原生元素,也能够创建新的(多只)渲染进程。另外,Node
API 是放到中的。

  • 调用原生元素:打开 diglog
    和另外操作系统的相互均是资源密集型操作(注:出于安全考虑,渲染进程是免能够直接看当地资源的),因此还待在主进程完成。

澳门新葡亰亚洲在线 2

渲染进程

渲染进程是使之一个浏览器窗口。与主进程不同,它会存多独(注:一个
Electron
应用只能是一个主进程)并且互独立(它吧能是隐藏的)。主窗口一般为命名为
index.html。它们就是比如超人的 HTML 文件,但 Electron 赋予了其完整的
Node API。因此,这吗是它们跟浏览器的分。

  • 互独立:每个渲染进程都是单独的,这象征有渲染进程的崩溃,也不见面影响外渲染进程。
  • 隐藏:可藏窗口,然后于其当偷偷摸摸运行代码()。

澳门新葡亰亚洲在线 3

把它想象成这样

Chrome(或其他浏览器)的每个标签页(tab)及其页面,就吓于 Electron
中之一个独门渲染进程。即使关闭所有标签页,Chrome 依然留存。这好于
Electron 的主进程,能开拓新的窗口或者关闭是利用。

注:在 Chrome
浏览器中,一个标签页(tab)中的页面(即除去浏览器本身有,如搜索框、工具栏等)就是一个渲染进程。

澳门新葡亰亚洲在线 4

交互通讯

出于主进程和渲染进程各自负责不同之任务,而对需要共同完成的职责,它们要彼此通讯。IPC即吧之而异常,它提供了经过之中的报导。但它们只能在主进程与渲染进程中传递信息(即渲染进程中无克展开直接通讯)。

  • IPC:主进程和渲染进程各自有着一个 IPC 模块。

澳门新葡亰亚洲在线 5

集成一句子话

Electron 应用就是比如 Node 应用,它为靠一个 package.json
文件。该文件定义了哪位文件作为主进程,并据此吃 Electron
知道从哪里启动以。然后主进程会创造渲染进程,并会用 IPC
让两岸间进行消息传递。

澳门新葡亰亚洲在线 6

至今,Electron
的基础部分介绍了。该有的是冲笔者之前翻的同样篇稿子《Essential
Electron》,译文可触及击
这里。


Vue 全家桶

欠工具使用了 Vue、Vuex、Vuex-router。在工具基本定型阶段,由 1.x 升级至了
2.x。

怎么选择 Vue

对笔者来说:

  • 简简单单容易用,一般以就待看官方文档。
  • 数据让视图,所以基本不用操作 DOM 了。
  • 框架的存在是以帮忙我们承诺本着复杂度。
  • 全家桶的利益是:对于一般景象,我们便无欲考虑用怎样个库(插件)。

Vue 1.x -> Vue 2.0 的版本迁移用
vue-migration-helper
即可分析有大部分亟待转移的地方。

网上早就生诸多关于 Vue 的课,故在此不再赘述。至此,Vue 部分介绍完。


js-xlsx

该库支持各种电子表格格式的分析和转移。它由 JavaScript 实现,适用于前者和
Node。详情>>

手上支撑读入的格式来(不断更新):

  • Excel 2007+ XML Formats (XLSX/XLSM)
  • Excel 2007+ Binary Format (XLSB)
  • Excel 2003-2004 XML Format (XML “SpreadsheetML”)
  • Excel 97-2004 (XLS BIFF8)
  • Excel 5.0/95 (XLS BIFF5)
  • OpenDocument Spreadsheet (ODS)

支持写起的格式来:

  • XLSX
  • CSV (and general DSV)
  • JSON and JS objects (various styles)

眼前该库提供的 sheet_to_json 方法能够将读入的 Excel 数据转为 JSON
格式。而对于导出操作,我们要呢 js-xlsx 提供指定的 JSON 格式。

再次多关于 Excel 在 JavaScript
中拍卖的学识而查阅凹凸实验室的《Node读写Excel文件探究实践》。但欠文章在个别地处问题(均于
js-xlsx 实战的导出表格部分):

  1. 变化头部时,Excel 的排列信息简单地经过 String.fromCharCode(65+j)
    生成。当排大于 26 时会见油然而生问题。这个问题会见在后边章节中叫起解决方案;
  2. 更换成为 worksheet
    需要的组织处,出现逻辑性错误,并且会招严重的性问题。逻辑问题在斯不讲述,我们看性能问题:
    随着 ECMAScript 的不断更新,JavaScript
    变得进一步强劲和易用。尽管如此,我们要要就『物尽所用』,而未苟『大材小用』,否则可能会见拿走“反效果”。这里导致性问题的亏
    Object.assign()
    方法,该方式可将自由多只来源对象的但枚举属性拷贝至目标靶,并回目标靶。由于拖欠措施本身的实现机制,会于是案例中发生大量之冗余操作。在该案例中,单元格信息是绝无仅有的,所以一直通过
    forEach 为一个空对象赋值即可。提升 N
    倍性能的以,也将逻辑性错误解决了。

原来的:

JavaScript

var result = 某数组.reduce((prev, next) => Object.assign({}, prev,
{[next.position]: {v: next.v}}), {});

1
2
var result = 某数组.reduce((prev, next) => Object.assign({}, prev, {[next.position]: {v: next.v}}), {});
 

改为:

JavaScript

var result = 某数组.forEach((v, i) => data[v.position]= {v: v.v})

1
2
var result = 某数组.forEach((v, i) => data[v.position]= {v: v.v})
 

施行是查验真理的唯一标准

于明亮上述知识后,下面就谈谈在该类型执行着总结出的术、难点和严重性

CSS、JavaScript 和 Electron 相关的知与技能

高亮 table 的列

Excel 单元格采用 table 标签显示。在 Excel
中,被入选的单元格会高亮相应的『行』和『列』,以提醒用户。在拖欠用中也起召开相应的拍卖,横向高亮用
tr:hover 实现,而纵向呢?这里所运用的一个技术是:

倘 HTML 结构如下:

JavaScript

div.container table tr td

1
2
3
4
5
div.container
  table
    tr
      td
 

CSS 代码如下:

JavaScript

.container { overflow:hidden; } td { position: relative; }
td:hover::after { position: absolute; left: 0; right: 0; top: -1单亿px;
// 小目标上,不过大凡负的😭 bottom: -1个亿px; z-index: -1; //
避免遮住自家及同列 td 的情节、border 等 }

1
2
3
4
5
6
7
8
9
10
11
.container { overflow:hidden; }
td { position: relative; }
td:hover::after {
  position: absolute;
  left: 0;
  right: 0;
  top: -1个亿px; // 小目标达成,不过是负的😭
  bottom: -1个亿px;
  z-index: -1; // 避免遮住自身和同列 td 的内容、border 等
}
 

斜分割线

如图:澳门新葡亰亚洲在线 7

分割线可以经 ::after/::before 伪类元素实现平等长长的直线,然后经
transform:rotate();
旋转特定角度实现。但这种实现的一个问题是:由于宽度是勿必然的,因此需要经过
JavaScript 运算才会赢得确切之对角分割线。

故而,这里可以经过 CSS 线性渐变
linear-gradient(to top right, transparent, transparent calc(50% - .5px), #d3d6db calc(50% - .5px), #d3d6db calc(50% + .5px), transparent calc(50% + .5px))
实现。无论宽高如何更换,依然妥妥地于适应。

Excel 的列转换

  • Excel 的排需要用『字母』表示,但非可知简单地通过
    String.fromCharCode()
    实现,因为当过 26 列 时尽管会见发出问题(如:第 27
    列,String.fromCharCode(65+26) 得到的凡 [,而不是
    AA)。因此,这要经过『十进制和 26 进制转换』算法来贯彻。

JavaScript

// 将盛传的本来数易为26进制表示。映射关系:[0-25] -> [A-Z]。
function getCharCol(n) { let temCol = ”, s = ”, m = 0 while (n >=
0) { m = n % 26 + 1 s = String.fromCharCode(m + 64) + s n = (n – m) / 26
} return s }

1
2
3
4
5
6
7
8
9
10
11
12
13
// 将传入的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
function getCharCol(n) {
  let temCol = ”,
    s = ”,
    m = 0
  while (n >= 0) {
    m = n % 26 + 1
    s = String.fromCharCode(m + 64) + s
    n = (n – m) / 26
  }
  return s
}
 

JavaScript

// 将盛传的26进制转换为自然数。映射关系:[A-Z] ->[0-25]。
function getNumCol(s) { if (!s) return 0 let n = 0 for (let i = s.length

  • 1, j = 1; i >= 0; i–, j *= 26) { let c = s[i].toUpperCase() if
    (c < ‘A’ || c > ‘Z’) return 0 n += (c.charCodeAt() – 64) * j }
    return n – 1 }
1
2
3
4
5
6
7
8
9
10
11
12
// 将传入的26进制转换为自然数。映射关系:[A-Z] -&gt;[0-25]。
function getNumCol(s) {
  if (!s) return 0
  let n = 0
  for (let i = s.length – 1, j = 1; i &gt;= 0; i–, j *= 26) {
    let c = s[i].toUpperCase()
    if (c &lt; ‘A’ || c &gt; ‘Z’) return 0
    n += (c.charCodeAt() – 64) * j
  }
  return n – 1
}
 

为 DOM 的 File 对象多了 path 属性

Electron 也 File 对象额外增了 path
属性,该属性可取得文件在文件系统上之实在路径。因此,你可利用 Node
为所欲为。应用场景有:拖拽文件后,通过 Node 提供的 File API
读取文件等。

支撑大的修功能,如粘贴和复制

Electron 应用在 MacOS
中默认不支持『复制』『粘贴』等广泛编辑功能,因此用为 MacOS
显式地设置复制粘贴等编制功能的菜单栏,并为这个设置相应的快捷键。

JavaScript

// darwin 就是 MacOS if (process.platform === ‘darwin’) { var template =
[{ label: ‘FromScratch’, submenu: [{ label: ‘Quit’, accelerator:
‘CmdOrCtrl+Q’, click: function() { app.quit(); } }] }, { label: ‘Edit’,
submenu: [{ label: ‘Undo’, accelerator: ‘CmdOrCtrl+Z’, selector:
‘undo:’ }, { label: ‘Redo’, accelerator: ‘Shift+CmdOrCtrl+Z’, selector:
‘redo:’ }, { type: ‘separator’ }, { label: ‘Cut’, accelerator:
‘CmdOrCtrl+X’, selector: ‘cut:’ }, { label: ‘Copy’, accelerator:
‘CmdOrCtrl+C’, selector: ‘copy:’ }, { label: ‘Paste’, accelerator:
‘CmdOrCtrl+V’, selector: ‘paste:’ }, { label: ‘Select All’, accelerator:
‘CmdOrCtrl+A’, selector: ‘selectAll:’ }] }]; var osxMenu =
menu.buildFromTemplate(template); menu.setApplicationMenu(osxMenu); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// darwin 就是 MacOS
if (process.platform === ‘darwin’) {
    var template = [{
      label: ‘FromScratch’,
      submenu: [{
        label: ‘Quit’,
        accelerator: ‘CmdOrCtrl+Q’,
        click: function() { app.quit(); }
      }]
    }, {
      label: ‘Edit’,
      submenu: [{
        label: ‘Undo’,
        accelerator: ‘CmdOrCtrl+Z’,
        selector: ‘undo:’
      }, {
        label: ‘Redo’,
        accelerator: ‘Shift+CmdOrCtrl+Z’,
        selector: ‘redo:’
      }, {
        type: ‘separator’
      }, {
        label: ‘Cut’,
        accelerator: ‘CmdOrCtrl+X’,
        selector: ‘cut:’
      }, {
        label: ‘Copy’,
        accelerator: ‘CmdOrCtrl+C’,
        selector: ‘copy:’
      }, {
        label: ‘Paste’,
        accelerator: ‘CmdOrCtrl+V’,
        selector: ‘paste:’
      }, {
        label: ‘Select All’,
        accelerator: ‘CmdOrCtrl+A’,
        selector: ‘selectAll:’
      }]
    }];
    var osxMenu = menu.buildFromTemplate(template);
    menu.setApplicationMenu(osxMenu);
}
 

又靠近原生应用

Electron
的一个败笔是:即使你的施用是一个大概的时钟,但它吧不得不包含圆的基础设备(如
Chromium、Node
等)。因此,一般情形下,打包后底程序至少会达到几十兆(根据系统项目进行转变)。当您的动越来越繁杂,就更加可以忽略文件体积问题。

阳,页面的渲染难免会促成『白屏』,而且此以了 Vue
这看似框架,情况就是逾糟糕了。另外,Electron
应用为避免不了『先打开浏览器,再渲染页面』的步骤。下面提供几乎种办法来减轻这种气象,以吃程序还靠近原生应用。

  1. 指定 BrowserWindow 的背景颜色;
  2. 优先躲窗口,直到页面加载后重新显示;
  3. 封存窗口的尺码以及职位,以让程序下次被打开时,依然保存的一样大小以及产出于一如既往的职务上。

对于第一沾,若采用之背景不是纯白(#fff)的,那么可指定窗口的背景颜色和那相同,以避免渲染后底剧变。

JavaScript

mainWindow = new BrowserWindow({ title: ‘XCel’, backgroundColor:
‘#f5f5f5’, };

1
2
3
4
5
mainWindow = new BrowserWindow({
    title: ‘XCel’,
    backgroundColor: ‘#f5f5f5’,
};
 

对此第二点,由于 Electron
本质是一个浏览器,需要加载非网页部分的资源。因此,我们可优先躲窗口。

JavaScript

var mainWindow = new BrowserWindow({ title: ‘ElectronApp’, show: false,
};

1
2
3
4
5
var mainWindow = new BrowserWindow({
    title: ‘ElectronApp’,
    show: false,
};
 

抵交渲染进程始起渲染页面的那么一刻,在 ready-to-show
的回调函数中显窗口。

JavaScript

mainWindow.on(‘ready-to-show’, function() { mainWindow.show();
mainWindow.focus(); });

1
2
3
4
5
mainWindow.on(‘ready-to-show’, function() {
    mainWindow.show();
    mainWindow.focus();
});
 

于第三触及,笔者并没实现,原因如下:

  1. 用户一般是基于这底状对程序的尺码和职务展开调整,即视情况只要得。
  2. 上述是本人个人臆测,主要是本人懒。

那个落实方式,可参考《4 must-know tips for building cross platform
Electron
apps》。

什么样以渲染进程调用原生弹框?

在渲染进程中调用原本专属于主进程面临之 API (如弹框)的艺术发出有限种:

  1. IPC 通讯模块:先以主进程通过 ipcMain 进行监听,然后于渲染进程经过
    ipcRenderer 进行接触;
  2. remote 模块:该模块为渲染进程与主进程之间提供了迅速的报导方式。

对于第二种植办法,在渲染进程中,运行以下代码即可:

JavaScript

const remote = require(‘electron’).remote remote.dialog.showMessageBox({
type: ‘question’, buttons: [‘不报告你’, ‘没有梦想’], defaultId: 0,
title: ‘XCel’, message: ‘你的期是呀?’ }

1
2
3
4
5
6
7
8
9
10
const remote = require(‘electron’).remote
 
remote.dialog.showMessageBox({
  type: ‘question’,
  buttons: [‘不告诉你’, ‘没有梦想’],
  defaultId: 0,
  title: ‘XCel’,
  message: ‘你的梦想是什么?’
}
 

自动更新

若 Electron
应用尚未提供自动更新功能,那么就是象征用户想感受新出的法力还是用上修复
Bug
后底初本子,只能依靠用户自己积极地失去官网下载,这确是坏之经验。Electron
提供的 autoUpdater
模块可实现自动更新功能,该模块提供了第三着框架
Squirrel 的接口,但 Electron 目前仅放了
Squirrel.Mac,且它与
Squirrel.Windows(需要分外引入)的处理方式也非雷同(在客户端和服务器端两地方)。因此只要对拖欠模块不熟悉,处理起来会相对比繁琐。具体可参照笔者之其余一样首译文《Electron
自动更新的整体教程(Windows 和
OSX)》。

当下 Electron 的 autoUpdater 模块不支持 Linux 系统。

此外,XCel 目前并无下 autoUpdater 模块实现自动更新功能,而是以
Electron 的
DownloadItem
模块实现,而服务器端则使用了 Nuts。

呢 Electron 应用生成 Windows 安装包

通过 electron-builder 可直接生成常见的
MacOS 安装包,但其生成的 Windows 的装包却多少发简洁(默认选项项时)。

澳门新葡亰亚洲在线 8
Mac 常见的设置模式,将“左侧的使用图标”拖拽到“右侧的 Applications”即可

透过 electron-builder 生成的 Windows 安装包与我们在 Windows
上广泛的软件设置界面不绝雷同,它从未装向导和点击“下同样步”的按钮,只出一个安时的
gif 动画(默认的 gif 动画而下图,当然你吗可以指定特定的 gif
动画),因此为就算倒闭了用户挑选设置路径等权利。

澳门新葡亰亚洲在线 9
Windows 安装时 默认显示的 gif
动画

若您想啊包装后底 Electron 应用(即透过
electron-packager/electron-builder
生成的,可直接运行的次序目录)生成有点击“下一样步”按钮和而让用户指定安装路径的常见安装包,可以尝试
NSIS 程序,具体而看即篇教程 《[教學]才如10分鐘學會使用 NSIS
包裝您的桌面軟體–安裝程式打包。完全免費。》。

横流:electron-builder
也供了转安装包的布置起,切切实实查看>>。

NSIS(Nullsoft Scriptable Install System)是一个开源之 Windows
系统下安装程序制作程序。它提供了装、卸载、系统装置、文件解压缩等职能。正而该名所描述的那么,NSIS
是透过其的脚本语言来讲述安装程序的一言一行以及逻辑的。NSIS
的脚本语言和科普的编程语言有近似之构造与语法,但她是啊安装程序这类以所设计之。

迄今为止,CSS、JavaScript 和 Electron 相关的知及技巧有阐述了。


性优化

脚谈谈『性能优化』,这有涉嫌到运行效率内存占用量
横流:以下内容均根据 Excel 样例文件(数据量为:1913 行 x 180
列)得出的定论。

施行效率及渲染之优化

Vue 性能真的吓?

Vue 一直自诩着自己性出色,但当数据量上升至早晚量级时(如 1913 x 180 ≈
34 万只数据单元),会面世严重的性能问题(未做相应优化的前提下)。

若是直接通过列表渲染 v-for 渲染数据时,会招程序卡死。
报:通过翻相关资料可得, v-for
在老大渲染时,需要针对每个子项进行初始化(如数据绑定等操作,以便拥有又快的创新速度),这对于数据量较生时,无疑会导致严重的性质问题。

顿时,我想开了个别栽缓解思路:

  1. Vue 是多少让视图的,对数码分段 push,即用一个宏大的职责分割为 N
    份。
  2. 友好并接 HTML 字符串,再经 innerHTML 一次性插入。

终极,我选了次长长的,理由是:

  1. 性最佳,因为每次执行多少过滤时,Vue 都要开展 diff,性能不优秀。
  2. 更切合当下运之需:纯展示且不论需动画过渡等。
  3. 落实再次简单

用原先繁重的 DOM 操作(Vue)转换为 JavaScript
的拼接字符串后,性能得到了异常特别升级(不见面导致程序卡死要渲染不产生视图)。这种优化措施难道不就是
Vue、React
等框架解决之题材之一为?只不过框架考虑的面貌再广泛,有些地方要我们友好因实际情况进行优化而已。

在浏览器中,JavaScript 的演算在现世底发动机中非常抢,但 DOM
本身是那个慢的东西。当你调用原生 DOM API 的时光,浏览器需要以
JavaScript 引擎的语境下接触原生的 DOM
的兑现,这个历程有一定之性质损耗。所以,本质的勘察是,要拿吃时间之操作尽量在纯粹的计算中失举行,保证最后计算出来的待实际点实际
DOM 的操作是无比少之。 —— 《Vue
2.0——渐进式前端解决方案》

自,由于 JavaScript
天生单线程,即使实行数速度再快,也在所难免会造成页面有浅之时间不容用户的输入。此时可是经过
Web Worker 或其它措施化解,这也以凡咱们继承讲到之题材。

也生网友提供了优化大量列表的法门:https://clusterize.js.org/。但于本案例中笔者并无行使这办法。

强大的 GPU 加速

将拼接的字符串插入 DOM
后,出现了另外一个问题:滚动会十分卡。猜想马上是渲染问题,毕竟 34
万个单元格同时设有让界面被。

添加 transform: translate3d(0, 0, 0) / translateZ(0) 属性启动 GPU
渲染,即可解决之渲染性能问题。再次感叹该属性的强大。

后来,考虑到用户并不需要查看所有数据,只需要出示部分数据被用户展开参考即可。我们针对之单渲染前
30/50 行数据。这样即可提升用户体验,也能够益优化性能。

记得关闭 Vuex 的从严模式

除此以外,由于自己学艺不精和粗率,忘记在生育环境关闭 Vuex
的『严格模式』。

Vuex 的严酷模式一旦以生条件中关闭,否则会指向 state 树进行一个深观察
(deep
watch),产生不必要之习性损耗。也许在数据量少时,不见面专注到此题材。

复原当时底场面:导入 Excel 数据后,再进行交互(涉及 Vuex
的读写操作),需要相当几乎秒才见面应,而直接通过纯 DOM
监听的轩然大波则不管此题材。由此,判断出是 Vuex 问题。

JavaScript

const store = new Vuex.Store({ // … strict: process.env.NODE_ENV !==
‘production’ })

1
2
3
4
5
const store = new Vuex.Store({
  // …
  strict: process.env.NODE_ENV !== ‘production’
})
 

多进程!!!

面前说道,JavaScript
天生单线程,即使再快,对于数据量较充分时,也会产出拒绝响应的题目。因此用
Web Worker 或类似的方案去化解。

每当这里自己不选择 Web worker 的原委发生如下几碰:

  1. 发生外更好之代表方案:一个主进程能创建多单渲染进程,通过 IPC
    即可开展数量交互;
  2. Electron 不支持 Web
    Worker!(当然,可能会见在新本子支持,最新信息请关注官方)

Electron 作者在 2014.11.7 在《state of web worker support?》 issue
中恢复了以下就同样段:

Node integration doesn’t work in web workers, and there is no plan to
do. Workers in Chromium are implemented by starting a new thread, and
Node is not thread safe. Back in past we had tried to add node
integration to web workers in Atom, but it crashed too easily so we
gave up on it.

因而,我们最后用了创造一个初的渲染进程 background process
进行处理数据。由 Electron 章节可知,每个 Electron
渲染进程是独的,因此它们不见面互相影响。但这吗带动了一个题材:它们不克互相通讯?

错!下面来 3 栽方法进行报道:

  1. Storage
    API:对某标签页的
    localStorage/sessionStorage 对象进行增删改时,其他标签页能由此
    window.storage 事件监听到。
  2. IndexedDB:IndexedDB
    是一个为能够在客户端存储可观数额之结构化数据,并且以这些数据及以索引进行大性能检索的
    API。
  3. 透过主进程作为中转站:设主界面的渲染进程是 A,background process
    是 B,那么 A 先将 Excel 数据传递到主进程,然后主进程再倒车到 B。B
    处理完毕晚更原路回,具体要下图。当然,也可以将数据存储于主进程中,然后以多单渲染进程被采取
    remote 模块来走访它。

该工具采用了第三栽方式的第一栽状况:
澳门新葡亰亚洲在线 10

1、主页面渲染进程 A 的代码如下:

JavaScript

//① ipcRenderer.send(‘filter-start’, { filterTagList:
this.filterTagList, filterWay: this.filterWay, curActiveSheetName:
this.activeSheet.name }) // ⑥ 在某处接收 filter-response 事件
ipcRenderer.on(“filter-response”, (arg) => { // 得到处理数据 })

1
2
3
4
5
6
7
8
9
10
11
12
//①
ipcRenderer.send(‘filter-start’, {
    filterTagList: this.filterTagList,
    filterWay: this.filterWay,
    curActiveSheetName: this.activeSheet.name
})
 
// ⑥ 在某处接收 filter-response 事件
ipcRenderer.on("filter-response", (arg) =&gt; {
    // 得到处理数据
})
 

2、作为中转站的主进程的代码如下:

JavaScript

//② ipcMain.on(“filter-start”, (event, arg) => { // webContents
用于渲染和控制 web page
backgroundWindow.webContents.send(“filter-start”, arg) }) // ⑤
用于收纳返回事件 ipcMain.on(“filter-response”, (event, arg) => {
mainWindow.webContents.send(“filter-response”, arg) })

1
2
3
4
5
6
7
8
9
10
11
//②
ipcMain.on("filter-start", (event, arg) =&gt; {
    // webContents 用于渲染和控制 web page
    backgroundWindow.webContents.send("filter-start", arg)
})
 
// ⑤ 用于接收返回事件
ipcMain.on("filter-response", (event, arg) =&gt; {
    mainWindow.webContents.send("filter-response", arg)
})
 

3、处理繁重数据的 background process 渲染进程 B 的代码如下:

JavaScript

// ③ ipcRenderer.on(‘filter-start’, (event, arg) => { // 进行演算 …
// ④ 运算完毕后,再经 IPC 原路返回。主进程和渲染进程 A
也要建立相应的监听事件 ipcRenderer.send(‘filter-response’, { filRow:
tempFilRow }) })

1
2
3
4
5
6
7
8
9
10
11
// ③
ipcRenderer.on(‘filter-start’, (event, arg) =&gt; {
    // 进行运算
    …
 
    // ④ 运算完毕后,再通过 IPC 原路返回。主进程和渲染进程 A 也要建立相应的监听事件
    ipcRenderer.send(‘filter-response’, {
        filRow: tempFilRow
    })
})
 

由来,我们以『读取文件』、『过滤数据』和『导出文件』三怪耗时的多寡操作都易至了
background process 中处理。

这边,我们只是开创了一个
background process,如果想使开得重绝,我们得新建『CPU 线程数- 1 』
个的 background process
同时针对数码进行处理,然后在主进程对处理后数进行拼接,最后再次用拼接后底数返回到主页面的渲染进程。这样就算可尽管榨干
CPU 了。当然,在这个笔者非见面进行这个优化。

绝不以优化而优化,否则得不偿失。 —— 某网友

内存占有量过死

解决了执行效率与渲染问题后,发现为有内存占用量过十分之题材。当时蒙是以下几单因:

  1. 其三老耗时操作均放置在 background process
    处理。在简报传递数据的历程被,由于匪是共享内存(因为 IPC 是根据
    Socket
    的),导致出现多卖数据副本(在形容就首文章时才出矣即相对方便的答案)。
  2. Vuex
    是因一个大局单例的模式开展保管,但她会是休是指向数据做了少数封装,而致性的损耗呢?
  3. 由于 JavaScript
    目前勿持有积极回收资源的力量,所以只能积极对闲置对象设置也
    null,然后等待 GC 回收。

由 Chromium 采用多进程架构,因此会面涉嫌到过程之中通信问题。Browser
进程在开行 Render 进程的过程被见面成立一个坐 UNIX Socket 为底蕴之 IPC
通道。有了 IPC 通道之后,接下 Browser 进程同 Render
进程就盖信息的款型开展通信。我们将这种信息称 IPC
消息,以分别为线程消息循环中之音讯。
——《Chromium的IPC消息发送、接收及分发机制分析》

概念:为了好掌握,以下『Excel 数据』均指 Excel 的通中单元格转为
JSON 格式后底数码。

无限容易处理的的确是第三碰,手动将不再需要的变量及时安装为
null,但效果并无醒目。

后来,通过操作系统的『活动监视器』(Windows
上是职责管理器)对拖欠工具的各国级(打开时、导入文本时、筛选时跟导出时)进行简易的内存分析,得到以下报告:

—————- S:报告分割线 —————-
经观察,主要耗内存的是页面渲染进程。下面通过截图证明:
PID 15243 是主进程
PID 15246 是页面渲染进程
PID 15248 是 background 渲染进程

a、首次等启动程序时(第 4 行是主进程;第 1 行是页面渲染进程;第 3 行是
background 渲染进程 )

澳门新葡亰亚洲在线 11

b、导入文本(第 5 行是主进程;第 2 行是页面渲染进程;第 4 行是
background 渲染进程 )
澳门新葡亰亚洲在线 12

c、筛选数据(第 4 行是主进程;第 1 行是页面渲染进程;第 3 行是
background 渲染进程 )
澳门新葡亰亚洲在线 13

出于 JavaScript 目前非拥有积极回收资源的效应,所以不得不积极将目标设置也
null,然后等待 GC 回收。

故而,经过一段时间等待后,内存占用如下:
d、一段时间后(第 4 行是主进程;第 1 行是页面渲染进程;第 3 行是
background 渲染进程 )
澳门新葡亰亚洲在线 14

由于上述可得,页面渲染进程由于页面元素以及 Vue 等 UI
相关资源是固定的,占用内存较充分还不可知回收。主进程占用资源也非能够得那个好放,暂时无理解原委,而
background 渲染进程则比好地释放资源。

—————- E:报告分割线 —————-

冲报告,初步得出的下结论是 Vue 和报道时占用资源比较充分。

因拖欠工具的骨子里运用场景:Excel
数据仅于『导入』和『过滤后』两独号要出示,而且显示的凡由此
JavaScript 拼接的 HTML 字符串所结合的 DOM 而已。因此用表格数据放置在
Vuex 中,有接触滥用资源的疑心。

另外,在 background process 中也闹满腔来同一卖 Excel
数据副本。因此,索性就以 background process 存储一份 Excel
数据,然后以数据变动时,通过 IPC 让 background process 返回拼接好的
HTML
字符串即可。这样一来,内存占有量立刻下跌多。另外,这为是一个一举多得之优化:

  1. 字符串拼接操作为易至了
    background process,页面渲染进程进一步压缩耗时的操作;
  2. 内存占有量大大削弱多少,响应速度也获取了提升。

骨子里,这为产生接触像 Vuex 的『全局单例模式管理』,一客数据就哼。

理所当然,对于 Excel 的为主信息,如行列数、SheetName、标题组等全仍保留于
Vuex。

优化后底内存占有量如下图。与上述报告的老三摆图相比(同一等级),内存占有量下降了
44.419%: 澳门新葡亰亚洲在线 15
除此以外,对于不需要应的多少,可经过 Object.freeze()
冻结起来。这也是一律栽优化手段。但欠工具目前连从未用至。

至今,优化部分也论述了了!


欠工具目前凡开源的,欢迎大家利用或引进给用研组等发生得的食指。

你们的反馈(可领取交 issues /
pull
request)能叫这家伙在采用及功能上不断完善。

最后,感谢 LV
在活设计、界面设计和优化及的武力支持。全文了!

打赏支持自勾勒来更多好章,谢谢!

打赏作者

打赏支持我形容来双重多好章,谢谢!

任选一种植出方式

澳门新葡亰亚洲在线 16
澳门新葡亰亚洲在线 17

1 赞 2 收藏
评论

有关作者:刘健超-J.c

澳门新葡亰亚洲在线 18

前端,在路上…http://jchehe.github.io
个人主页 ·
我的文章 ·
19 ·
    

澳门新葡亰亚洲在线 19

相关文章