常用类库的使用记录

1,290 阅读5分钟

时间日期相关

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的常用属性 (还是代表拖拽的整体)
    1. direction 可拖拽的方向 vertical (default) and horizontal.
    2. isDropDisabled 是否允许拖拽设置为true之后,仍然会有一定的拖拽效果,比如小手的手势等,同时设置isDragDisabled之后即可
  • Draggable常用属性 (单个拖拽区块)
    1. isDragDisabled 表示当前的区块是否可以被拖拽
    2. index 用来在拖拽方法中记录拖拽元素的起始位置

react-infinite-scroller 无限加载

当遇到那种搜索条件改变之后,需要重新从pageNum为1时开始的时候,此时InfiniteScroll会记录原来的loadMore中的pageNum的数值会有问题,如果改为受控时会有连续请求的情况(暂时加debounce解决)

  1. pageStart代表分页是从第几页开始的(一般为0或1)
  2. useWindow 是否使用window的滚动,false的时候需要使外层的容器有overflow效果才可以加载
  3. loadMore 滚动加载的事件
  4. hasMore 是否显示加载更多 (根据当前的数据总数和所有的数据总数比较)
  5. loader 加载更多的内容
  6. children的内容是一个数组,循环出来的dom结构
  7. loadMore={loading ? null : this.loadMoreList}

classnames

复杂的判断条件生成对应样式类名。

react-loadable

路由按需加载

JS

html2canvas

将html内容写入canvas生成图片

  • options
    1. ignoreElements 可以在生成图片时忽略某些元素,值为一个函数 ignoreElements: ele => ele.className === 'anyclass', 返回true的元素隐藏,否则正常显示。
    2. 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

www.grapecity.com.cn/developer/s…

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 * * * * *
每小时的130秒触发:30 1 * * * *
每天的凌晨1130秒触发:30 1 1 * * *
每月的11130秒触发:30 1 1 1 * *
2016年的111130秒触发:30 1 1 1 2016 *
每周11130秒触发: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) }} />