Skip to content

常用工具库详解 ​

dayjs ​

推荐使用 dayjs,和 moment 用法一致,但打包更小(moment 打包之后 200k,dayjs 打包之后 2k)

官方网站:dayjs 中文教程

安装:npm i dayjs

获取 & 设置 ​

单位全拼说明
年yeary
月monthM(一月 0,十二月 11)
日dateD
星期dayd(星期天 0,星期六 6)
时hourh
分minutem
秒seconds
毫秒millisecondms

示例:

  • 获取年:dayjs().year() 或 dayjs().get('year')
  • 设置年:dayjs().year(2000) 或 dayjs().set('year', 2000)

操作 ​

js
// 格式化
dayjs().format('YYYY-MM-DD hh:mm:ss A') // 2021-01-10 04:39:28 PM

// 获取一月初
dayjs().startOf('month')

// 获取一年年末
dayjs().endOf('year')

// 增加7天
dayjs().add(7, 'days')

// 减少7天
dayjs().subtract(7, 'days')

// 上个月
dayjs().subtract(1, 'months')
// 格式化
dayjs().format('YYYY-MM-DD hh:mm:ss A') // 2021-01-10 04:39:28 PM

// 获取一月初
dayjs().startOf('month')

// 获取一年年末
dayjs().endOf('year')

// 增加7天
dayjs().add(7, 'days')

// 减少7天
dayjs().subtract(7, 'days')

// 上个月
dayjs().subtract(1, 'months')

startOf / endOf 支持的单位:year(y)、quarter(Q)、month(M)、week(w)、date(D)、day(d)、hour(h)、minute(m)、second(s)

查询 ​

js
dayjs('2010-10-20').isBefore('2010-10-21') // true
dayjs('2010-10-20').isAfter('2010-10-21')  // false
dayjs('2010-10-20').isBefore('2010-10-21') // true
dayjs('2010-10-20').isAfter('2010-10-21')  // false

闰年判断需要插件:

js
var isLeapYear = require('dayjs/plugin/isLeapYear')
dayjs.extend(isLeapYear)
dayjs().isLeapYear()
var isLeapYear = require('dayjs/plugin/isLeapYear')
dayjs.extend(isLeapYear)
dayjs().isLeapYear()

返回月份的天数:dayjs().daysInMonth()

格式化 ​

js
dayjs().format('YYYY-MM-DD hh:mm:ss') // 2020-05-02 10:30:00
dayjs().format('YYYY-MM-DD hh:mm:ss') // 2020-05-02 10:30:00
占位符输出详情
YY18两位数年份
YYYY2018四位数年份
M1-12月份
MM01-12月份,两位数
MMMJan-Dec缩写月份名称
MMMMJanuary-December完整月份名称
D1-31月份里的一天
DD01-31两位数
d0-6星期天是 0
H0-23小时,24 小时制
HH00-23小时,两位数
h1-12小时,12 小时制
hh01-12两位数
m0-59分钟
mm00-59两位数
s0-59秒
ss00-59两位数
SSS000-999毫秒
AAM PM
aam pm

时长 duration ​

需要引入插件:

js
import duration from 'dayjs/plugin/duration'
dayjs.extend(duration)

// 获取秒,传入时间戳
dayjs.duration(1500).seconds() // 1
import duration from 'dayjs/plugin/duration'
dayjs.extend(duration)

// 获取秒,传入时间戳
dayjs.duration(1500).seconds() // 1

Moment.js ​

Moment.js 是一个用于解析、验证、操作和显示日期和时间的 JavaScript 库

安装:npm install moment

创建日期 ​

js
const now = moment()
const specificDate = moment('2024-12-31')
const ymdDate = moment({ year: 2024, month: 11, day: 31 })
const now = moment()
const specificDate = moment('2024-12-31')
const ymdDate = moment({ year: 2024, month: 11, day: 31 })

格式化 ​

js
moment().format()                            // 2024-05-30T09:30:26+00:00
moment().format('YYYY-MM-DD')                // 2024-05-30
moment().format('MMMM Do YYYY, h:mm:ss a')   // May 30th 2024, 9:30:26 am
moment().format()                            // 2024-05-30T09:30:26+00:00
moment().format('YYYY-MM-DD')                // 2024-05-30
moment().format('MMMM Do YYYY, h:mm:ss a')   // May 30th 2024, 9:30:26 am

