各类工具函数


工具函数大集

各类工具函数

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()
      }
    })
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值