什么? 方法还能这么用? 开发效率意想不到

220 阅读2分钟

复制文本到剪切板

/**
 * 复制文本到剪切板
 * @param {String} text 要复制的内容
 * @param {Function} callback 回调
 */
export const copyText = (text, callback) => {
  var tag = document.createElement("input");
  tag.setAttribute("id", "cp_hgz_input");
  tag.value = text;
  document.getElementsByTagName("body")[0].appendChild(tag);
  document.getElementById("cp_hgz_input").select();
  document.execCommand("copy");
  document.getElementById("cp_hgz_input").remove();
  if (callback && typeof callback == "function") {
    callback(text);
  }
}

获取当前选中文本内容

// 获取选中文本内容
const getSelection = () => window.getSelection().toString()

下载

1. 下载内容(文件流形式)

/**
 * H5下载内容(文件流形式)
 * @param {String} content 下载内容
 * @param {String} filename 文件名
 */
export const downFile = (content, filename) => {
  var ele = document.createElement('a');
  ele.download = filename;
  ele.style.display = 'none';
  var blob = new Blob([content]);
  ele.href = URL.createObjectURL(blob);
  document.body.appendChild(ele);
  ele.click();
  document.body.removeChild(ele);
};

2. 下载文件(URL形式)

/**
 * 下载文件(URL形式)
 * @param {String} url 下载地址
 * @param {String} filename 文件名
 */
export const downFile = (url, filename) => {
  let ele = document.createElement("a");
  ele.download = filename;
  ele.href = url;
  document.body.appendChild(ele);
  ele.click();
  document.body.removeChild(ele);
  ele.click();
}

3.下载在线文件

使用上述方法 downFile 下载文件, 如果是PDF格式的, 会直接在浏览器中打开,而非下载,因此需将文件转换为文件流形式再下载。

/**
 * 下载在线文件
 * @param {String} url      网络地址
 * @param {String} filename 文件名
 */
export const downloadFile = (url, filename) => {

  const xhr = new XMLHttpRequest();
  xhr.open("GET", url, true);
  xhr.responseType = "blob";

  xhr.onload = function () {
    const blob = xhr.response;
    const link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = filename; // 下载时的文件名,可自行更改

    link.click();
    window.URL.revokeObjectURL(link.href);
  };

  xhr.send();
}

图片转base64

/**
 * 图片转base64
 * @param {String} src 图片地址(网络图片/本地图片)
 * @returns base64 图片地址
*/
export const Image2Base64 = (src) => {
  return new Promise((resolve, reject) => {

    var img = new Image();
    img.src = src
    img.crossOrigin = "anonymous";

    img.onload = function() {
      var canvas = document.createElement("canvas");
      canvas.width = img.width;
      canvas.height = img.height;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, img.width, img.height);
      var base64 = canvas.toDataURL("image/png");

      resolve(base64)
    }
  })
}
// base64 转文件流
 base64toFile (dataurl, filename) {
      var arr = dataurl.split(',')
      var mime = arr[0].match(/:(.*?);/)[1]
      var bstr = atob(arr[1])
      var n = bstr.length
      var u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
}

获取地址栏参数

/**
 * 获取地址栏参数
 * @param {String} 	name 	地址栏参数名称
 * @param {String} 	url 	地址栏全地址,不传自动取地址栏
 */
export const getQueryString = (name, url) => {
	if (url && url.split('?').length == 2) {
		url = url.split('?')[1]
	} else {
		url = window.location.search.substr(1)
	}
	var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
	var r = url.match(reg);
	if (r != null) return unescape(r[2]);
	return null;
}

设置不同环境是否显示打印信息(console.log)

根据不同的环境,设置是否显示打印信息,一般我们生产环境考虑到内存外溢,会屏蔽 console 相关打印信息,但是开发偶尔会忘记删除,导致外溢。因此,可通过以下代码实现取消打印。

注意:需放在全局调用

/**
 * 否开启日志调试,True 输出 False 不输出
 * 
 * @param {Object} 
 * @param {Boolean} params.development  开发环境
 * @param {Boolean} params.staging      测试环境
 * @param {Boolean} params.production   生产环境
 * */