操作 ​

js
moment().add(7, 'days')
moment().subtract(2, 'months')
moment().set('month', 0) // January
moment().add(7, 'days')
moment().subtract(2, 'months')
moment().set('month', 0) // January

比较 ​

js
moment('2024-12-31').isBefore('2025-01-01') // true
moment('2024-12-31').isAfter('2024-01-01')  // true
moment('2024-12-31').isSame('2024-12-31')   // true
moment('2024-12-31').isBefore('2025-01-01') // true
moment('2024-12-31').isAfter('2024-01-01')  // true
moment('2024-12-31').isSame('2024-12-31')   // true

差异 ​

js
const end = moment('2024-12-31')
const start = moment('2024-01-01')
end.diff(start, 'days')   // 364
end.diff(start, 'months') // 11
const end = moment('2024-12-31')
const start = moment('2024-01-01')
end.diff(start, 'days')   // 364
end.diff(start, 'months') // 11

时区 ​

js
moment().format('Z') // +00:00
moment().format('Z') // +00:00

需要 moment-timezone 插件:

js
const moment = require('moment-timezone')
moment.tz('2024-12-31 23:59:59', 'America/New_York')
const moment = require('moment-timezone')
moment.tz('2024-12-31 23:59:59', 'America/New_York')

本地化 ​

js
moment.locale('zh-cn')
moment().format('LLLL') // 2024年5月30日星期四 09:30
moment.locale('zh-cn')
moment().format('LLLL') // 2024年5月30日星期四 09:30

倒计时示例 ​

js
function countdown(targetTime) {
  const intervalId = setInterval(() => {
    const now = moment()
    const target = moment(targetTime)
    const diff = target.diff(now)
    if (diff <= 0) {
      clearInterval(intervalId)
      console.log('0天00时00分00秒')
    } else {
      const duration = moment.duration(diff)
      const formatted = `${Math.floor(duration.asDays())}天${String(duration.hours()).padStart(2, '0')}时${String(duration.minutes()).padStart(2, '0')}分${String(duration.seconds()).padStart(2, '0')}秒`
      console.log(formatted)
    }
  }, 1000)
}
countdown('2024-12-31T23:59:59')
function countdown(targetTime) {
  const intervalId = setInterval(() => {
    const now = moment()
    const target = moment(targetTime)
    const diff = target.diff(now)
    if (diff <= 0) {
      clearInterval(intervalId)
      console.log('0天00时00分00秒')
    } else {
      const duration = moment.duration(diff)
      const formatted = `${Math.floor(duration.asDays())}天${String(duration.hours()).padStart(2, '0')}时${String(duration.minutes()).padStart(2, '0')}分${String(duration.seconds()).padStart(2, '0')}秒`
      console.log(formatted)
    }
  }, 1000)
}
countdown('2024-12-31T23:59:59')

number-precision ​

数字精度处理函数

安装:npm install number-precision --save

js
NP.strip(num)                           // 计算精度数,第二个参数可保留位数(无四舍五入)
NP.plus(num1, num2, num3, ...)          // 加
NP.minus(num1, num2, num3, ...)         // 减
NP.times(num1, num2, num3, ...)         // 乘
NP.divide(num1, num2, num3, ...)        // 除
NP.round(num, ratio)                    // 解决 toFixed 四舍五入出错的问题
NP.strip(num)                           // 计算精度数,第二个参数可保留位数(无四舍五入)
NP.plus(num1, num2, num3, ...)          // 加
NP.minus(num1, num2, num3, ...)         // 减
NP.times(num1, num2, num3, ...)         // 乘
NP.divide(num1, num2, num3, ...)        // 除
NP.round(num, ratio)                    // 解决 toFixed 四舍五入出错的问题

xlsx ​

安装:

bash
npm install xlsx
yarn add xlsx
npm install xlsx
yarn add xlsx

导出 Excel ​

js
import * as XLSX from 'xlsx'

const data = [
  { name: 'Alice', age: 25, city: 'New York' },
  { name: 'Bob', age: 30, city: 'Los Angeles' },
  { name: 'Charlie', age: 35, city: 'Chicago' },
]

