相关资源
vue,自动更新版本号
修改 package.json 的 version
function changePackageJsonVersion() {
//每次打包构建代码,自动更新版本号,同一天加1,隔天自动回归变成 1 。例如{ 今天:1.20200917.3,第二天:1.20200918.1 }
const fs = require('fs');
try {
function AddZero(time) {
if (time < 10) {
return '0' + time;
} else {
return time;
}
}
let packageTxt = fs.readFileSync('./package.json', 'utf8');
let versionData = packageTxt.split('\n');
let packageJson = JSON.parse(packageTxt);
let VersionArr = packageJson.version.split('.');
let date = new Date();
let today =
date.getFullYear() +
'' +
AddZero(date.getMonth() + 1) +
'' +
AddZero(date.getDate());
if (today == VersionArr[1]) {
VersionArr[2] = parseInt(VersionArr[2]) + 1;
} else {
VersionArr[1] =
date.getFullYear() +
'' +
AddZero(date.getMonth() + 1) +
'' +
AddZero(date.getDate());
VersionArr[2] = 1;
}
let versionLine = VersionArr.join('.');
for (let i = 0; i < versionData.length; i++) {
if (versionData[i].indexOf('"version":') != -1) {
versionData.splice(
i,
1,
' "version": "' + versionLine + '",'
);
break;
}
}
fs.writeFileSync('./package.json', versionData.join('\n'), 'utf8');
} catch (e) {
// console.log(chalk.red.bold('读取文件修改版本号出错:', e.toString()));
}
}
NodeJS + express访问html、css、JS等静态资源文件
判断浏览器环境
- 是否是微信打开的h5页面
isWeixin() { let wx = navigator.userAgent.toLowerCase(); if (wx.match(/MicroMessenger/i) == 'micromessenger') { return true; } else { return false; } },
- 是否是ios手机
isIOS() { let u = navigator.userAgent, app = navigator.appVersion; return !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); },
打开新的浏览器选项卡
window.open(url, '_blank');
关闭当前浏览器选项卡
function closeWin(){
if (navigator.userAgent.indexOf("Firefox") != -1 || navigator.userAgent.indexOf("Chrome") != -1) {
window.location.href = "about:blank";
window.close();
} else {
window.opener = null;
window.open("", "_self");
window.close();
};
}
如何判断数组类型
Array.isArray(arr)
如何判断一个对象是不是空对象?
Object.keys(obj).length === 0
利用a标签解析url
function urlParse(url, key) {
var a = document.createElement('a')
a.href = url
var result = {
href: url,
protocol: a.protocol.replace(':', ''),
port: a.port,
query: a.search,
params: (function(){
var ret = {}, centArr,
seg = a.search.replace(/^\?/, '').replace(/^\?/,'').split('&')
for (i = 0, len = seg.length; i < len; i ++) {
if (!seg[i]) { continue }
centArr = seg[i].split('=')
ret[centArr[0]] = centArr[1]
}
return ret
}()),
hash: a.hash,
file: (a.pathname.match(/\/([^\/?#]+)$/i) || [, ''])[1],
path: a.pathname.replace(/^([^\/])/, '/$1'),
relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [, ''])[1],
segments: a.pathname.replace(/^\//, '').split('/')
}
a = null
return key ? result[key] : result
}
- H5 有新的 API URL 也可以快速的处理一个链接
var url = new URL('https://www.baidu.com/')
url.hash
js 实现图片点击下载功能
- 方法一
downloadQrFunc2() { var src1 = "https://pic2.zhimg.com/v2-5ec052fff9d691c6a61654ed16440547_400x224.jpg"; var src = "https://bkimg.cdn.bcebos.com/pic/2934349b033b5bb571dc8c5133d3d539b600bc12?x-bce-process=image/resize,m_lfit,w_268,limit_1/format,f_jpg"; var filename; var filetype; var path = src; if (path.indexOf("/") > 0) { var file = path.substring(path.lastIndexOf("/") + 1, path.length); var fileArr = file.toLowerCase().split("."); filename = fileArr[0]; filetype = fileArr[1]; } // var newImage = new Image(); // newImage.src = src; var canvas = document.createElement("canvas"); var img = document.createElement("img"); img.onload = function(e) { canvas.width = img.width; canvas.height = img.height; var context = canvas.getContext("2d"); context.drawImage(img, 0, 0, img.width, img.height); canvas.getContext("2d").drawImage(img, 0, 0, img.width, img.height); canvas.toBlob(blob => { var a = document.createElement("a"); a.href = window.URL.createObjectURL(blob); a.download = filename; a.click(); }, `image/${filetype}`); }; img.setAttribute("crossOrigin", "Anonymous"); img.src = src; },
- 方法二
dowonUrl(url) { const a = document.createElement('a'); a.setAttribute('download', url); a.setAttribute('href', url); a.click(); },
- 方法三 提供一个图片链接,点击下载 参考地址
图片、pdf等文件,浏览器会默认执行预览,不能调用download方法进行下载,需要先把图片、pdf等文件转成blob,再调用download方法进行下载,转换的方式是使用axios请求对应的链接//可以用来下载浏览器会默认预览的文件类型,例如mp4,jpg等 import axios from 'axios' //提供一个link,完成文件下载,link可以是 http://xxx.com/xxx.xls function downloadByLink(link,fileName){ axios.request({ url: link, responseType: 'blob' //关键代码,让axios把响应改成blob }).then(res => { const link=URL.createObjectURL(res.data) download(link, fileName) }) }
树结构数据的操作
- 参考链接
//定义树结构数据的操作 class treeDataFun { // 参考资料 https://wintc.top/article/20 constructor() {} // 列表转为树 listToTree(list) { let info = list.reduce( (map, node) => ((map[node.id] = node), (node.children = []), map), {} ); return list.filter((node) => { info[node.parentId] && info[node.parentId].children.push(node); return !node.parentId; }); } // 递归实现 - 树结构转列表结构 treeToList(tree, result = [], level = 0) { tree.forEach((node) => { result.push(node); node.level = level + 1; node.children && this.treeToList(node.children, result, level + 1); }); return result; } // 树结构筛选 treeFilter(tree, func) { // 使用map复制一下节点,避免修改到原树 return tree .map((node) => ({ ...node })) .filter((node) => { node.children = node.children && treeFilter(node.children, func); return func(node) || (node.children && node.children.length); }); } // 树结构查找 treeFind(tree, func) { for (const data of tree) { if (func(data)) return data; if (data.children) { const res = treeFind(data.children, func); if (res) return res; } } return null; } // 查找节点路径 treeFindPath(tree, node => node.id === '2-1') treeFindPath(tree, func, path = []) { if (!tree) return []; for (const data of tree) { path.push(data.id); if (func(data)) return path; if (data.children) { const findChildren = treeFindPath(data.children, func, path); if (findChildren.length) return findChildren; } path.pop(); } return []; } // treeForeach(tree, node => { console.log(node.title) }) treeForeach(tree, func) { tree.forEach((data) => { data.children && treeForeach(data.children, func); // 遍历子树 func(data); }); } } export const treeData = new treeDataFun();
【JS】(数组、对象)深拷贝函数的封装
- 1
function deepClone (obj) {
let newObj;
if (Array.isArray(obj)) { // 判断复制的目标是不是数组
newObj = [];
} else if (typeof obj === 'object') {
newObj = {};
} else {
newObj = obj;
};
if (typeof obj === 'object') {
for (item in obj) {
if(obj.hasOwnProperty(item)) {
if(obj[item] && typeof obj[item] === 'object') {
newObj[item] = deepClone(obj[item])
} else {
newObj[item] = obj[item]
}
}
}
}
return newObj;
}
let obj = {name:'小明',age:20}
newObj = deepClone(obj)
- 2
按 Ctrl+C 复制代码按 Ctrl+C 复制代码
当然,用JSON对象的parse和stringify也能完成深拷贝,但是用JSON.parse(JSON.stringify(obj))拷贝会有一个问题,就是如果数组或者对象中的属性为undefined、function和symbol时,转换过程中会被忽略
例:const obj = {name:'小明',age:20,subject:{a:100,b:null,c:undefined}}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj) // {name:'小明',age:20,subject:{a:100,b:null}}
数组增加是否包含某个元素的函数
Array.prototype.contains = function (obj) {
var i = this.length
while (i--) {
if (this[i] === obj) {
return true
}
}
return false
}
日期相关
小程序日期格式化
function formatTime(date) {
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
/**
* 时间戳转化为年 月 日 时 分 秒
* number: 传入时间戳
* format:返回格式,支持自定义,但参数必须与formateArr里保持一致
*/
function formatTimeTwo(number, format) {
var formateArr = ['Y', 'M', 'D', 'h', 'm', 's'];
var returnArr = [];
var date = new Date(number * 1000);
returnArr.push(date.getFullYear());
returnArr.push(formatNumber(date.getMonth() + 1));
returnArr.push(formatNumber(date.getDate()));
returnArr.push(formatNumber(date.getHours()));
returnArr.push(formatNumber(date.getMinutes()));
returnArr.push(formatNumber(date.getSeconds()));
for (var i in returnArr) {
format = format.replace(formateArr[i], returnArr[i]);
}
return format;
}
module.exports = {
formatTime: formatTime,
formatTimeTwo: formatTimeTwo
}
调用:
var sjc = 1488481383;
console.log(time.formatTime(sjc,'Y/M/D h:m:s'));
console.log(time.formatTime(sjc, 'h:m'));
得到的效果如下:
2017/03/03 03:03:03
03:03
日期格式化
// 日期格式化
export function formatDate(date, fmt) {
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
}
let o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
};
for (let k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
let str = o[k] + '';
const str2 = ('00' + str).substr(str.length)
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : str2 ;
}
}
return fmt;
};
var time1 = formatDate(’2021-09-01‘,"yyyy-MM-dd hh:mm:ss");
方法二
Date.prototype.Format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
调用:
var time1 = new Date().Format("yyyy-MM-dd");
var time2 = new Date().Format("yyyy-MM-dd HH:mm:ss");
时间 - 间隔 判断
/**
* @description 时间 间隔 的判断
* @param {number} time
* @param {string} option 时间格式 yyy-MM-dd 等等
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
// 时间格式化函数
return parseTime(time, option)
} else {
return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
}
}
js日期比较(yyyy-mm-dd)
function duibi(a, b) {
var arr = a.split("-");
var starttime = new Date(arr[0], arr[1], arr[2]);
var starttimes = starttime.getTime();
var arrs = b.split("-");
var lktime = new Date(arrs[0], arrs[1], arrs[2]);
var lktimes = lktime.getTime();
if (starttimes >= lktimes) {
alert('开始时间大于离开时间,请检查');
return false;
}
else
return true;
}
js时间比较(yyyy-mm-dd hh:mi:ss)
function comptime() {
var beginTime = "2009-09-21 00:00:00";
var endTime = "2009-09-21 00:00:01";
var beginTimes = beginTime.substring(0, 10).split('-');
var endTimes = endTime.substring(0, 10).split('-');
beginTime = beginTimes[1] + '-' + beginTimes[2] + '-' + beginTimes[0] + ' ' + beginTime.substring(10, 19);
endTime = endTimes[1] + '-' + endTimes[2] + '-' + endTimes[0] + ' ' + endTime.substring(10, 19);
alert(beginTime + "aaa" + endTime);
alert(Date.parse(endTime));
alert(Date.parse(beginTime));
var a = (Date.parse(endTime) - Date.parse(beginTime)) / 3600 / 1000;
if (a < 0) {
alert("endTime小!");
} else if (a > 0) {
alert("endTime大!");
} else if (a == 0) {
alert("时间相等!");
} else {
return 'exception'
}
}
js时间比较(hh:mm)
var t1 = '80:06'
var t2 = '12:30'
types: function (t1, t2) {
var date = new Date();
var a = t1.split(":");
var b = t2.split(":");
return date.setHours(a[0], a[1]) > date.setHours(b[0], b[1]);
}
根据元素ID遍历树形结构,查找到所有父元素ID
- 数据
[{
"orgId": 1,
"orgName": "校长办公室1",
"parentId": 0,
"children": [{
"orgId": 2,
"orgName": "校长办公室2",
"parentId": 1,
"children": [{
"orgId": 3,
"orgName": "校长办公室3",
"parentId": 2,
}]
}]
}]
- 函数
function buildParentList(arr){
arr.forEach(g =>
{
if(g.parentId != undefined) {
let pid = g['parentId']
let oid = g['orgId']
parentList[oid] = pid
}
if (g.children != undefined)
buildParentList(g['children'])
})
}
function findParent(idx){
if (parentList[idx] != undefined){
let pid = parentList[idx]
console.log(pid)
findParent(pid)
}
}
- 执行方法:
buildParentList(list)
findParent(3); // 0 1 2
findParent(2); // 0 1
findParent(4); // undefined
根据ID或者ID集合查找树形结构数据里面ID所对应的节点信息
// 根据ID或者ID集合查找树形结构数据里面ID所对应的节点信息
export const getCity = (arr, data, city = []) => {
if (typeof data === 'object') {
for (let i = 0; arr[i] !== undefined; i++) {
for (let j = 0; data[j] !== undefined; j++) {
if (arr[i] === data[j].id) {
city.push(data[j]);
}
}
}
for (let i = 0; data[i] !== undefined; i++) {
getCity(arr, data[i].children, city);
}
}
return city;
};
// console.log(getCity(["c128cc24578842debff29b4eba1355bf", "4b21a22d711c4cf6a3e0166011a77e53", "5d918f95b513450c83b54748631c3c34"], data))
input file
// 展示input上传图片
addImg(event) {
let inputDOM = this.$refs.inputer;
// 通过DOM取文件数据
this.fil = inputDOM.files;
let files = inputDOM.files[0];
var formdata = new FormData();
formdata.append('file', inputDOM.files[0]);
formdata.append('workorderNo', this.form.workorderNo);
formdata.append('token', this.user);
uploadImg(formdata, res => {
console.log(res.data)
})
let oldLen = this.imgLen;
let len = this.fil.length + oldLen;
if (len > 5) {
alert('最多可上传4张,您还可以上传' + (5 - oldLen) + '张');
return false;
}
for (let i = 0; i < this.fil.length; i++) {
let size = Math.floor(this.fil[i].size / 1024);
if (size > 5 * 1024 * 1024) {
alert('请选择5M以内的图片!');
return false
}
this.imgLen++;
this.$set(this.imgs, this.fil[i].name + '?' + new Date().getTime() + i, this.fil[i]);
}
},
// 删除指定图片
delImg(key) {
this.$delete(this.imgs, key);
this.imgLen--;
},
正则
1 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3 InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
4 手机号码:^(13[0-9]|14[0-9]|15[0-9]|166|17[0-9]|18[0-9]|19[8|9])\d{8}$
5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
6 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
7 18位身份证号码(数字、字母x结尾):^((\d{18})|([0-9x]{18})|([0-9X]{18}))$
8 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
9 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
10 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
11 日期格式:^\d{4}-\d{1,2}-\d{1,2}
12 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
13 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
14 钱的输入格式:
15 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
16 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
17 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
18 4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
19 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$
20 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
21 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
22 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
23 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
24 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
25 中文字符的正则表达式:[\u4e00-\u9fa5]
26 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
27 空白行的正则表达式:\n\s*\r (可以用来删除空白行)
28 HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
29 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
30 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
31 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
32 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
33 IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)) (由@飞龙三少 提供,感谢共享)
rem.js , 需要自己改px为rem
/*** html节点字体大小随屏幕大小改变 ***/
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 640) {
let designSize = 1920; // 设计图尺寸
let wW = docEl.clientWidth; // 窗口宽度
let rem = wW * 100 / designSize;
docEl.style.fontSize = rem + 'px';
} else {
docEl.style.fontSize = 40 * (clientWidth / 640) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
// 4.如果是在手机上, 平板电脑上, 更要使用REM, 由于手机上一般不会调整浏览器大小, 所以可以在页面载入时, 设置一次即可
// $(function () {
// var whdef = 50 / 750;// 表示750的设计图,使用50PX的默认值
// var wH = window.innerHeight;// 手机窗口的高度
// var wW = window.innerWidth;// 手机窗口的宽度
// var rem = wW * whdef;// 以默认比例值乘以当前窗口宽度,得到该宽度下的相应FONT-SIZE值
// $('html').css('font-size', rem + "px");
// })
// 3.当浏览器窗口变化时, 内容的大小以及相对位置也会相应变化, 这个依靠JS修改HTML的FONT - SIZE值实现.如下:
// $(window).resize(function ()// 绑定到窗口的这个事件中
// {
// var whdef = 100 / 1920;// 表示1920的设计图,使用100PX的默认值
// var wH = window.innerHeight;// 当前窗口的高度
// var wW = window.innerWidth;// 当前窗口的宽度
// var rem = wW * whdef;// 以默认比例值乘以当前窗口宽度,得到该宽度下的相应FONT-SIZE值
// $('html').css('font-size', rem + "px");
// });