export const consoleConfig = ({
  development = false,
  staging = false,
  production = false,
}) => {
  console_log = {
    development,
    staging,
    production,
  }
  let nodeDev = Object.keys(console_log).find((key) => {
    return process.env.NODE_ENV === key
  })

  var logDebug = console_log[nodeDev];
  console.log = (function(oriLogFunc) {
    return function() {
      if (logDebug) {
        oriLogFunc.apply(this, arguments);
      }
    }
  })(console.log);
}

隐藏手机号中间4位

/**
 * 隐藏手机号中间4位
 * @param {String} phone  11位手机号
*/ 
export const replaceByPhone = (phone) => phone.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2');

禁止浏览器双指缩放

const doubleZoomDisable = () => {
  window.addEventListener(
    "mousewheel",
    function (event) {
      if (event.ctrlKey === true || event.metaKey) {
        event.preventDefault();
      }
    },
    { passive: false }
  );

  //firefox
  window.addEventListener(
    "DOMMouseScroll",
    function (event) {
      if (event.ctrlKey === true || event.metaKey) {
        event.preventDefault();
      }
    },
    { passive: false }
  );
}

范围内生成不重复的数字

/**
 * 范围内生成不重复的数字,返回值中会带有arr
 * @param {Number} arr 	    当前已有数据,根据业务需要此处可自行决定是否深度拷贝
 * @param {Number} maxIndex 返回最大数字
 * @param {Number} multiple 是否返回多个
 * 
 @returns 当前生成的数字(下标形式)
 */
export const getNumNoRepeat = (exists = [], maxIndex = 10, multiple = false) => {
	let times = maxIndex * 10; // 最多循环取值,超出返回 -1
	let indexs = [...exists];
	const getSingle = () => {
		do {
			var num = Math.floor(Math.random() * maxIndex);
			if (-1 == indexs.indexOf(num)) { //数组中不存在
				indexs.push(num);
				return num;
			}
			times -= 1;
			if (times == 0) return -1
		} while (times);

	}
	if (!multiple) {
		// 单条
		return getSingle()
	} else {
		// 多条
		if (exists.length > maxIndex) return []
		for (let i = 0; i <= maxIndex - exists.length; i++) {
			getSingle();
		}
		return indexs
	}
}

例如:

// 生成5以内包含[1,5]的不重复数字
getNumNoRepeat3([1, 5], 5, true) // [1, 5, 2, 0, 4]

// 生成5以内的不重复数字
getNumNoRepeat3([], 5, true) // [2, 4, 1, 3, 0]

解决微信小程序富文本内容中字体颜色失效问题

/**
 * html富文本内容 - font的color属性改为style中添加color
 * @example <font color="#348aff" />  =>  <font style="color: #348aff" />
 */
export const fontColor2StyleColorByHtml = (str) => {
    return str.replace(/\<font\s*color=(.*?)\s*>/ig, "<font style=\"color:$1\">")
}

随机生成十六进制

// 随机生成十六进制
const generateHex = () => `#${(~~(Math.random() * (1 << 24))).toString(16).padEnd(6, '0')}`

前端实现网络图片批量下载

前端实现网络图片批量转base64、写入zip、批量下载

/**
 * 前端实现网络图片批量下载
 * @description 该方法需要安装 jszip 依赖包
 * 
 * @param {Array}   files             需要下载的图片数组
 * @param {String}  files[].filePath  图片网络地址
 * @param {String}  files[].fileName  图片名称,不填写取 filePath
 * @param {String}  zipName           zip 名称
 * @param {String}  success           成功回调
 * @param {String}  fail              失败回调
 * 
 */
