电视直播工具推荐

https://github.com/andandroidor/ourtv

June 29, 2024 · 1 min · word · 水华

前端和excel的那些事

在开发需求中,经常会遇到需要和excel相关的需求,毕竟不是所有人都是程序员,很多的业务都是通过excel去进行数据的整理归类计算的,excel中提供的一系列快捷功能,统计功能也非常的实用,但是这也就造成了除了和接口打交道,前端也需要和excel打一下交道 excel 是什么 excel是微软出的一款电子表格软件,wps是国内知名的免费办公软件,以及苹果的Numbers同样都支持编辑和生成excel文件 excel 的格式 这里说的不是单纯的excel而是平时前端开发的时候所使用到的**excel类型**的文件格式,主要有 csv csv 是一种纯文本的格式,非常的简单,每一行代表一行,没一列通过,进行分割,我们只需要通过split函数就能直接分割成对应的二维数组结构 xsls/xls 区别在于 xls类型的文件我们可以通过存储网页的形式存储下来,xsls就是一个纯的二进制文件了,这一类更倾向于使用类库进行操作 读取 如果是csv,最简单的情况下,就直接使用<input type="file">,只有用fileReader读取为纯文本就行了 nodejs和browser唯一的区别就在于,node还支持直接通过steam等概念进行输入,而browser只有arrayBuffer这一种手段 在一般情况下,直接fileReader读取excel都会是二进制流,不过根据其编码规范是可以进行还原的,其中的对应关系比较负责 常用的库 库的左右就在于,他们能将excel的文件专为对应的js对象供我们操作 sheet.js 社区开源版本的xlsx.js就可以完成读取和写入的工作了, 以下是 sheet.js 的对应数据结构. 读取也狠方便 XLSX.read(buffer, { type: "buffer" }); 不过官方的文档相对还是比较难以理解的,一般日常我用另外一个库 exceljs js-xlsx 的 思想构成也是通过将二进制流转为js对象的方式方便我们操作,不过 api 方面设计的更加友好一点 最主要的两点。 中文文档 demo 易懂 读取也很容易,通过fileReader.readAsArrayBuffer 就能直接读取,如果是在node环境下,更能直接通过steam和file接口直接获取数据 // load from buffer var workbook = new Excel.Workbook(); workbook.xlsx.load(data) .then(function() { // use workbook }); 写入 原生 js 这个只适用于 js xls 2013 之前的xls模式是可以将一个html文件导出成一个.xls文件的所以我们首先定义一个html <table id="tblData"> <tr> <th>Name</th> <th>Email</th> <th>Country</th> </tr> <tr> <td>John Doe</td> <td>john@gmail.com</td> <td>USA</td> </tr> <tr> <td>Michael Addison</td> <td>michael@gmail.com</td> <td>UK</td> </tr> <tr> <td>Sam Farmer</td> <td>sam@gmail.com</td> <td>France</td> </tr> </table> 接着获取html之后导出 ...

February 14, 2020 · 1 min · 212 words · 水华

一次node内存泄漏排查和解决

背景 公司需要对接各种渠道,进行渠道管理进行了统一规范,生成了 ChannelManager 这个类,上线后发现一直报警,内存居高不下,而且走势呈阶梯上升,判断发生了内存泄漏 技术栈 Nuxt 基于 nuxt 和 vue 开发的一套前端代码 nodejs 性能平台 alinode,一个 ali 官方出的用来监控整个 node 内存和机器运行情况的程序,非常好用,问题是数据有一定延时 解决的步骤 首先尝试临时解决问题 因为线上一共有四台机器跑 ssr,所以通过设置不同的 crontab 进行分批重启 pm2,使得服务不间断 下线问题的 feture 最近上线的 feture 只有 channelManager,于是回滚代码之后重新发布,发现问题解决,找到问题代码区域 CodeReview 开会大家回顾整个问题代码,分析之后发现可能的问题在于使用了 global 的 mixin,改成 Vue plugin 的形式使用,具体可以参考这个 issue 测试环境下发现问题依旧没有解决 验尸 对比了最近几次 alinode 抓下的堆快照,发现所有的闭包都是 vue 实例,而且都会有一个同样的 key$channelManager 找出问题所在 最终发现是上 channelManager 的时候在 nuxt 的 plugin 中使用了 inject,因为 inject 的时候是同一个实例,本身的目的是可以获取 channel 列表 module.exports = (ctx, inject) => { const ChannelManager = require('ChannelManager') inject('channelManager', ChannelManager) } 原因 在于 v8 的整个 gc 机制在于是否能够被访问到,因为 inject 之后不知道为何从 channelManager 能够访问到所有 inject 之后的 vue 实例,所以这一系列的 vue 对象都不可被回收 ...

