时间日期相关
moment
时间相关处理,moment的参数可以是时间戳或者字符串的时间格式或者moment对象格式;moment的参数如果是不规则的格式(null)转为Invalid date的字符串,应注意使用。
- 格式化时间
// 以YYYY年MM月DD日形式显示当前时间
moment().format("YYYY年MM月DD日")
// 201903
moment().format("YYYYMM")
// 时间戳格式化
moment(45444545454).format("YYYY-MM-DD HH:mm:ss")
- 某一时间的前一段时间
// 现在的时间减去一天
moment().subtract(1, 'days').format("YYYYMM")
- 获取时间戳
moment().valueOf(); // 当前时间的时间戳
moment(time).valueOf(); // 指定时间的时间戳
moment().endOf('day').valueOf() // 一天时间的最后值 (注意日期区间选择器选择同一天的时候)
moment().startOf('day').valueOf() // 一天时间的最早值 (默认)
- 精确到小时等单位来操作时间
moment(moment().format("YYYY-MM-DD HH")).valueOf(); // 当前时间精确到小时的时间戳
solarLunar
农历公历转化
import solarLunar from 'solarLunar';
// 输入的日历为公历
const solar2LunarDate = solarLunar.solar2Lunar(2019,1,12)
// 输入的日历为农历
const lunar2SolarDate = solarLunar.lunar2Solar(2019,1,12)
React
react-beautiful-dnd
拖拽组件,拖拽之后的顺序是要人为的修改数据的排序的,组件内部不会去自动排序
// onDragEnd是记录拖拽的信息(拖拽的位置以及拖拽完的位置) destination 的index代表拖拽完后的位置的index source的index代表拖拽前的index
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable">
{provided => (
<div ref={provided.innerRef}>
{[1, 2, 3].map(
(item, index) => (
<Draggable
key={index}
draggableId={index}
index={index} // 最好使用index因为用来表示当前区块的顺序
>
{providedDraggable => (
<div
ref={providedDraggable.innerRef}
{...providedDraggable.draggableProps}
{...providedDraggable.dragHandleProps}
>
<div>{item}</div>
</div>
)}
</Draggable>
)
)}
</div>
)}
</Droppable>
</DragDropContext>
- 可拖放的组件可以通过Draggable包裹,Draggable必须包含在Droppable中
- Droppable的常用属性 (还是代表拖拽的整体)
- direction 可拖拽的方向 vertical (default) and horizontal.
- isDropDisabled 是否允许拖拽设置为true之后,仍然会有一定的拖拽效果,比如小手的手势等,同时设置isDragDisabled之后即可
- Draggable常用属性 (单个拖拽区块)
- isDragDisabled 表示当前的区块是否可以被拖拽
- index 用来在拖拽方法中记录拖拽元素的起始位置
react-infinite-scroller 无限加载
当遇到那种搜索条件改变之后,需要重新从pageNum为1时开始的时候,此时InfiniteScroll会记录原来的loadMore中的pageNum的数值会有问题,如果改为受控时会有连续请求的情况(暂时加debounce解决)
- pageStart代表分页是从第几页开始的(一般为0或1)
- useWindow 是否使用window的滚动,false的时候需要使外层的容器有overflow效果才可以加载
- loadMore 滚动加载的事件
- hasMore 是否显示加载更多 (根据当前的数据总数和所有的数据总数比较)
- loader 加载更多的内容
- children的内容是一个数组,循环出来的dom结构
- loadMore={loading ? null : this.loadMoreList}
classnames
复杂的判断条件生成对应样式类名。
react-loadable
路由按需加载
JS
html2canvas
将html内容写入canvas生成图片
- options
- ignoreElements 可以在生成图片时忽略某些元素,值为一个函数 ignoreElements: ele => ele.className === 'anyclass', 返回true的元素隐藏,否则正常显示。
- windowWidth、windowHeight 可以影响需要生成图片的DOM的宽高。
- 由于某些样式在生成图片时会有问题,所以可以生成去除某些样式的图片。
复制要生成图片的dom并修改样式,新的dom插入到页面中(必须插入到页面中,可以通过定位实现无感知插入),并对新插入的dom作为数据源进行生成图片,导出之后再移除复制的dom即可,不改变默认展示dom。
const parentDom = document.getElementById('parent');
const prevDom = document.getElementById('prevDom');
// clone 原始dom
const cloneDom = prevDom.cloneNode(true);
// 对新的dom进行样式修改,使用定位实现无感知插入
cloneDom.style.position = 'absolute';
cloneDom.style.width = '100%';
cloneDom.style.left = `-${window.screen.width}px`;
cloneDom.style.bottom = `${prevDom.offsetHeight + 200}px`;
// ... 进行需要额外处理的操作
parentDom.appendChild(cloneDom); // 在父元素下插入新的dom
// 生成图片并移除新插入的dom
html2canvas(cloneDom, {
logging: false,
ignoreElements: ele => ele.className === 'anyclass',
}).then(canvas => {
...
parentDom.removeChild(cloneDom);
});
highlight
highlight.js使代码区块高亮的插件(可以将主题的代码下载下来,在指定渲染代码的地方使用下载的对应主题的css即可)。
QRCanvas
基于canvas的二维码生成库。
JSON对比
react-diff-viewer
json对比显示组件 npm install react-diff-viewer --save
- json的key值的顺序不同导致比较的差异也不同,需要将前后两次数据key值对齐
- 前后比较的value需要是json字符串
- splitView 为true时表示左右拆分显示
- showDiffOnly 默认为true,表示没有差异时会收起json内容,设置为true表示json内容一直显示
- leftTitle、rightTitle 表示左右拆分时的标题
- json数据value值很长时换行显示
// 组件容器外层类名
.codeDiffBox {
table {
pre {
word-break: break-all;
}
}
}
jsondiffpatch
json对比获取详细数据差异 npm install jsondiffpatch --save
const jsondiffpatch = require('jsondiffpatch').create({});
// 是否有差异
const hasDiff = Boolean(jsondiffpatch?.diff(oldValue, newValue));
markdown
doctoc
为markdown文件生成目录, 最上方规定目录生成的位置。读取markdown文件之后去除第一个dom节点(即目录)用于文档的展示,第一个dom节点即是生成的目录。
- 确定生成目录的位置
// 用于确定生成的目录的位置在最上方
<!-- START doctoc -->
<!-- END doctoc -->
// 此空行不可缺少
- 在指定的文件生成目录
// 生成对应目录
npm install doctoc -g
doctoc filename.md
- node脚本简化流程
const fs = require('fs');
var exec = require('child_process').exec;
const data = fs.readFileSync('./toc.md', 'utf8');
// 没有以指定形式开始的时候在文件头部写入指定内容
if(!data.startsWith('<!-- START doctoc')) {
const newData = `<!-- START doctoc -->
<!-- END doctoc -->
${data}`
fs.writeFileSync('./toc.md', newData, 'utf8');
exec('doctoc ./toc.md');
}
doctoc-generator
生成目录的结构化数据
showdown
npm install showdown --save
import showdown from 'showdown';
let converter = new showdown.Converter();
// 解析完为html字符串,使用dangerouslySetInnerHTML插入到标签
<div dangerouslySetInnerHTML = {{ __html: converter.makeHtml('## title') }}></div>
表格相关
xlsx
在线的Excel控件spreadjs
node
node-schedule
使用
npm install node-schedule
启动一个定时
const schedule = require('node-schedule');
const flag = schedule.scheduleJob('30 * * * * *', () => {
console.log('定时开始了');
});
取消一个定时
const schedule = require('node-schedule');
const flag = schedule.scheduleJob('30 * * * * *', () => {
console.log('定时开始了');
});
flag.cancel();
cron
6个占位符从左到右分别代表:秒、分、时、日、月、周几
*表示通配符,匹配任意,当秒是*时,表示任意秒数都触发,其它类推
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, OPTIONAL)
每分钟的第30秒触发:30 * * * * *
每小时的1分30秒触发:30 1 * * * *
每天的凌晨1点1分30秒触发:30 1 1 * * *
每月的1日1点1分30秒触发:30 1 1 1 * *
2016年的1月1日1点1分30秒触发:30 1 1 1 2016 *
每周1的1点1分30秒触发:30 1 1 * * 1
sqlite3
嵌入式数据库 npm install sqlite3
通用方法封装
/**
* sqlite相关操作方法
*/
'use strict';
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
const DB = {};
DB.SqliteDB = function(file) {
DB.db = new sqlite3.Database(file);
DB.exist = fs.existsSync(file);
if (!DB.exist) {
fs.openSync(file, 'w');
}
};
// 建表
DB.SqliteDB.prototype.createTable = function(sql) {
return new Promise(resolve => {
DB.db.serialize(function() {
DB.db.run(sql, err => {
if (err === null) {
resolve(true);
} else {
resolve(false);
}
});
});
});
};
// 查询数据
DB.SqliteDB.prototype.queryData = function(sql) {
return new Promise(resolve => {
DB.db.all(sql, (err, rows) => {
if (err === null) {
resolve(rows);
} else {
resolve([]);
}
});
});
};
// 执行sql语句
DB.SqliteDB.prototype.executeSql = function(sql) {
return new Promise(resolve => {
DB.db.run(sql, err => {
if (err === null) {
resolve(true);
} else {
resolve(false);
}
});
});
};
// 关闭数据库连接
DB.SqliteDB.prototype.close = function() {
DB.db.close();
};
exports.SqliteDB = DB.SqliteDB;
exports.DB = DB;
使用
const sqlite = require('../utils/sqlite.js').SqliteDB;
const file = 'student.db';
const sqliteDB = new sqlite(file);
// 建表
const createTableSql = `CREATE TABLE IF NOT EXISTS student (
id INTEGER PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL,
class VARCHAR(100) NOT NULL)`;
await sqliteDB.createTable(createTableSql);
// 查询数据
const queryStudentSql = 'select * from student';
const res = await sqliteDB.queryData(queryStudentSql);
// 执行sql
const deleteStudentSql = `delete from student where id = ${studentId}`;
const res = await sqliteDB.executeSql(deleteStudentSql);
web安全
DOMPurify
DOMPurify是一个开源的基于DOM的快速XSS净化工具
import purify from "dompurify";
<div dangerouslySetInnerHTML={{ __html: purify.sanitize(data) }} />