export const networkImageToZip = async ({
  files = [],
  zipName = 'demo',
  success,
  fail
}) => {
  let startTime = new Date().getTime();

  // 加入zip文件
  function addToZip(zip, base64, name) {
    return new Promise((resolve, reject) => {
      //过滤base64格式
      let image = base64.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
      let imageNames = `${name}.png`;
      zip.file(imageNames, image, {
        base64: true
      });
      resolve();
    });
  }

  //下载zip文件到本地
  function createZip(zip) {
    zip
      .generateAsync({
        type: "blob",
      })
      .then((content) => {
        let endTime = new Date().getTime();
        console.warn(`下载用时: ${endTime - startTime}ms`);
        success && success()
        saveAs(content, `${zipName}.zip`);
      })
      .catch((err) => {
        fail && fail(err)
      });
  }

  try {
    const JSZip = require("jszip")
    const zip = new JSZip();

    // 网络地址转base64
    let base64s = await Promise.all(
      files.map((item) => {
        return new Promise(async (resolve, reject) => {
          var xhr = new XMLHttpRequest()
          xhr.open('get', item.filePath, true)
          xhr.responseType = "blob";
          xhr.onload = function () {
            if (this.status === 200) {
              let oFileReader = new FileReader();
              oFileReader.onloadend = function (e) {
                resolve({
                  base64: e.target.result,
                  fileName: item.fileName || item.filePath,
                });
              };
              oFileReader.readAsDataURL(this.response);
            }
          }
          xhr.send();
        });
      })
    )

    // base64 写入 zip 文件
    base64s.map(async (it) => {
      await addToZip(zip, it.base64, it.fileName);
    });

    createZip(zip);
  } catch (err) {
    fail && fail(err)
  }
}

禁止用户按F12启用开发者模式

在项目上线后,用户可以通过F12查看代码接口等信息,此时调用以下方法可以阻止用户此操作,效果如下:

image.png

/**
 * 禁用开发者模式(f12)
 * @param {String} path       跳转路径
 * @param {String} innerHTML  页面提示内容,支持html
 */
export const developingMode = (path, innerHTML) => {
  (function noDebuger() {
    function testDebuger() {
      var d = new Date();
      debugger;
      if (new Date() - d > 10) {
        document.body.innerHTML = `<div style="width: 100%;height: 100vh;font-size: 30px;text-align: center;font-weight: bold;">${innerHTML || '不要这样子啦~'}<a href="${path}" target="_blank" style="cursor: pointer; color:#4285f4;">点击返回</a>~</div>`;
        return true
      }
      return false
    }

    function start() {
      while (testDebuger()) {
        testDebuger()
      }
    }
    if (!testDebuger()) {
      window.onblur = function() {
        setTimeout(function() {
          start()
        }, 500)
      }
    } else {
      start()
    }
  })();
  var x = document.createElement('div');
  Object.defineProperty(x, 'id', {
    get: function() {
      var a = "";
      for (var i = 0; i < 99999999999; i++) {
        a = a + i.toString()
      }
    }
  });
  window.onkeydown = window.onkeyup = window.onkeypress = function(a) {
    if (a.keyCode == 123) {
      document.querySelector("body div").append("TIHI!@#$%^&*()_+)()*&*^&TGYGJGYGuygT^&6746t78t78g785tgyuGGIUGOIUB&^Y(*^&^$$&*G*GUIGUOUIYUIT&*%$^%#^%ER^%RF&FGIY*G*&^T*(G*O")
    }
  }
}

时间格式化

/**
 * 时间格式化
 * @param {*} time
 */
export function formatDate(time) {
  if (!time) return "";
  const date = new Date(time);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

padStart 方法用来确定字符串长度, 不足用0补全

实现文字打字输出效果


/**
 * 实现文字打字输出效果
 * @param {number} textElement
 * @param {string} delay
 */
export const typewriterEffect = (textElement, delay = 100) => {
  const text = textElement.textContent;
  textElement.textContent = "";

  let i = 0;
  const timer = setInterval(() => {
    textElement.textContent += text[i];
    i++;

    if (i === text.length) {
      clearInterval(timer);
    }
  }, delay);
}

使用

// <div id="text">打字效果打字效果打字效果打字效果打字效果打字效果打字效果</div>

typewriterEffect(document.getElementById("text"), 100);

JS八大类型判断

/**
 * 数据类型判断
 * @param {*} _ 
 * @returns {String} 输出类型: [Number|String|Boolean|Undefined|Null|Object|Array|Function]
 */
const typeOf = (_) => Object.prototype.toString.call(_).slice(8, -1);

测试结果如下:

typeOf(1);  // Number
typeOf("1"); // String
typeOf(true); // Boolean
typeOf(null); // Null
typeOf(undefined); // Undefined
typeOf(Symbol(1)); // Symbol
typeOf({}); // Object
typeOf([]); // Array
typeOf(function () { }); // Function
typeOf(new Date()); // Date
typeOf(new RegExp()); // RegExp