文章目录
- 各类工具函数
- 1.保留小数点后几位
- 2.深拷贝
- 3.生成随机字符串
- 4.复制内容到剪切板
- 5.获取文件名后缀
- 6.数组去重
- 7.对象转化为FormData对象
- 8. 休眠多少毫秒
- 9.下载一个excel文档
- 10. 提供一个图片链接,点击下载
- 11. 在浏览器中自定义下载一些内容
- 12.取整
- 13.数字取反
- 13.禁止右键、选择、复制
- 14.数据类型验证
- 15.压缩base64格式的图片
- 16.获取地址栏置顶参数
- 17.生成随机uuid
- 18.检查字符串是否只包含字母与数字
- 19.检查字符串是否只包含数字
- 20.检查字符串是否只包含字母
- 21.去除字符串中的HTML
- 22.滚动到页面顶部
- 23.判断当前是否是苹果设备
- 24.重定向到一个URL
- 25. 打开浏览器打印框
- 26.图片上传
- 27. 根据url转换图片(base64)
- 28.压缩图片base64体积
- 29. 视频倍速播放
- 30. 将单引号字符串数组转为真数组
- 31. DES加密解密
- 32.防抖、节流函数
- 33.滚动加载
- 34.渲染大数据
- 35.计算两个坐标点(经纬度)的距离
- 36. 判断一个日期是否是工作日
- 37.判断一个数字是奇数还是偶数
- 38. 检查当前设备是否是苹果设备
- 39. 获取所有参数的平均值
- 40. 转换华氏/摄氏度
- 41.冒泡排序
- 42.实现一行文内两端对齐
- vue相关
- 搜索相关
- 插件类使用
工具函数大集
各类工具函数
1.保留小数点后几位
// 保留小数点以后几位,默认2位
export function cutNumber(number, no = 2) {
if (typeof number != 'number') {
number = Number(number)
}
return Number(number.toFixed(no))
}
//方式二:
const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed);
// Examples
toFixed(25.198726354, 1); // 25.1
toFixed(25.198726354, 2); // 25.19
toFixed(25.198726354, 3); // 25.198
toFixed(25.198726354, 4); // 25.1987
toFixed(25.198726354, 5); // 25.19872
toFixed(25.198726354, 6); // 25.198726
2.深拷贝
1.简单深拷贝
export function deepCopy(obj) {
if (typeof obj != 'object') {
return obj
}
if (obj == null) {
return obj
}
return JSON.parse(JSON.stringify(obj))
}
//缺陷:只拷贝对象、数组以及对象数组,对于大部分场景已经足够
使用方式:
const person={name:'xiaoming',child:{name:'Jack'}}
deepCopy(person) //new person
//方式2:
JSON.parse(JSON.stringify(obj))
//注意对于内容为undefined null function error Date RegExp时候,会出错
2.递归深拷贝
//递归函数实现深拷贝
const copyObj = (obj = {}) => {
//变量先置空
let newobj = null;
//判断是否需要继续进行递归
if (typeof (obj) == 'object' && obj !== null&& !(obj instanceof Date)) {
newobj = obj instanceof Array ? [] : {};
//进行下一层递归克隆
for (var i in obj) {
newobj[i] = copyObj(obj[i])
}
//如果不是对象直接赋值
} else newobj = obj;
return newobj;
}
//使用:
//模拟对象
let obj = {
numberParams:1,
functionParams:() => {
console.log('昨天基金全是绿的,只有我的眼睛是红的');
},
objParams:{
a:1,
b:2
}
}
const newObj = copyObj(obj); //这样就完成了一个对象的递归拷贝
obj.numberParams = 100; //更改第一个对象的指
console.log(newObj.numberParams); //输出依然是1 不会跟随obj去改变
3.使用lodash库实现 (推荐)
// 1.安装 npm i --save lodash
//2. 引入
import lodash from 'lodash';
let obj = {
a: {
c: 2,
d: [1, 3, 5],
e:'阿巴阿巴'
},
b: 4
}
const newObj = lodash.cloneDeep(obj);
obj.b = 20;
console.log(newObj.b); //输出 4; 不会改变
4. jquery中深拷贝
let obj = {
a: {
c: 2,
d: [1, 3, 5],
e:'阿巴阿巴'
},
b: 4
}
let newObj= $.extend(true, {}, obj1); //拷贝完成
obj.b = 20;
console.log(newObj.b); //输出 4
5.weakMap实现深拷贝(推荐)
function deepClone (target, hash = new WeakMap()) { // 额外开辟一个存储空间WeakMap来存储当前对象
if (target === null) return target // 如果是 null 就不进行拷贝操作
if (target instanceof Date) return new Date(target) // 处理日期
if (target instanceof RegExp) return new RegExp(target) // 处理正则
if (target instanceof HTMLElement) return target // 处理 DOM元素
if (typeof target !== 'object') return target // 处理原始类型和函数 不需要深拷贝,直接返回
// 是引用类型的话就要进行深拷贝
if (hash.get(target)) return hash.get(target) // 当需要拷贝当前对象时,先去存储空间中找,如果有的话直接返回
const cloneTarget = new target.constructor() // 创建一个新的克隆对象或克隆数组
hash.set(target, cloneTarget) // 如果存储空间中没有就存进 hash 里
Reflect.ownKeys(target).forEach(key => { // 引入 Reflect.ownKeys,处理 Symbol 作为键名的情况
cloneTarget[key] = deepClone(target[key], hash) // 递归拷贝每一层
})
return cloneTarget // 返回克隆的对象
}
//使用:
const obj = {
a: true,
b: 100,
c: 'str',
d: undefined,
e: null,
f: Symbol('f'),
g: {
g1: {} // 深层对象
},
h: [], // 数组
i: new Date(), // Date
j: /abc/, // 正则
k: function () {}, // 函数
l: [document.getElementById('foo')] // 引入 WeakMap 的意义,处理可能被清除的 DOM 元素
}
obj.obj = obj // 循环引用
const name = Symbol('name')
obj[name] = 'lin' // Symbol 作为键
const newObj = deepClone(obj)
console.log(newObj)
3.生成随机字符串
/**
* 生成随机id
* @param {*} length
* @param {*} chars
*/
export function uuid(length, chars) {
chars =
chars ||
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
length = length || 8
var result = ''
for (var i = length; i > 0; --i)
result += chars[Math.floor(Math.random() * chars.length)]
return result
}
使用方式
//第一个参数指定位数,第二个字符串指定字符,都是可选参数,如果都不传,默认生成8位
uuid()
4.复制内容到剪切板
//复制内容到剪切板
export function copyToBoard(value) {
const element = document.createElement('textarea')
document.body.appendChild(element)
element.value = value
element.select()
element.setSelectionRange(0, value.length)//解决ios12不兼容
if (document.execCommand('copy')) {
document.execCommand('copy')
document.body.removeChild(element)
return true
}
document.body.removeChild(element)
return false
}
使用方式:
//如果复制成功返回true
copyToBoard('lalallala')
原理:
创建一个textare元素并调用select()方法选中
document.execCommand('copy')方法,拷贝当前选中内容到剪贴板。
//方法二:
npm install --save vue-clipboard2
/main.js中引入
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard)
//使用:
this.$copyText(需要f).then(
(e) => {
this.$toast({
message: "复制成功!",
position: "top",
});
},
function (e) {
this.$toast({
message: "复制失败!",
position: "top",
});
}
);
5.获取文件名后缀
/**
* 获取文件后缀名
* @param {String} filename
*/
export function getExt(filename) {
if (typeof filename == 'string') {
return filename
.split('.')
.pop()
.toLowerCase()
} else {
throw new Error('filename must be a string type')
}
}
使用方式
getExt("1.mp4") //->mp4
6.数组去重
/**
* 数组去重
* @param {*} arr
*/
export function uniqueArray(arr) {
if (!Array.isArray(arr)) {
throw new Error('The first parameter must be an array')
}
if (arr.length == 1) {
return arr
}
return [...new Set(arr)]
}
使用方式:
uniqueArray([1,1,1,1,1])//[1]
7.对象转化为FormData对象
/**
* 对象转化为formdata
* @param {Object} object
*/
export function getFormData(object) {
const formData = new FormData()
Object.keys(object).forEach(key => {
const value = object[key]
if (Array.isArray(value)) {
value.forEach((subValue, i) =>
formData.append(key + `[${i}]`, subValue)
)
} else {
formData.append(key, object[key])
}
})
return formData
}
//使用场景:上传文件时我们要新建一个FormData对象,然后有多少个参数就append多少次,使用该函数可以简化逻辑
使用方式:
let req={
file:xxx,
userId:1,
phone:'15198763636',
//...
}
fetch(getFormData(req))
8. 休眠多少毫秒
/**
* 休眠xxxms
* @param {Number} milliseconds
*/
export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
//使用方式
const fetchData=async()=>{
await sleep(1000)
}
9.下载一个excel文档
同时适用于word,ppt等浏览器不会默认执行预览的文档,也可以用于下载后端接口返回的流数据,见3
//下载一个链接
function download(link, name) {
if(!name){
name=link.slice(link.lastIndexOf('/') + 1)
}
let eleLink = document.createElement('a')
eleLink.download = name
eleLink.style.display = 'none'
eleLink.href = link
document.body.appendChild(eleLink)
eleLink.click()
document.body.removeChild(eleLink)
}
//下载excel
download('http://111.229.14.189/file/1.xlsx')
//下载后端返回的流
数据是后端以接口的形式返回的,进行下载
download('http://111.229.14.189/gk-api/util/download?file=1.jpg')
download('http://111.229.14.189/gk-api/util/download?file=1.mp4')
10. 提供一个图片链接,点击下载
图片、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)
})
}
注意:会有同源策略的限制,需要配置转发
11. 在浏览器中自定义下载一些内容
场景:我想下载一些DOM内容,我想下载一个JSON文件
/**
* 浏览器下载静态文件
* @param {String} name 文件名
* @param {String} content 文件内容
*/
function downloadFile(name, content) {
if (typeof name == 'undefined') {
throw new Error('The first parameter name is a must')
}
if (typeof content == 'undefined') {
throw new Error('The second parameter content is a must')
}
if (!(content instanceof Blob)) {
content = new Blob([content])
}
const link = URL.createObjectURL(content)
download(link, name)
}
//下载一个链接
function download(link, name) {
if (!name) {//如果没有提供名字,从给的Link中截取最后一坨
name = link.slice(link.lastIndexOf('/') + 1)
}
let eleLink = document.createElement('a')
eleLink.download = name
eleLink.style.display = 'none'
eleLink.href = link
document.body.appendChild(eleLink)
eleLink.click()
document.body.removeChild(eleLink)
}
使用方式:
downloadFile('1.txt','lalalallalalla')
downloadFile('1.json',JSON.stringify({name:'hahahha'}))
window.downFile = function (resBlob, fileName, fileType = '.xls', target = '_self') {
const blob = new Blob([resBlob], {
type: 'application/vnd.ms-excel;charset=utf-8'
})
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
// 兼容IE/Edge
window.navigator.msSaveOrOpenBlob(blob, fileName + fileType)
} else {
const url = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.target = target
a.style.display = 'none'
a.setAttribute('download', fileName + fileType)
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
window.URL.revokeObjectURL(url) // 释放资源
}
}
// 在使用axios请求的时候,加上responseType: 'blob'入参
const res = await this.$http({ data: {}, responseType: 'blob'})
window.downFile(res.blob, '文件下载')
12.取整
function getIntPart(val){
if( typeof val==='number'){
return ~~val;
}else{
return val
}
}
使用方法:
getIntPart(3.4)
13.数字取反
export function reverseNumber(val) {
if (parseFloat(val).toString() == "NaN") {
return val
} else {
return ~val + 1
}
}
reverseNumber(33)
13.禁止右键、选择、复制
;['contextmenu', 'selectstart', 'copy'].forEach(function (ev) {
document.addEventListener(ev, function (event) {
return (event.returnValue = false)
})
})
14.数据类型验证
/
function typeOf(obj) {
const toString = Object.prototype.toString
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object',
'[object FormData]': 'formData'
}
return map[toString.call(obj)]
}
//方法二:
function typeOf(obj) {
// let res = Object.prototype.toString.call(obj).split(' ')[1]
// res = res.substring(0, res.length - 1).toLowerCase()
// return res
// 评论区里提到的更好的写法
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()
}
15.压缩base64格式的图片
//压缩方法
function dealImage(base64, w, callback) {
var newImage = new Image();
var quality = 0.6; //压缩系数0-1之间
newImage.src = base64;
newImage.setAttribute("crossOrigin", 'Anonymous'); //url为外域时需要
var imgWidth, imgHeight;
newImage.onload = function () {
imgWidth = this.width;
imgHeight = this.height;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (Math.max(imgWidth, imgHeight) > w) {
if (imgWidth > imgHeight) {
canvas.width = w;
canvas.height = w * imgHeight / imgWidth;
} else {
canvas.height = w;
canvas.width = w * imgWidth / imgHeight;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
quality = 0.6;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
var base64 = canvas.toDataURL("image/jpeg", quality); //压缩语句
// 如想确保图片压缩到自己想要的尺寸,如要求在50-150kb之间,请加以下语句,quality初始值根据情况自定
// while (base64.length / 1024 > 150) {
// quality -= 0.01;
// base64 = canvas.toDataURL("image/jpeg", quality);
// }
// 防止最后一次压缩低于最低尺寸,只要quality递减合理,无需考虑
// while (base64.length / 1024 < 50) {
// quality += 0.001;
// base64 = canvas.toDataURL("image/jpeg", quality);
// }
callback(base64);//必须通过回调函数返回,否则无法及时拿到该值
}
}
----------------------------------
//这是原来的base64格式字符串
var base64= path;
//这就是你压缩之后的字符串
var str;
//你可以打桩看一下有多长
console.log(base64.length);
//然后调用压缩方法 第一个参数就是原来的字符串,第二个是宽度,第三个就是回调方法,也就是压缩函数最后面那个callback(base64)
dealImage(base64, 500, useImg);
//然后一压 再打个桩看下长度 方法名随便起怎么舒服怎么来
function useImg(base64) {
str= base64;
console.log(str.length);
}
16.获取地址栏置顶参数
//JS写法
const getParam = (url, param) => new URLSearchParams(new URL(url).search).get(param);
//TS写法
const getParam = (url: string, param: string): string | null => new URLSearchParams(new URL(url).search).get(param);
//例子:
getParam('http://domain.com?message=hello', 'message'); // 'hello'
//针对vue去除路由符号
function getUrlKey (name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1].replace(/\+/g, '%20')) || null
}
17.生成随机uuid
const uuid = (a) => (a ? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16) : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid));
18.检查字符串是否只包含字母与数字
const isAlphanumeric = (str) => /^[0-9A-Z]+$/i.test(str);
19.检查字符串是否只包含数字
const isNumeric = (str) => !/[^0-9]/.test(str);
20.检查字符串是否只包含字母
const isAlpha = (str) => /^[A-Z]+$/i.test(str);
21.去除字符串中的HTML
const stripHtml = html => (new DOMParser().parseFromString(html, 'text/html')).body.textContent || ''
22.滚动到页面顶部
const goToTop = () => window.scrollTo(0, 0);
goToTop();
23.判断当前是否是苹果设备
const isAppleDevice = () => /Mac|iPod|iPhone|iPad/.test(navigator.platform);
isAppleDevice();
24.重定向到一个URL
const redirect = url => location.href = url
redirect("https://www.google.com/")
25. 打开浏览器打印框
const showPrintDialog = () => window.print()
showPrintDialog()
26.图片上传
//头像上传
<template>
<div id="idPhoto">
<div class="btn" @click="upload">开始上传</div>
<input style="display:none" id="file" type="file" ref="uploadFile" @change="fileChange" accept="image/*">
<!-- 引用vant中的加载 -->
<van-loading size="24px" v-show="loading" vertical>头像上传中...</van-loading>
</div>
</template>
<script>
//压缩图片base64
function dealImage(base64, w, callback) {
var newImage = new Image();
var quality = 0.6; //压缩系数0-1之间
newImage.src = base64;
newImage.setAttribute("crossOrigin", "Anonymous"); //url为外域时需要
var imgWidth, imgHeight;
newImage.onload = function () {
imgWidth = this.width;
imgHeight = this.height;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (Math.max(imgWidth, imgHeight) > w) {
if (imgWidth > imgHeight) {
canvas.width = w;
canvas.height = (w * imgHeight) / imgWidth;
} else {
canvas.height = w;
canvas.width = (w * imgWidth) / imgHeight;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
quality = 0.6;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
var base64 = canvas.toDataURL("image/jpeg", quality); //压缩语句
// 如想确保图片压缩到自己想要的尺寸,如要求在50-150kb之间,请加以下语句,quality初始值根据情况自定
// while (base64.length / 1024 > 150) {
// quality -= 0.01;
// base64 = canvas.toDataURL("image/jpeg", quality);
// }
// 防止最后一次压缩低于最低尺寸,只要quality递减合理,无需考虑
// while (base64.length / 1024 < 50) {
// quality += 0.001;
// base64 = canvas.toDataURL("image/jpeg", quality);
// }
callback(base64); //必须通过回调函数返回,否则无法及时拿到该值
};
}
export default {
name: "MyAppIdphoto",
data() {
return {
imgUrl: "",
loading: false,
};
},
mounted() {},
methods: {
upload() {
this.$refs.uploadFile.click();
},
// 选择后的图片文件对象转base64
fileChange() {
var _this = this;
_this.loading = true;
var files = document.getElementById("file").files;
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = function () {
var base64 = this.result;
// console.log(base64.length);
var str;
//压缩base64
dealImage(base64, 500, useImg);
//拿到压缩后的base64
function useImg(base64) {
str = base64; //拿到返回后的base64
_this.$store.commit("SET_IMG", base64);
_this.$toast("头像上传成功!");
}
};
},
},
};
</script>
27. 根据url转换图片(base64)
function getBase64(url, callback) {
var Img = new Image(),
dataURL = '';
Img.src = url + '?v=' + Math.random();
Img.setAttribute('crossOrigin', 'Anonymous');
Img.onload = function() {
var canvas = document.createElement('canvas'),
width = Img.width,
height = Img.height;
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(Img, 0, 0, width, height);
dataURL = canvas.toDataURL('image/jpeg');
return callback ? callback(dataURL) : null;
};
}
--------------
//使用:
let imgUrl='xxx'
getBase64(imgUrl, dataURL => {
console.log(dataURL:就是base64了)
});
28.压缩图片base64体积
function dealImage(base64, w, callback) {
var newImage = new Image();
var quality = 0.6; //压缩系数0-1之间
newImage.src = base64;
newImage.setAttribute("crossOrigin", "Anonymous"); //url为外域时需要
var imgWidth, imgHeight;
newImage.onload = function () {
imgWidth = this.width;
imgHeight = this.height;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
if (Math.max(imgWidth, imgHeight) > w) {
if (imgWidth > imgHeight) {
canvas.width = w;
canvas.height = (w * imgHeight) / imgWidth;
} else {
canvas.height = w;
canvas.width = (w * imgWidth) / imgHeight;
}
} else {
canvas.width = imgWidth;
canvas.height = imgHeight;
quality = 0.6;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
var base64 = canvas.toDataURL("image/jpeg", quality); //压缩语句
// 如想确保图片压缩到自己想要的尺寸,如要求在50-150kb之间,请加以下语句,quality初始值根据情况自定
// while (base64.length / 1024 > 150) {
// quality -= 0.01;
// base64 = canvas.toDataURL("image/jpeg", quality);
// }
// 防止最后一次压缩低于最低尺寸,只要quality递减合理,无需考虑
// while (base64.length / 1024 < 50) {
// quality += 0.001;
// base64 = canvas.toDataURL("image/jpeg", quality);
// }
callback(base64); //必须通过回调函数返回,否则无法及时拿到该值
};
}
//进行使用 第三个参数为回调
dealImage(base64, 500, useImg);
function useImg(){
//通过回调拿到压缩后的base64
}
29. 视频倍速播放
// html
<video id="myVideo" src="./xx.mp4" type="video/mp4></viedeo>
// js
myVideo.setAttribute('playbackRate', '1.5')//依赖于playbackRate属性
30. 将单引号字符串数组转为真数组
const arr = "['啊', '啊啊', '啊啊啊']"
console.log(JSON.parse(arr.replace(/'/g, '"'))) // ['啊', '啊啊', '啊啊啊']
31. DES加密解密
//npm install crypto-js 安装插件
import CryptoJS from "crypto-js";
const key = "Nj1Hsjc2"; //密钥(加解密密钥同一个)
//加密
export const encryptDes = message => {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString(); //返回base64格式密文
//return encrypted.ciphertext.toString(); //返回hex格式密文
};
//解密
export const decryptDes = ciphertext => {
const keyHex = CryptoJS.enc.Utf8.parse(key);
//decode解码(针对百分号等
ciphertext = decodeURIComponent(ciphertext) //decodeURLComponent比decoURL更强大,可以解码任何t
// direct decrypt ciphertext
const decrypted = CryptoJS.DES.decrypt(
{
//ciphertext: CryptoJS.enc.Hex.parse(ciphertext) //转hex格式
ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
},
keyHex,
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}
);
return decrypted.toString(CryptoJS.enc.Utf8);
};
32.防抖、节流函数
//防抖函数:(多次触发,只生效最后一次的)关注结果 相当于lol 回城
function debounce(fn, delay = 200) {
let timer = 0;
return function () {
if (timer) clearInterval(timer)//清零之前的
timer = setTimeout(() => {
fn.apply(this, arguments); // 透传 this 和参数
timer = 0;
}, delay)
console.log('timer', timer);
}
}
//案例:
let input = document.getElementById('input');
input.addEventListener('keyup', debounce(() => {
console.log('触发防抖');
}, 300))
//节流函数:(连续触发事件,在一段时间内只触发一次 多次点击,固定时间内触发一次)关注过程 相当于 技能cd
//方法一:
let timer = null
export // 第三种:结合了前俩种的写法,我认为这样封装相对完美
function Throttle (fn ,time) {
let startTime = Date.now()
return function() {
let nowTime = Date.now()
clearTimeout(timer)
if (nowTime - startTime >= time){ // 时间范围允许立即执行
fn.apply(null,arguments)
startTime = Date.now()
}else {
timer = setTimeout(()=>{
fn.apply(null,arguments)
}, time)
}
}
}
//方法二:
let last
export const Throttle = (fn, t) => {
let interval = t || 500
return (function () {
let args = arguments
let now = +new Date()
if (last && now - last < interval) {
} else {
last = now
fn.apply(this, args)
}
})()
//注:可以使用loadash库
// 1.安装 npm i --save lodash
// 2. 引入 import * as _ from 'lodash'
//防抖:
_.debounce(function(){
console.log('你好啊')
},1000)
//节流:
_.throttle(func, [wait=0], [options=])
//带立即执行和取消防抖的 防抖函数处理逻辑
<body>
<button id="debounce">点击</button>
<button id="dd">取消</button>
<script>
var mydebounce = document.getElementById("debounce")
var Mydebounce = document.getElementById("dd")
var set = debounce(sayDebounce,5000,true) //true可以立即执行
mydebounce.addEventListener("click",set)
Mydebounce.addEventListener("click",function () {
set.cancel() //取消debounce
} )
//防抖函数
function debounce(fn,time,immediate) {
let timer = null
let debounced = function () {
let context = this
let args = arguments
if(timer) clearTimeout(timer) //清除前一个定时器
if (immediate) { //为true立即执行
let callNow = !timer
timer = setTimeout(()=>{
timer = null
},time || 500)
if (callNow) fn.apply(context,args)
}
else { //非立即执行
timer = setTimeout(function(){
fn.apply(context, args)
}, time || 500);
}
}
debounced.cancel = function() { //取消防抖
clearTimeout(timer);
timer = null;
};
return debounced
}
//要防抖的事件处理
function sayDebounce() {
console.log("处理防抖的事件写在这里,比如发送请求");
}
</script>
</body>
33.滚动加载
//监听页面滚动事件,分析clientHeight、scrollTop、scrollHeight三者的属性关系。
window.addEventListener('scroll', function() {
const clientHeight = document.documentElement.clientHeight;
const scrollTop = document.documentElement.scrollTop;
const scrollHeight = document.documentElement.scrollHeight;
if (clientHeight + scrollTop >= scrollHeight) {
// 检测到滚动至页面底部,进行后续操作
// ...
}
}, false);
34.渲染大数据
setTimeout(() => {
// 插入十万条数据
const total = 100000;
// 一次插入的数据
const once = 20;
// 插入数据需要的次数
const loopCount = Math.ceil(total / once);
let countOfRender = 0;
const ul = document.querySelector('ul');
// 添加数据的方法
function add() {
const fragment = document.createDocumentFragment();
for(let i = 0; i < once; i++) {
const li = document.createElement('li');
li.innerText = Math.floor(Math.random() * total);
fragment.appendChild(li);
}
ul.appendChild(fragment);
countOfRender += 1;
loop();
}
function loop() {
if(countOfRender < loopCount) {
window.requestAnimationFrame(add);
}
}
loop();
}, 0)
35.计算两个坐标点(经纬度)的距离
// 方法定义 lat,lng
function GetDistance( lat1, lng1, lat2, lng2){
var radLat1 = lat1*Math.PI / 180.0;
var radLat2 = lat2*Math.PI / 180.0;
var a = radLat1 - radLat2;
var b = lng1*Math.PI / 180.0 - lng2*Math.PI / 180.0;
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
s = s *6378.137 ;// EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
}
// 调用 return的距离单位为km
GetDistance(10.0,113.0,12.0,114.0)
36. 判断一个日期是否是工作日
const isWeekday = (date) => date.getDay() % 6 !== 0;
console.log(isWeekday(new Date(2021, 0, 11)));
// Result: true (周一)
console.log(isWeekday(new Date(2021, 0, 10)));
// Result: false (周日)
37.判断一个数字是奇数还是偶数
const isEven = num => num % 2 === 0; //偶数
console.log(isEven(2));
// Result: true
console.log(isEven(3));
// Result: false
38. 检查当前设备是否是苹果设备
const isAppleDevice = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
console.log(isAppleDevice);
// Result: 是苹果设备会返回 True
39. 获取所有参数的平均值
const average = (...args) => args.reduce((a, b) => a + b) / args.length; //通过reduce函数计算
average(1, 2, 3, 4);
// Result: 2.5
40. 转换华氏/摄氏度
const celsiusToFahrenheit = (celsius) => celsius * 9/5 + 32;
const fahrenheitToCelsius = (fahrenheit) => (fahrenheit - 32) * 5/9;
// Examples
celsiusToFahrenheit(15); // 59
celsiusToFahrenheit(0); // 32
celsiusToFahrenheit(-20); // -4
fahrenheitToCelsius(59); // 15
fahrenheitToCelsius(32); // 0
41.冒泡排序
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { //相邻元素两两对比
var temp = arr[j+1]; //元素交换
arr[j+1] = arr[j];
arr[j] = temp;
}
// ES6 写法
// if (arr[i] > arr[j]) {
// [arr[i],arr[j]] = [arr[j],arr[i]];
//}
}
}
return arr;
42.实现一行文内两端对齐
//text-align-last,该属性定义的是一段文本中最后一行在被强制换行之前的对齐规则。
text-align-last:justify
vue相关
1.自定义聚焦指令
//全局指令 main.js中
import Vue from 'vue'
Vue.directive("fofo",{
inserted(el) {
// 判断拿到的元素名称
if (el.nodeName === 'INPUT' || el.nodeName === 'TEXTAREA') {
el.focus()
} else {
// 尝试向内层获取一下
el.querySelector('input').focus()
}
}
})
//第二种
mounted周期,ref+querySelector获取input标签,调用focus()
搜索相关
1.联想关键字高亮
//参数一接收被修改字符串,参数二要匹配的关键字
export const lightFn = (str, targetStr) => {
// 忽略大小写且全局匹配
const reg = new RegExp(targetStr, 'ig')
return str.replace(reg, match => {
return `<span style="color:red">${match}</span>`
})
}
插件类使用
1. htmlCanvas
//作用:dom 转图片
注意点:
1.使用background背景图转换会导致图片模糊不清,可以使用img标签展示
2.建议使用npm install --save html2canvas@1.0.0-rc.4 版本 新版本在ios13.4上有兼容问题
3.解决ios15.1系统生成时会刷新页面,图片存储异常丢失问题:
给所有被绘制的标签设置字体:比如 font-family: sans-serif;(根标签写就可以了)
4.html2canvas动态加载内容,通过canvas转换出来的数据,图片为空
问题分析:
内容是动态加载进来的,转换肯定是在请求完毕之后再去转换,但是在请求完毕之后去转换,按理说所需要的所有数据都已经到达前端,应该可以转换,经过思考,发现图片内容从后台读取需要一定时间去解析,才能够完整的将图片资源展示出来,html2canvas是将页面上显示的dom元素,经过解析将dom画在canvas上在转换为image图片格式。
//解决方法:
让html2canvas转换代码等待一定时间,在进行转换操作,可进行转换。定时器处理
// 1.安装依赖
npm install --save html2canvas@1.0.0-rc.4
//2.使用
<template>
<div>
<div ref="canvas">html2Canvas</div>
<button @click="toImg">生成图片</button>
</div>
</template>
<script>
import html2canvas from "html2canvas"
export default {
methods: {
toImg() {
const opts = {
scale: 5, //图片清晰度的保证(一般设2)
useCORS: true, //允许图片跨域,一定要开启
backgroundColor: "#fff", //画布背景色
};
(window.html2canvas || html2canvas)(this.$refs.canvas, opts).then(canvas => {
let dataURL = canvas.toDataURL(""); //将canvas 转为 img标签需要的base64
console.log(dataURL);
})
}
}
}
</script>
//截图并转为图片文件保存
//获取截图区域
function html2canvas(document.getElementById("xxxx").get, {
backgroundColor: null,
useCORS: true
}).then(canvas => {
let dataURL = canvas.toDataURL("image/png");
let formObj = new FormData();
formObj.append("uploadFile", this.base64ToBlob(dataURL));
});
//进行转换
function base64ToBlob(urlData) {
var arr = urlData.split(",");
var mime = arr[0].match(/:(.*?);/)[1] || "image/png";
// 去掉url的头,并转化为byte
var bytes = window.atob(arr[1]);
// 处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
// 生成视图(直接针对内存):8位无符号整数,长度1个字节
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
console.log(new Blob([ab], { type: mime }));
return new Blob([ab], {
type: mime
});
}
2. dom-to-image
//1.安装
npm install dom-to-image
//2.引入
import domtoimage from 'dom-to-image';
//3.使用
downLoadPhoto () {
const node = document.getElementById('table')//对应的html标签id
// domtoimage.toSvg(node) 转
domtoimage.toPng(node)
.then((dataUrl) => {
const img = new Image()
img.src = dataUrl
// 将获取到的base64下载下来
const imgUrl = img.src
if (window.navigator.msSaveOrOpenBlob) {
const bstr = atob(imgUrl.split(',')[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
const blob = new Blob([u8arr])
window.navigator.msSaveOrOpenBlob(blob, 'chart-download' + '.' + 'png')
} else {
// 这里就按照chrome等新版浏览器来处理
const a = document.createElement('a')
a.href = imgUrl
a.setAttribute('download', 'chart-download')
a.click()
}
})
}