June 1, 2019 · 1 min · 90 words · 水华

electron开机自动启动

直接 直接上 直接上代码 const exeName = path.basename(process.execPath) app.setLoginItemSettings({ openAtLogin: !openAtLogin, path: process.execPath, args: [ '--processStart', `"${exeName}"` ] }) }

February 11, 2019 · 1 min · 19 words · 水华

我们是怎么从ng迁移到vue的

我们是如何从ng1迁移ing到vue的 原本的技术栈 ng1 + gulp + slim + vue *2 + iframe 的一个后端管理项目 这是一个本身因为人手不足,一开始由后端同学创建的后端管理项目,基本采用了gulp + ng1来进行开发,同时前端接手之后为了方便开发以及跟上潮流,采用了新开子目录使用vue开发,nginx和iframe进行整合的方式,最后一个项目变成了三个项目,其实最开始进行开发的时候,连怎么启动都不知道😂 要解决的问题 项目的层级结构 原本的结构 顶级目录只包含多个子文件夹以及build.sh,每个子项目需要独立进行编译以及开发 新的结构 采用signle-spa作为入口文件解决方案,统一管理所有项目的入口文件,实现一次启动,所有项目都能一起开发以及编译,省去了来回切换以及端口冲突 构建语言的混乱 原本的架构 原本的app是使用ng1来进行编写js部分,slim来编写页面模版,同时使用gulp来完成遍历所有的js文件,并打包到一个js中,后来一些新的页面部分采用iframe引入另一个vue-cli项目,两者之间通过cookie来进行登录数据的共享。 更新之后的架构 因为模版文件的问题,仍然以gulp为主,webpack负责vue和原本app的js打包和资源文件的编译工作,大家约定好,原本的ng部分尽量不更新,新的采用vue进行编写 逐步过渡 原本的方案 老的不管它,需要更新就回去更新,新的需求去vue的项目中编写 现在的方案 single-spa进行页面的拆分,将需要更新的老的ng部分作为一个新的子app,拆分出来之后再进行更新,保证局部更新,不影响整体 解决过程 编译工具 确定了整体的迁移方案之后,就是首先对编译工具的改造了,最开始是想把gulp先替换成webpack的(因为习惯配置webpack了,以及webpack4 + babel7真的编译速度快了很多) 但是因为slim始终找不到适合使用的webpack插件的关系,最终决定还是保留gulp进行编译ng的相关的html文件 小问题 gulp支持webpack的问题 gulp-webpack插件支持的webpack版本是2,但是目标是使用4(为了快),好在webpack支持使用node来进行调用,只要在编译结束之后给gulp一个回调就可以了 const webpack = require('webpack') const fs = require('fs') module.exports = function (webpackConfig) { return new Promise((resolve, reject) => { const compiler = webpack(webpackConfig); compiler.run((err, stats) => { if (err) { console.error(err) reject(err) } // 输出 process.stdout.write(stats.toString({ // stats对象中保存着编译过程中的各种消息 colors: true, // 增加控制台颜色开关 modules: false, // 不增加内置模块信息 children: false, // 不增加子级信息 chunks: false, // 允许较少的输出 chunkModules: false // 不将内置模块的信息加到包信息 }) + '\n\n') }) compiler.hooks.afterEmit.tap('gulp', function() { resolve() }) }) } 同理,devServer也使用自定义的脚本, 当然因为公司原因,其中的api切换也直接放在devServer的before中 ...

January 3, 2019 · 2 min · 326 words · 水华