const worksheet = XLSX.utils.json_to_sheet(data)
const workbook = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, 'example.xlsx')
import * as XLSX from 'xlsx'

const data = [
  { name: 'Alice', age: 25, city: 'New York' },
  { name: 'Bob', age: 30, city: 'Los Angeles' },
  { name: 'Charlie', age: 35, city: 'Chicago' },
]

const worksheet = XLSX.utils.json_to_sheet(data)
const workbook = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, 'example.xlsx')

导入 Excel ​

html
<input type="file" id="upload" />
<input type="file" id="upload" />
js
document.getElementById('upload').addEventListener('change', (event) => {
  const file = event.target.files[0]
  const reader = new FileReader()
  reader.onload = (e) => {
    const data = new Uint8Array(e.target.result)
    const workbook = XLSX.read(data, { type: 'array' })
    const firstSheetName = workbook.SheetNames[0]
    const worksheet = workbook.Sheets[firstSheetName]
    const jsonData = XLSX.utils.sheet_to_json(worksheet)
    console.log(jsonData)
  }
  reader.readAsArrayBuffer(file)
})
document.getElementById('upload').addEventListener('change', (event) => {
  const file = event.target.files[0]
  const reader = new FileReader()
  reader.onload = (e) => {
    const data = new Uint8Array(e.target.result)
    const workbook = XLSX.read(data, { type: 'array' })
    const firstSheetName = workbook.SheetNames[0]
    const worksheet = workbook.Sheets[firstSheetName]
    const jsonData = XLSX.utils.sheet_to_json(worksheet)
    console.log(jsonData)
  }
  reader.readAsArrayBuffer(file)
})

设置单元格样式 ​

js
worksheet['A1'] = { v: 'Header', s: { font: { bold: true, color: { rgb: 'FF0000' } } } }
worksheet['A1'] = { v: 'Header', s: { font: { bold: true, color: { rgb: 'FF0000' } } } }

设置列宽和行高 ​

js
worksheet['!cols'] = [{ wpx: 100 }, { wpx: 200 }, { wpx: 300 }]
worksheet['!rows'] = [{ hpx: 20 }, { hpx: 30 }, { hpx: 40 }]
worksheet['!cols'] = [{ wpx: 100 }, { wpx: 200 }, { wpx: 300 }]
worksheet['!rows'] = [{ hpx: 20 }, { hpx: 30 }, { hpx: 40 }]

多工作表 ​

js
const workbook = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(workbook, sheet1, 'Sheet1')
XLSX.utils.book_append_sheet(workbook, sheet2, 'Sheet2')
XLSX.writeFile(workbook, 'multiple_sheets.xlsx')
const workbook = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(workbook, sheet1, 'Sheet1')
XLSX.utils.book_append_sheet(workbook, sheet2, 'Sheet2')
XLSX.writeFile(workbook, 'multiple_sheets.xlsx')

SortableJS ​

功能强大的 JavaScript 拖拽库

Sortable.js 中文网

ElementUI Table 使用 ​

js
import Sortable from "sortablejs"

const el = document.querySelector(".el-table__body-wrapper tbody")
new Sortable(el, {
  animation: 150,
  handle: ".table-move",
  ghostClass: "blue-background-class",
})
import Sortable from "sortablejs"

const el = document.querySelector(".el-table__body-wrapper tbody")
new Sortable(el, {
  animation: 150,
  handle: ".table-move",
  ghostClass: "blue-background-class",
})

配置项:https://sortablejs.com/options

vue-cropper(图片修剪) ​

安装:

bash
npm install vue-cropper
yarn add vue-cropper
npm install vue-cropper
yarn add vue-cropper
vue
<vue-cropper
    ref="cropper"
    :img="options.img"
    :autoCrop="options.autoCrop"
    :fixedBox="options.fixedBox"
    :canMoveBox="options.canMoveBox"
    :autoCropWidth="options.autoCropWidth"
    :autoCropHeight="options.autoCropHeight"
    :centerBox="options.centerBox"
    :fixed="options.fixed"
    :fixedNumber="options.fixedNumber"
    :canMove="options.canMove"
    :canScale="options.canScale"
    @realTime=realTime />

