验证 undefined 和 null
if(a === null && a === undefined){
doSomething();
}
// 如果 a 是只需 验证 为 null 和 undefined 时
// 可以精简成
a ?? doSomething();
// 空值运算符 (??) 是一个逻辑操作符,当左侧的操作数为 null 或者 undefined时, 返回其右边操作数,否则返回左侧操作数。
数组元素中的每一项转化为数字。
const arr = ['1','2','3','-45','1.45'];
arr.map(Number); // [ 1 , 2 , 3 , -45 , 1.45 ]
禁止浏览器回退
//禁止回退
window.location.hash = "no-back";
window.location.hash = "Again-No-back-button";
window.onhashchange = function () { window.location.hash = "no-back"; }
js 监听浏览器页面切换
document.addEventListener('visibilitychange',function(){
if (document.visibilityState=='hidden') {
//切离该页面时执行
} else if (document.visibilityState=='visible') {
//切换到该页面时执行
}
});
比较两个对象是否是相等的
vue 源码中的算法 !!(没有考虑正则表达式)
- js中对象是无法使用 == 来比较的, 因为比较的是内存地址 一定是 false
- 我一般会定义如果对象的各个属性都相等,那么对象就是相等的对象,例如: {} 与 {} 相等
算法描述 (抽象一下 就是判断两个集合是否相等)
- 假定对象 a 和 b
- 遍历a中的成员,判断是否每一个 a 中的成员都在 b 中,并且 与 b 中的对应成员相等。
- 遍历b中的成员,判断是否每一个 b 中的成员都在 a 中,并且 与 a 中的对应成员相等。
- 如果成员是引用类型, 递归
export function looseEqual (a: any, b: any): boolean {
if (a === b) return true
const isObjectA = isObject(a)
const isObjectB = isObject(b)
if (isObjectA && isObjectB) {
try {
const isArrayA = Array.isArray(a)
const isArrayB = Array.isArray(b)
if (isArrayA && isArrayB) {
return a.length === b.length && a.every((e, i) => {
return looseEqual(e, b[i]) // 这里是在判断a 里面的成员是不是都在b里面
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime() // 单独处理了 Date 类型, 时间戳应该是一样的
} else if (!isArrayA && !isArrayB) {
const keysA = Object.keys(a)
const keysB = Object.keys(b)
// 先判断 key 长度, 再判断 a 包含 b
return keysA.length === keysB.length && keysA.every(key => {
return looseEqual(a[key], b[key])
})
} else {
/* istanbul ignore next */
return false
}
} catch (e) {
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b)
} else {
return false
}
}
// 判断是否为对象
export function isObject (obj: mixed): boolean %checks {
return obj !== null && typeof obj === 'object'
}
base64转文件流
var data = new FormData(); // 创建 FormData
const file = base64ToFile("base64文件");
data.append("file", file); // 将这个 文件流 加入
//此时这个 data 就是文件流格式了就能当参数使用了
function base64ToFile(dataurl:string, filename = "file") {
//将base64转换为文件
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
//封装的 post 请求
const instance = axios()
interface Options {
params?: unknown;
headers?: unknown;
}
post(url: string, data?: unknown, headers?: unknown, params?: unknown):any {
const options: Options = {}
if (headers) {
options.headers = headers
}
if (params) {
options.params = params
}
return instance.post(url, data, options)
},
//在vue中
接口(params?: unknown) {
return axios.post(`${url}/app/qxjgl/saveCommentPicture`, params,{"Content-Type":"multipart/form-data"});
},
// 请求头 一般使用 {"Content-Type":"multipart/form-data"}
!! 注意 千万 不要 给参数 序列化 config.data = qs.stringify(config.data)
三秒钟连续点击超过8下打开 隐藏元素
let count = 0;
let lastClickTime = 0;
function showddd() {
const nowTime = new Date().getTime();
if (count === 0) {
lastClickTime = nowTime;
count++;
} else if (nowTime - lastClickTime < 3000) {
lastClickTime = nowTime;
count++;
} else {
count = 0;
}
if (count >= 8) {
const element = document.getElementById("DOM");
element!.style.display = "block";
}
}
自定义指令 点击 元素内部外部
<div V-click-outside>
<input type="text" :value="formatDate">
<div class="panneu" v-if="isVisible">
content
<button></button>
/div>
</div>
directives:{
clickOutside:[ // 指令的生命周期
bind(el,bindings,vnode){ // context
// 把事件绑定给document上 看一下点击的是否是当前这个元素内部let handler = (e)=>[
if(el.contains(e.target)){
// 判断一下是否当前面板已经显示出来了if(!vnode.context.isVisible){vnode.context.focus();
}elsef
if(vnode.context.isVisible){vnode.context.blur();
el.handler = handler;
document.addEventListener('click',handler)
unbind(el){
document.removeEventListener('click',el.handler)
}
}
前端实现一个 sleep函数
const sleep = (duration) => new Promise((resolve) => setTimeout(resolve, duration));
使用 生成器 解决回调地狱问题
// 生成器其实就是一个特殊的函数
function * gen(){
yield '111';
yield '222';
yield '333';
}
let iterator = gen(); //定义的生成器不能直接调用需要调用next方法
iterator.next();
//一个Generator函数与普通function的区别就是函数名前面多了一个星号 * 但是执行时有很大不同,与yield命令配合,可以实现暂停执行的功能
//生成器可以解决 回调地狱的问题
//示例:
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(111);
iterator.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log(111);
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
vue .once 方法实现
export function once (fn: Function): Function {
let called = false //是否调用过
return function () {
if (!called) {
called = true
fn.apply(this, arguments)
}
}
}
div 键盘事件失效
<div @keyup="onRockingBar" tabindex="0" style="outline: 0">
- tabindex="0" 加上这个属性即可。
- 不希望出现白框 style="outline: 0"