<div :style="previewStyle">
    <div :style="previews.div"><img :src="previews.url" :style="previews.img"></div>
</div>
<vue-cropper
    ref="cropper"
    :img="options.img"
    :autoCrop="options.autoCrop"
    :fixedBox="options.fixedBox"
    :canMoveBox="options.canMoveBox"
    :autoCropWidth="options.autoCropWidth"
    :autoCropHeight="options.autoCropHeight"
    :centerBox="options.centerBox"
    :fixed="options.fixed"
    :fixedNumber="options.fixedNumber"
    :canMove="options.canMove"
    :canScale="options.canScale"
    @realTime=realTime />

<div :style="previewStyle">
    <div :style="previews.div"><img :src="previews.url" :style="previews.img"></div>
</div>
js
const options = ref({
    autoCrop: true,
    fixedBox: false,
    canMoveBox: true,
    autoCropWidth: 200,
    autoCropHeight: 200,
    fixed: true,
    fixedNumber: [1, 1],
    centerBox: true,
    canMove: false,
    canScale: false
})

function realTime(data) {
    previewStyle.value = {
        width: data.w + "px",
        height: data.h + "px",
        overflow: "hidden",
        margin: "0",
        zoom: 0.5,
        borderRadius: "50%"
    }
    previews.value = data
}
const options = ref({
    autoCrop: true,
    fixedBox: false,
    canMoveBox: true,
    autoCropWidth: 200,
    autoCropHeight: 200,
    fixed: true,
    fixedNumber: [1, 1],
    centerBox: true,
    canMove: false,
    canScale: false
})

function realTime(data) {
    previewStyle.value = {
        width: data.w + "px",
        height: data.h + "px",
        overflow: "hidden",
        margin: "0",
        zoom: 0.5,
        borderRadius: "50%"
    }
    previews.value = data
}

styled-components ​

通过 JavaScript 改变 CSS 编写方式,all in js 思想。

基本 ​

js
const StyleApp = styled.div`
    background: yellow;
    border: 1px solid black;
    ul li { color: red; }
    &:hover { background: pink; }
`
const StyleApp = styled.div`
    background: yellow;
    border: 1px solid black;
    ul li { color: red; }
    &:hover { background: pink; }
`

透传 props ​

js
const StyledInput = styled.input`
    color: red;
    background: yellow;
`
<StyledInput type="text" placeholder="okok" />
const StyledInput = styled.input`
    color: red;
    background: yellow;
`
<StyledInput type="text" placeholder="okok" />

基于 props 判断 ​

js
const StyledButton = styled.button`
    background: ${(props) => props.bg || 'blue'};
`
const StyledButton = styled.button`
    background: ${(props) => props.bg || 'blue'};
`

样式化任意组件 ​

js
const Child = (props) => <div className={props.className}>child</div>
const StyledChild = styled(Child)` background: red; `
const Child = (props) => <div className={props.className}>child</div>
const StyledChild = styled(Child)` background: red; `

扩展样式 ​

js
const MyButton = styled.button` background: yellow; `
const BigButton = styled(MyButton)` height: 100px; width: 100px; `
const MyButton = styled.button` background: yellow; `
const BigButton = styled(MyButton)` height: 100px; width: 100px; `

动画 ​

js
import styled, { keyframes } from 'styled-components'

const rotate360 = keyframes`
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
`
const Rotate = styled.div`
    width: 100px; height: 100px;
    background: yellow;
    animation: ${rotate360} 1s linear infinite;
`
import styled, { keyframes } from 'styled-components'

const rotate360 = keyframes`
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
`
const Rotate = styled.div`
    width: 100px; height: 100px;
    background: yellow;
    animation: ${rotate360} 1s linear infinite;
`

Element UI ​

表格排序 ​

vue
<el-table :default-sort="{ prop: 'creation_time', order: 'descending' }">
    <el-table-column prop="creation_time" sortable />
</el-table>
<el-table :default-sort="{ prop: 'creation_time', order: 'descending' }">
    <el-table-column prop="creation_time" sortable />
</el-table>

表格手风琴效果 ​

js
expandChange(row, expandedRows) {
    if (expandedRows.length > 1) {
        this.expands = []
        if (row) this.expands.push(row)
        this.$refs.table.toggleRowExpansion(expandedRows[0])
    } else {
        this.expands = []
    }
}
expandChange(row, expandedRows) {
    if (expandedRows.length > 1) {
        this.expands = []
        if (row) this.expands.push(row)
        this.$refs.table.toggleRowExpansion(expandedRows[0])
    } else {
        this.expands = []
    }
}

修改表格头部样式 ​

css
::v-deep .NexineTable thead {
    color: #fff;
    background-color: rgb(252, 252, 252) !important;
    & th, & tr { background-color: transparent; }
}
::v-deep .NexineTable thead {
    color: #fff;
    background-color: rgb(252, 252, 252) !important;
    & th, & tr { background-color: transparent; }
}

超出省略 ​

vue
<el-table-column prop="address" :show-overflow-tooltip='true' />
<el-table-column prop="address" :show-overflow-tooltip='true' />

vue-animate-number(VUE 数字动画) ​

安装:npm install vue-animate-number

js
import Vue from 'vue'
import VueAnimateNumber from 'vue-animate-number'
Vue.use(VueAnimateNumber)
import Vue from 'vue'
import VueAnimateNumber from 'vue-animate-number'
Vue.use(VueAnimateNumber)
vue
<animate-number from="1" to="10" duration="1000" easing="easeOutQuad" :formatter="formatter"></animate-number>
<animate-number ref="myNum" from="0" to="10" mode="manual"></animate-number>
<button @click="startAnimate()">animate!</button>
<animate-number from="1" to="10" duration="1000" easing="easeOutQuad" :formatter="formatter"></animate-number>
<animate-number ref="myNum" from="0" to="10" mode="manual"></animate-number>
<button @click="startAnimate()">animate!</button>
js
methods: {
    formatter(num) { return num.toFixed(2) },
    startAnimate() { this.$refs.myNum.start() }
}
methods: {
    formatter(num) { return num.toFixed(2) },
    startAnimate() { this.$refs.myNum.start() }
}

animate.css ​

引入 ​

html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css" />

使用 ​

html
<div class="animated bounce"></div>
<div class="animated bounce"></div>

类名:infinite(无限循环)、delay-2s/3s/4s/5s、slow(2s)、slower(3s)、fast(800ms)、faster(500ms)

Vue 中使用 ​

vue
<transition enter-active-class="animate__animated animate__bounceInLeft"
            leave-active-class="animate__animated animate__hinge">
    <div class="box" v-if="isshow"></div>
</transition>
<transition enter-active-class="animate__animated animate__bounceInLeft"
            leave-active-class="animate__animated animate__hinge">
    <div class="box" v-if="isshow"></div>
</transition>

回调函数 ​

js
element.addEventListener('animationend', function () {
    alert('动画完成')
})
element.addEventListener('animationend', function () {
    alert('动画完成')
})

Hiprint(打印插件) ​

官网:http://hiprint.io/

安装:npm install vue-plugin-hiprint

html
<link rel="stylesheet" type="text/css" media="print" href="https://cdn.jsdelivr.net/npm/vue-plugin-hiprint@latest/dist/print-lock.css">
<link rel="stylesheet" type="text/css" media="print" href="https://cdn.jsdelivr.net/npm/vue-plugin-hiprint@latest/dist/print-lock.css">
js
import * as hiPrint from 'vue-plugin-hiprint'

let hiprintTemplate = new hiPrint.hiprint.PrintTemplate({
    template: order_particulars_my_panel,
    settingContainer: "#templateDesignDiv",
})

hiprintTemplate.print(printData, {}, {
    styleHandler: () => {
        let css = '<link href="http://hiprint.io/Content/hiprint/css/print-lock.css" media="print" rel="stylesheet">'
        return css
    }
})
import * as hiPrint from 'vue-plugin-hiprint'

let hiprintTemplate = new hiPrint.hiprint.PrintTemplate({
    template: order_particulars_my_panel,
    settingContainer: "#templateDesignDiv",
})

hiprintTemplate.print(printData, {}, {
    styleHandler: () => {
        let css = '<link href="http://hiprint.io/Content/hiprint/css/print-lock.css" media="print" rel="stylesheet">'
        return css
    }
})