赞
踩
onclick //左键点击
oncontextmenu //右键点击
onmouseover //鼠标移入 (冒泡,每次悬停触发一次)
onmousemove //鼠标移动 (每次移动都触发)
onmouseout //鼠标移出
onmousedown //鼠标在元素上按下
onmouseup //鼠标在元素上弹起
onmouseenter //鼠标移入 (不冒泡)
onmouseleave //鼠标移出 (不冒泡)
ondbclick //鼠标双击
onchange //内容改变
onfocus //获取焦点
onblur //失去焦点
ontimeupdate //媒体元素播放时间改变
var num = 10;
typeof: //判断变量的数据类型
Number //数值型
String //字符型
Boolean //布尔值
Array //数组
Object //对象
null //空值
undefined //未定义
//js 内置变量
top
parent
//转成 number
Number(str) //string -> number
Number(true) //boolean -> number (true:1 false:0)
parseInt(str) //string -> number (不保留小数)
parseFloat(str) //string -> number (保留小数)
//转成 string
String(val) // -> string (包含null和undefined)
.toString() //number -> string (null和undefined时报错)
String.charCodeAt(ascii) //ascii -> string
JSON.stringify //json -> string
JSON.parent(str) //string -> json (必须符合json格式)
//转成 bool
Boolean(val) // 0/NaN/null/undefined -> false
document.getElementById('app') //通过id获取
document.getElementsByClassName('box') //通过类名获取
document.getElementsByTagName('div') //通过标签名获取
document.querySelector('.box') //获取符合条件的第一个
document.querySelectorAll('.box') //获取所有符合条件的
var app = document.getElementById('app');
app.innerHTML //获取节点html格式文本
app.innerText //获取节点纯文本
app.innerHTML = '<h2>hello</h2>' //设置节点html格式文本
app.innerText = '<h2>hello</h2>' //设置节点纯文本 (不解析标签,原样输出)
//获取 设置样式
app.style.width //获取宽
app.style.fontSize //获取字体大小 (驼峰式写法)
input[0].getAttribute('type') //获取属性值 (获取类型)
input[0].className //获取类名
input[0].className = 'box' //设置类名
var input = document.getElementsByTagName('input');
input[0].value //获取表单节点输入内容
input[0].value = 'admin' //设置表单输入框内容
input[0]["type"] //获取属性
input[0]["type"] = 'checkbox' //设置属性
节点滚动
// 父节点滚动到指定位置
[pdom].scrollTo({
left: 100,
behavior: 'smooth'
});
// 使指定子节点显示在可视区域内容
[cdom].scrollIntoView({ behavior: 'smooth' });
arr.concat(arr2) //合并数组,返回新数组 arr.length //获取数组长度,返回长度 arr.push(val1) //数组尾部追加内容 arr.unshift(val1) //数组头部添加内容 arr.pop() //删除数组最后一个元素,返回删除的元素 arr.reverse() //数组反序输出 arr.toString() //将数组拼接成一个字符串 arr.splice(start, num, val1) //数组操作 (1:开始位置 2:数量 3:值) arr.slice(start, num) //数组截取 (1:开始位置 2:数量) arr.indexOf(str) //查找数组指定元素,返回索引 arr.lastIndexOf(str) //反向查找数组指定元素,返回索引 arr.includes(str) //在数组中查找元素,返回true/false arr.join("-") // 将数组的元素合并成一个字符串,用指定字符分割 arr.find((val, index, arr) => { // 查找第一个符合条件的元素,返回 return val > 10; }) arr.findIndex((val, index, arr) => { // 与find()类似,返回下标 return val > 10; }) arr.falt(Infinity) // 返回一维数组 [1,2,3,4],参数为 Infinity,表示无论几层,都转成一维数组 // 不兼容所有浏览器 arr.fill(val, statrt, end) // 填充一个数组(覆盖一个数组)(1.填充的值 2.开始填充的位置 3.结束填充的位置) arr.toString().split(',') // 数组扁平化 返回的元素是String Array.of(10,20,30) // 转成数组,创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型 // (有几个参数就有几个数组元素) Array.from() // 转成数组,从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例 // (尽量还原数组,浅拷贝)
sort 排序
let arr = [
{ id: 15, name: "a" },
{ id: 12, name: "b" },
{ id: 13, name: "c" },
{ id: 2, name: "d" },
{ id: 5, name: "e" }
]
// 普通用法
arr.sort()
// 升级用法
let result = arr.sort((a, b) => {
return a.id - b.id
})
delete obj["key"]; // 删除对象属性
Object.keys(obj).length // 获取对象长度
Object.is(obj1, obj2) // 比较两个对象是否相等
Object.assign(obj, obj1, obj2) // 合并对象,返回第一个对象
Object.prototype.toString.call(123) // 判断数据类型 例:[object Number]
obj.hasOwnProperty("a") // 判断对象上是否有指定属性
extend 合并对象
// 1.是否深拷贝 2.参数1 3.参数2... function extend(){ let deep = false let newObj = {} let i = 1 if(typeof arguments[0] === 'boolean'){ i++ deep = arguments[0] } newObj = arguments[i - 1] for(; i<arguments.length; i++){ for(let key in arguments[i]){ let copy = arguments[i][key] if(deep && newObj[key] && typeof copy === 'object'){ newObj[key] = extend(newObj[key], copy) } else { newObj[key] = copy } } } return newObj } let result = extend(false, obj1, obj2, obj3, obj4)
// 获取时间戳
var date = new Date();
date.getTime() //时间戳
date.valueOf() //时间戳
Number(date) //时间戳
+date //时间戳
Date.parse(date) //时间戳
var date = new Date();
date.getFullYear() //年份 (2020)
date.getMonth() //月份 (5+1 -- 比实际月份少1)
date.getDate() //日 (14)
date.getHours() //时
date.getMinutes() //分
date.getSeconds() //秒
date.getMilliseconds() //毫秒
* date.toLocaleString() //格式化字符串 (2020-6-14 21:13:15)
date.toString() //时间转成字符串 (Sun Jun 14 2020 21:12:21 GMT+0800 (GMT+08:00))
date.toLocaleDateString() //日期部分 (2020-6-14)
date.toLocaleTimeString() //时间部分 (21:15:11)
Math.abs(-10) //绝对值 (10) Math.pow(2, 31) //取幂值 (次方2^31) Math.ceil(1.1) //向上取整 (2) Math.floor(1.9) //向下取整 (1) Math.max(1,2,3) //取最大值 (3) Math.min(1,2,3) //取最小值 (1) Math.random() //取随机数 (0~1的小数) Math.floor(Math.random()*10) //随机数 (0-9的整数) Math.floor(Math.random()*(max-min+1)+min) //随机数 (最大值到最小值的整数) Math.round(1.5) //四舍五入M Math.cbrt(1) //立方根 [num].toFixed(n) //小数点后保留 n 位 Number.isNaN("15") //检查值是否为数字 Number.isIntEger() //判断一个数是否为整数,返回true/false(如果精度要求,不适用) Math.trunc(5.5) //去除小数,保留整数 => 5 Math.sign(5) //判断数值类型 正数:+1 负数:-1 0:0 -0:-0 其他值:NaN [number] | 0 //按位或取整,数字取整(类型可以是int或string) (201.56 | 0 => 201)
str.charAt(n) //取第 n 个字符
str.charCodeAt(n) //取第 n 个字符的ascii码
str.concat("789") //连接字符串
str.length //字符串长度
str.split(" ") //分割字符串,返回数组
str.replace("a","0") //替换字符串 (用 0 替换str中的所有 a)
str.toLocaleLowerCase() //字符串全部转小写
str.toLocaleUpperCase() //字符串全部转大写
str.toLowerCase() //字符串全部转小写
str.toUpperCase() //字符串全部转大写
// 查找字符串 str.slice(start, end) //查找字符串 [开始下标,结束下标] (不包含结束下标) str.lastIndexOf('l') //反向查找,返回正向下标 str.substring(start, end) //同 slice str.substr(start, lenth) //查找字符串 [开始下标,长度] // str.includes("o", [查找位置]) //查找字符串是否存在,返回ture/false str.startWith("he", [查找位置]) //查找字符串是否在原字符串的头部,返回true/false str.endsWith("world", [查找位置]) //与 startWith 相似,判断是否在尾部,返回true/false str.indexOf("a") //查找指定字符或字符串,返回字符下标 str.search("a") //类似于indexOf,但可以使用 正则 str.repeat(5) //将原字符串重复5次,形成新字符串(参数是小数,向下取整; 参数是负数,报错) str.padStart(5,"0") //字符串长度不足时,用“0”在前面补全 str.padEnd(5,"0") //字符串长度不足时,用“0”在后面补全 str.trimStart() //清除字符串头部空格 str.trimEnd() //清除字符串尾部空格
var pattern = /[0-9]/; //正则表达式
var str = "1a2s3d4f5g" //字符串
var reg = new RegExp(pattern,"g") //正则对象 (g -> 全局匹配)
var s = str.match(reg) //匹配文本
console.log(s); //返回数字
// 正则表达式
[\u4E00-\u9FA5]+ // 汉字
1(5|8|3)(\d){9} // 手机号
(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8} // 手机号
\d.+\d.+\d.+\d // ip地址
JSON.parse(jsonarr) //string 转 json
JSON.stringify(jsonobj) //json 转 string
encodeURI() //编码
decodeURI() //解码
document.execCommand("copy") // 浏览器的复制功能
//for 循环
var arr = [10,20,30,40,50]
for (var i=0; i<arr.length; i++) {
console.log(arr[i]);
}
//ES6:for...of 遍历数组
var arr = [10,20,30,40,50]
for (var item of arr) {
console.log(item);
}
// result: 10 20 30 40 50 (item就是每一个元素)
// keys() 遍历数组 键
for (var index of arr.key() {
console.log(index);
}
// values() 遍历数组 值
for (var value of arr.key() {
console.log(value);
}
// entries() 遍历数组 键值对
for (var [index, value] of arr.entries) {
console.log(index value);
}
//while 循环
var arr = [1,2,3,4,5]
var i=0;
while(i<arr.length) {
console.log(arr[i]);
i++;
}
//do...while 循环
var arr = [1,2,3,4,5]
var i=0;
do{
console.log(arr[i]);
i++;
}while(i<arr.length)
var el = document.createElement('p') //创建一个标签节点
var text = document.createTextNode('string') //创建一个文本节点
el.appendChild(text) //在标签节点中插入文本节点
el.className = "box" //设置节点的属性
parentEl.appendChild(el) //在已有元素中插入节点
var el = document.createElement('p') //创建一个节点
el.innerHTML = "<mark>hello</mark>" //在节点中插入内容
el.className = "box" //设置节点的属性
parentEl.appendChild(el) //插入到父元素
document.createElement('p') //创建 标签节点
document.createTextNode('string') //创建 文本节点
父元素.appendChild("节点") //将新建节点追加到父元素尾部
父元素.insertBefore("节点", "位置") //将新建节点插入到父元素指定位置
父元素.removeChild("节点") //删除指定节点
父元素.childNodes //获取父元素的所有节点,返回节点数组
父元素.childNodes[n].nodeType //获取第 n 个节点的类型,返回 1:标签节点 3:文本节点
父元素.firstChild //获取第一个任意元素
父元素.lastChild //获取最后一个任意元素
父元素.firstElementChild //获取第一个子节点元素
父元素.lastElementChild //获取最后一个子节点元素
节点.nextElementSibling //同级元素的下一个节点
节点.previousElementSibling //同级元素的上一个节点
function ajax(){ if (window.XMLHttpRequest) { var ajax = new XMLHttpRequest(); //chrome } else { var ajax = new ActiveXObject("Microsoft.XMLHTTP"); //IE } // 连接服务器 ajax.open('GET', url, true); //true:异步 false:同步 // 发送请求 ajax.send(); // 接收响应信息 ajax.onreadystatechange = function(){ if (ajax.readyState===4 && ajax.status===200) { console.log("请求成功"); } else { console.log("请求失败"); } } }
遍历数组
var arr = [1,2,3,4,5]
arr.forEach((val,index)=>{
console.log(index,val);
})
遍历数组,返回新数组
var arr = [1,2,3,4,5]
var newArr = arr.map((val,index)=>{
return val*10
})
console.log(newArr);
过滤数组,返回符合条件的数组
var arr = [1,2,3,4,5]
var newArr = arr.filter((val,index)=>{
return val<=3
})
console.log(newArr);
遍历数组,相邻元素进行计算 (可以相加,可以相乘。。。)
var arr = [1,2,3,4,5]
var newArr = arr.reduce((val1,val2)=>{
return val1*val2
})
console.log(newArr);
遍历数组,检查数组每一项是否都符合条件,返回true / false
var arr = [1,2,3,4,5]
var bool = arr.every((val,index)=>{
return val!==0
})
console.log(bool);
遍历数组,检查是否有符合条件的,有就返回 true
var arr = [1,2,3,4,5]
var bool = arr.some((val,index)=>{
return val===0
})
console.log(bool);
表格节点.tHead //获取表头
表格节点.tBodies //获取所有表格主体
表格节点.tFoot //获取表格尾部
表格节点.rows //获取所有行 (tr)
表格节点.cells //获取所有单元格 (td)
app.clientWidth //宽 (宽 + 内边距)
app.clientHeight //高 (高 + 内边距)
app.clientLeft //左边边框的宽度 (border-left-width)
app.clientTop //上边边框的宽度 (border-top-width)
app.scrollWidth //全部宽度 (包括内边距和外边距)
app.scrollHeight //全部高度 (包括内边距和外边距)
app.scrollLeft //距离左边的位置
app.scrollTop //距离上边的位置
app.offsetWidth //宽度 (没有外边距)
app.offsetHeight //高度 (没有外边距)
app.offsetLeft //带有定位的 距离左边的长度
app.offsetTop //带有定位的 距离上边的长度
app.offsetParent //距离定位父元素的 长度
app.getBoundingClientRect().left //距离屏幕左边的长度 (定位和外边距)
app.getBoundingClientRect().right //距离屏幕右边的长度
app.getBoundingClientRect().top //距离屏幕上边的长度
app.getBoundingClientRect().bottom //距离屏幕下边的长度
window.screen.width
window.screen.height
页面加载时,先加载可视区的图片
<img _src="./img/bg/jpg" alt="" >
var oImg = document.getElementByTagName('img')[0];
var url = oImg.getAttribute('_src');
setTimeout(function(){
oImg.src = url;
}, 200)
// 获取事件类型
function func(){
var type = ev.type;
console.log(type);
}
// 点击事件属性
ev.clientX //在可视区的点击位置
ev.clientY
ev.pageX //在body的点击位置
ev.pageY
ev.screenX //在显示器的点击位置
ev.screenY
0级绑定事件:带on的
btn.onClick = function(){
console.log("click 事件");
}
btn.onmouseover = function(){
console.log("mouseover 事件");
}
......
2级绑定事件
// 事件绑定: 1.事件类型 2.事件函数 3.是否在捕获或冒泡阶段执行(true-捕获,false-冒泡)
btn.addEventListener('click', function(){
console.log("addEventListener 绑定事件");
}, true)
// 方法一:ev.preventDefault();
document.oncontextmenu = function(ev){
ev.preventDefault();
console.log("ev");
}
// 方法二:return false;
document.oncontextmenu = function(){
console.log("ev");
return false;
}
<!-- ev.stopPropagation()阻止事件冒泡 -->
<body>
<div id="app"> </div>
<script>
var el = document.getElementById('app');
el.onclick = function(ev){
ev.stopPropagation();
console.log('app');
}
document.onclick = function(){
console.log("body");
}
</script>
</body>
window.onkeydown = function(ev){
console.log(ev.key); //ev.key:按下得键盘 按键
console.log(ev.keyCode); //ev.keyCode:按下得键盘码
console.log("ctrl:",ev.ctrlKey); //ctrl, alt, sgift 是否按下
console.log("alt:",ev.altKey); // 按下为true,未按下为false
console.log("shift:",ev.shiftKey);
}
// 获取滚轮值:上滚返回120,下滚返回-120
window.onmousewheel = function(ev){
console.log(ev.wheelDelta);
}
封装函数,方法。把函数封装成函数使用,在任意地方使用
- 基类也叫父类,子类也叫派生类,子类中可以使用父类得某些属性和方法,子类是父类功能得扩展
- 如果继承关系复杂时,比如多个类之间都存在继承关系,那么当使用某一个类时,要把这几个联系在一起的类一同使用
重载。同一个接口,不同类型调用,实现不同的功能
判断基本数据类型
判断实例或对象
**this:**使用function
时指向的是触发事件本身,使用 箭头函数 时指向的是上一层,如果没有,指向的是window
// 改变this指向
element.call(obj, [参数1], [参数2])
element.apply(obj, [参数1], [参数2])
element.bind(obj, [参数1], [参数2])
__proto__
:指向当前实例的原型const s = new Set(); //s.add(1).add(2).add(3) => 链式操作
s.add(1); //添加
s.delete(1); //删除
s.has(1); //是否存在 true/false
const m = new Map();
m.set("key","value"); //添加,添加时注意key和value,都要写
m.get("key"); //获取
m.has("key"); //是否存在 true/false
m.delete("key"); //删除
m.clear(); //清空
遍历map
for(let [key,value] of m){
console.log(key,value);
}
消除 后退的所有动作。包括 键盘、鼠标手势等产生的后退动作
// 禁用回退按钮 (vue登录页 例)
mounted() {
// 登录页 : 禁用回退按钮
if(this.$route.name === "login"){
history.pushState(null, null, document.URL);
window.addEventListener("popstate", function () {
history.pushState(null, null, document.URL);
});
}
}
// 输入框失去焦点,页面滑动到顶部
inpurBlur(){
setTimeout(function (){
document.body.scrollTop = 0;
},200);
},
inputOnFocus(e) {
setTimeout(function (){
e.target.scrollIntoView(true); // 让当前的元素滚动到浏览器窗口的可视区域内
},200); // 延时 == 键盘弹起需要时间
}
Cannot read property ‘length’ of undefined
后台在返回数据时是需要时间的 不管多快 都是需要时间的 但是在初始化时,并没有给一个空的数组 注意 是数组形式 所以当调用 .length 方法时 这时后台数据还没有返回回来 此时它不是数组 就会报错
方法:
同时判断数组的布尔值 和 数组的长度
<script src="https://cdn.staticfile.org/fingerprintjs2/2.1.0/fingerprint2.min.js"></script>
var pcid = "";
Fingerprint2.get(function (components) {
// 参数
const values = components.map(function (component) {
return component.value
});
// 指纹
pcid = Fingerprint2.x64hash128(values.join(''), 31);
_YS.userConfig = {
author: pcid
};
});
npm install --save file-saver xlsx
npm install --save script-loader
blob.js
(function (view) { "use strict"; view.URL = view.URL || view.webkitURL; if (view.Blob && view.URL) { try { new Blob; return; // eslint-disable-next-line no-empty } catch (e) {} } let BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function (view) { let get_class = function (object) { return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; } , FakeBlobBuilder = function BlobBuilder() { this.data = []; } , FakeBlob = function Blob(data, type, encoding) { this.data = data; this.size = data.length; this.type = type; this.encoding = encoding; } , FBB_proto = FakeBlobBuilder.prototype , FB_proto = FakeBlob.prototype , FileReaderSync = view.FileReaderSync , FileException = function (type) { this.code = this[this.name = type]; } , file_ex_codes = ( "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" ).split(" ") , file_ex_code = file_ex_codes.length , real_URL = view.URL || view.webkitURL || view , real_create_object_URL = real_URL.createObjectURL , real_revoke_object_URL = real_URL.revokeObjectURL , URL = real_URL , btoa = view.btoa , atob = view.atob , ArrayBuffer = view.ArrayBuffer , Uint8Array = view.Uint8Array ; FakeBlob.fake = FB_proto.fake = true; while (file_ex_code--) { FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; } if (!real_URL.createObjectURL) { URL = view.URL = {}; } URL.createObjectURL = function (blob) { var type = blob.type , data_URI_header ; if (type === null) { type = "application/octet-stream"; } if (blob instanceof FakeBlob) { data_URI_header = "data:" + type; if (blob.encoding === "base64") { return data_URI_header + ";base64," + blob.data; } else if (blob.encoding === "URI") { return data_URI_header + "," + decodeURIComponent(blob.data); } if (btoa) { return data_URI_header + ";base64," + btoa(blob.data); } else { return data_URI_header + "," + encodeURIComponent(blob.data); } } else if (real_create_object_URL) { return real_create_object_URL.call(real_URL, blob); } }; URL.revokeObjectURL = function (object_URL) { if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { real_revoke_object_URL.call(real_URL, object_URL); } }; FBB_proto.append = function (data/*, endings*/) { let bb = this.data; // decode data to a binary string if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { let str = "" , buf = new Uint8Array(data) , i = 0 , buf_len = buf.length ; for (; i < buf_len; i++) { str += String.fromCharCode(buf[i]); } bb.push(str); } else if (get_class(data) === "Blob" || get_class(data) === "File") { if (FileReaderSync) { let fr = new FileReaderSync; bb.push(fr.readAsBinaryString(data)); } else { // async FileReader won't work as BlobBuilder is sync throw new FileException("NOT_READABLE_ERR"); } } else if (data instanceof FakeBlob) { if (data.encoding === "base64" && atob) { bb.push(atob(data.data)); } else if (data.encoding === "URI") { bb.push(decodeURIComponent(data.data)); } else if (data.encoding === "raw") { bb.push(data.data); } } else { if (typeof data !== "string") { data += ""; // convert unsupported types to strings } // decode UTF-16 to binary string bb.push(unescape(encodeURIComponent(data))); } }; FBB_proto.getBlob = function (type) { if (!arguments.length) { type = null; } return new FakeBlob(this.data.join(""), type, "raw"); }; FBB_proto.toString = function () { return "[object BlobBuilder]"; }; FB_proto.slice = function (start, end, type) { var args = arguments.length; if (args < 3) { type = null; } return new FakeBlob( this.data.slice(start, args > 1 ? end : this.data.length) , type , this.encoding ); }; FB_proto.toString = function () { return "[object Blob]"; }; FB_proto.close = function () { this.size = this.data.length = 0; }; return FakeBlobBuilder; }(view)); view.Blob = function Blob(blobParts, options) { var type = options ? (options.type || "") : ""; var builder = new BlobBuilder(); if (blobParts) { for (let i = 0, len = blobParts.length; i < len; i++) { builder.append(blobParts[i]); } } return builder.getBlob(type); }; }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
Export2Excel.js
/* eslint-disable */ require('script-loader!file-saver'); require('./blob'); require('script-loader!xlsx/dist/xlsx.core.min'); function generateArray(table) { var out = []; var rows = table.querySelectorAll('tr'); var ranges = []; for (var R = 0; R < rows.length; ++R) { var outRow = []; var row = rows[R]; var columns = row.querySelectorAll('td'); for (var C = 0; C < columns.length; ++C) { var cell = columns[C]; var colspan = cell.getAttribute('colspan'); var rowspan = cell.getAttribute('rowspan'); var cellValue = cell.innerText; if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue; //Skip ranges ranges.forEach(function (range) { if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) { for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null); } }); //Handle Row Span if (rowspan || colspan) { rowspan = rowspan || 1; colspan = colspan || 1; ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}}); } ; //Handle Value outRow.push(cellValue !== "" ? cellValue : null); //Handle Colspan if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null); } out.push(outRow); } return [out, ranges]; }; function datenum(v, date1904) { if (date1904) v += 1462; var epoch = Date.parse(v); return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); } function sheet_from_array_of_arrays(data, opts) { var ws = {}; var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}; for (var R = 0; R != data.length; ++R) { for (var C = 0; C != data[R].length; ++C) { if (range.s.r > R) range.s.r = R; if (range.s.c > C) range.s.c = C; if (range.e.r < R) range.e.r = R; if (range.e.c < C) range.e.c = C; var cell = {v: data[R][C]}; if (cell.v == null) continue; var cell_ref = XLSX.utils.encode_cell({c: C, r: R}); if (typeof cell.v === 'number') cell.t = 'n'; else if (typeof cell.v === 'boolean') cell.t = 'b'; else if (cell.v instanceof Date) { cell.t = 'n'; cell.z = XLSX.SSF._table[14]; cell.v = datenum(cell.v); } else cell.t = 's'; ws[cell_ref] = cell; } } if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range); return ws; } function Workbook() { if (!(this instanceof Workbook)) return new Workbook(); this.SheetNames = []; this.Sheets = {}; } function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; return buf; } export function export_table_to_excel(id) { var theTable = document.getElementById(id); console.log('a') var oo = generateArray(theTable); var ranges = oo[1]; /* original data */ var data = oo[0]; var ws_name = "SheetJS"; console.log(data); var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); /* add ranges to worksheet */ // ws['!cols'] = ['apple', 'banan']; ws['!merges'] = ranges; /* add worksheet to workbook */ wb.SheetNames.push(ws_name); wb.Sheets[ws_name] = ws; var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") } function formatJson(jsonData) { console.log(jsonData) } export function export_json_to_excel(th, jsonData, defaultTitle) { /* original data */ var data = jsonData; data.unshift(th); var ws_name = "SheetJS"; var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); /* add worksheet to workbook */ wb.SheetNames.push(ws_name); wb.Sheets[ws_name] = ws; var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); var title = defaultTitle || '列表' saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx") }
util / index.js
export const export2Excel = (columns, list, name) => {
require.ensure([], () => {
const { export_json_to_excel } = require('./excel/Export2Excel');
let tHeader = [];
let filterVal = [];
columns.forEach(item => {
tHeader.push(item); // 表头值
});
for (let key in list[0]) {
filterVal.push(key); // 表头键
}
const data = list.map(v => filterVal.map(j => v[j]));
export_json_to_excel(tHeader, data, name); // excel表名称
});
};
npm install vue-xlsx-table --save
import vueXlsxTable from 'vue-xlsx-table';
Vue.use(vueXlsxTable, {rABS: false});
<template> <div id="app"> <vue-xlsx-table @on-select-file="handleSelectedFile"></vue-xlsx-table> </div> </template> <script> export default { name: 'app', methods: { handleSelectedFile (convertedData) { console.log(convertedData) } } } </script>
npm install --save html2canvas
npm install jspdf --save
创建 htmlToPdf.js
import html2Canvas from 'html2canvas'; import JsPDF from 'jspdf'; const htmlToPdf = (Vue) => { Vue.prototype.$getPdf = function () { var title = this.htmlTitle; html2Canvas(document.querySelector('#pdfDom'), { allowTaint: true }).then(function (canvas) { let contentWidth = canvas.width; let contentHeight = canvas.height; let pageHeight = contentWidth / 592.28 * 841.89; let leftHeight = contentHeight; let position = 0; let imgWidth = 595.28; let imgHeight = 592.28 / contentWidth * contentHeight; let pageData = canvas.toDataURL('image/jpeg', 1.0); let PDF = new JsPDF('', 'pt', 'a4'); if (leftHeight < pageHeight) { PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight); } else { while (leftHeight > 0) { PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight); leftHeight -= pageHeight; position -= 841.89; if (leftHeight > 0) { PDF.addPage(); } } } PDF.save(title + '.pdf'); }); }; }; export default { htmlToPdf };
在 main.js 中引入注册
import htmlToPdf from 'htmlToPdf.js';
Vue.use(htmlToPdf);
创建 index.vue 使用生成pdf的方法
<template> <div class="content" @contextmenu.prevent> <!-- 模板 --> <div id="pdfDom"> <h1 class="title">hello world</h1> </div> <!-- 下载 --> <button class="button" @click="download">download</button> </div> </template> <script> export default { props: {}, data() { return { htmlTitle: "个人信息", // 生成的pdf文件名 }; }, methods: { download(){ // 生成pdf的方法 this.$getPdf(); }, }, }; </script>
// 字符串加密
const compile: (code) => {
var c = String.fromCharCode(code.charCodeAt(0) + code.length);
for(let i = 1; i < code.length; i++){
c += String.fromCharCode(code.charCodeAt(i) + code.charCodeAt(i - 1));
}
return escape(c);
};
// 字符串解密
const uncompile: (code) => {
code = unescape(code);
let c = String.fromCharCode(code.charCodeAt(0) - code.length);
for(let i = 1; i < code.length; i++){
c += String.fromCharCode(code.charCodeAt(i) - c.charCodeAt(i - 1));
}
return c;
};
<input type=button value=导入收藏夹 onclick="window.external.ImportExportFavorites(true,'http://localhost');">
<input type=button value=导出收藏夹 onclick="window.external.ImportExportFavorites(false,'http://localhost');">
<input type=button value=整理收藏夹 onclick="window.external.ShowBrowserUI('OrganizeFavorites', null)">
<input type=button value=语言设置 onclick="window.external.ShowBrowserUI('LanguageDialog', null)">
<input type=button value=加入收藏夹 onclick="window.external.AddFavorite('http://www.google.com/', 'google')">
<input type=button value=加入到频道 onclick="window.external.addChannel('http://www.google.com/')">
<input type=button value=加入到频道 onclick="window.external.showBrowserUI('PrivacySettings',null)">
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="0">
进入页面 <meta http-equiv="Page-Enter" content="revealTrans(duration=x, transition=y)"> 推出页面 <meta http-equiv="Page-Exit" content="revealTrans(duration=x, transition=y)"> 这个是页面被载入和调出时的一些特效。duration表示特效的持续时间,以秒为单位。transition表示使 用哪种特效,取值为1-23: 0 矩形缩小 1 矩形扩大 2 圆形缩小 3 圆形扩大 4 下到上刷新 5 上到下刷新 6 左到右刷新 7 右到左刷新 8 竖百叶窗 9 横百叶窗 10 错位横百叶窗 11 错位竖百叶窗 12 点扩散 13 左右到中间刷新 14 中间到左右刷新 15 中间到上下 16 上下到中间 17 右下到左上 18 右上到左下 19 左上到右下 20 左下到右上 21 横条 22 竖条
//网页是否被检索 <meta name="ROBOTS" content="属性值">
其中属性值有以下一些:
属性值为"all": 文件将被检索,且页上链接可被查询;
属性值为"none": 文件不被检索,而且不查询页上的链接;
属性值为"index": 文件将被检索;
属性值为"follow": 查询页上的链接;
属性值为"noindex": 文件不检索,但可被查询链接;
属性值为"nofollow":
<meta http-equiv="Refresh" content="30" />
<meta http-equiv="Refresh" content="5; url=子任-专注网站前端开发技术和UEO实战技能" />
function DownURL(strRemoteURL,strLocalURL) { try { var xmlHTTP=new ActiveXObject("Microsoft.XMLHTTP"); xmlHTTP.open("Get",strRemoteURL,false); xmlHTTP.send(); var adodbStream=new ActiveXObject("ADODB.Stream"); adodbStream.Type=1;//1=adTypeBinary adodbStream.Open(); adodbStream.write(xmlHTTP.responseBody); adodbStream.SaveToFile(strLocalURL,2); adodbStream.Close(); adodbStream=null; xmlHTTP=null; } catch(e) { window.confirm("下载URL出错!"); } //window.confirm("下载完成."); } //检验连接是否有效 function getXML(URL) { var xmlhttp = new ActiveXObject("microsoft.xmlhttp"); xmlhttp.Open("GET",URL, false); try { xmlhttp.Send(); } catch(e){} finally { var result = xmlhttp.responseText; if(result) { if(xmlhttp.Status==200) { return(true); } else { return(false); } } else { return(false); } } }
window.print()
navigator.appVersion // 浏览器的版本号
navigator.appName // 浏览器的名称
navigator.language // 浏览器使用的语言
navigator.platform // 浏览器使用的平台
navigator.userAgent // 浏览器的user-agent信息
// process.env.NODE_ENV
if(process.env.NODE_ENV === 'development'){
console.log("开发环境");
} else if(process.env.NODE_ENV === 'production'){
console.log("线上环境");
}
const onScroll = () => {
// 总高度
let innerHeight = document.querySelector('#app').clientHeight;
// 客户区高度
let clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
// 滚动高度
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 客户区高度 + 滚动高度 >= 总高度
if (clientHeight + scrollTop >= innerHeight) {
console.log("到底了");
}
};
let data = [ { roleId: 1, name: "A", parentId: 0 }, { roleId: 2, name: "B", parentId: 1 }, { roleId: 3, name: "C", parentId: 1 }, { roleId: 4, name: "D", parentId: 3 }, { roleId: 5, name: "E", parentId: 4 }, ] console.log(setTreeData(data)) function setTreeData(arr) { let map = {}; //构建map arr.forEach(i => { map[i.roleId] = i; //构建以id为键 当前数据为值 }); let treeData = []; arr.forEach(item => { const mapItem = map[item.parentId]; //判断当前数据的parentId是否存在map中,返回存在的数据 console.log(mapItem); if (mapItem) { //存在则表示当前数据不是最顶层的数据 //注意: 这里的map中的数据是引用了arr的它的指向还是arr,当mapItem改变时arr也会改变,踩坑点 (mapItem.children || (mapItem.children = [])).push(item); //这里判断mapItem中是否存在child } else { //不存在则是顶层数据 treeData.push(item); } }); return treeData; }
isCardNo(num) { num = num.toUpperCase(); //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。 if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(num))) { return false; } //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 //下面分别分析出生日期和校验位 var len, re; len = num.length; if (len == 15) { re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/); var arrSplit = num.match(re); //检查生日日期是否正确 var dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4]); var bCorrectDay; bCorrectDay = (dtmBirth.getYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && ( dtmBirth.getDate() == Number(arrSplit[4])); if (!bCorrectDay) { return false; } else { //将15位身份证转成18位 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); var nTemp = 0, i; num = num.substr(0, 6) + '19' + num.substr(6, num.length - 6); for (i = 0; i < 17; i++) { nTemp += num.substr(i, 1) * arrInt[i]; } num += arrCh[nTemp % 11]; return true; } } if (len == 18) { re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/); var arrSplit = num.match(re); //检查生日日期是否正确 var dtmBirth = new Date(arrSplit[2] + "/" + arrSplit[3] + "/" + arrSplit[4]); var bCorrectDay; bCorrectDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4])); if (!bCorrectDay) { return false; } else { //检验18位身份证的校验码是否正确。 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 var valnum; var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); var nTemp = 0, i; for (i = 0; i < 17; i++) { nTemp += num.substr(i, 1) * arrInt[i]; } valnum = arrCh[nTemp % 11]; if (valnum != num.substr(17, 1)) { return false; } return true; } } return false; }
let oInput = document.createElement('input');
oInput.value = "123456";
document.body.appendChild(oInput);
oInput.select();
document.execCommand("Copy");
oInput.className = 'oInput';
oInput.style.display = 'none';
*** 上传时参数不能序列化**
// state.imgList = [file, file, file];
let formData = new FormData();
if (state.imgList.length > 0) {
for (let i = 0; i < state.imgList.length; i++) {
formData.append('files', state.imgList[i].file)
}
}
formData.append("id", route.query.id);
formData.append("organizeId", userInfo.organizeId);
formData.append("schoolId", route.query.schoolId);
formData.append("remarks", state.submit.remarks);
<template> <div> <!--图片展示--> <div class="video"> <video ref="video" width="100%" height="100%" autoplay></video> </div> <!--canvas截取流--> <div class="video"> <canvas ref="canvas" width="200%" height="200%"></canvas> <!-- <canvas ref="canvas" width="800%" height="800%"></canvas> --> </div> <!--确认--> <el-button size="mini" type="primary" @click="callCamera">开启摄像头</el-button> <el-button size="mini" type="primary" @click="closeCamera">关闭摄像头</el-button> <el-button size="mini" type="primary" @click="photograph">拍照</el-button> </div> </template>
// 调用摄像头 callCamera() { // H5调用电脑摄像头API navigator.mediaDevices.getUserMedia({ video: true }).then(success => { // 摄像头开启成功 this.$refs['video'].srcObject = success // 实时拍照效果 this.$refs['video'].play() }).catch(error => { console.error('摄像头开启失败,请检查摄像头是否可用!') }) }, // 关闭摄像头 closeCamera() { if (!this.$refs['video'].srcObject) return let stream = this.$refs['video'].srcObject let tracks = stream.getTracks() tracks.forEach(track => { track.stop() }) this.$refs['video'].srcObject = null }, // 拍照 photograph() { let ctx = this.$refs['canvas'].getContext('2d') // 把当前视频帧内容渲染到canvas上 ctx.drawImage(this.$refs['video'], 0, 0, 320, 400) // ctx.drawImage(this.$refs['video'], 0, 0, 160, 200) // 转base64格式、图片格式转换、图片质量压缩 let imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg', 1) // 由字节转换为KB 判断大小 let str = imgBase64.replace('data:image/jpeg;base64,', '') let strLength = str.length let fileLength = parseInt(strLength - (strLength / 8) * 2) // 图片尺寸 用于判断 let size = (fileLength / 1024).toFixed(2) console.log(size) // 上传拍照信息 调用接口上传图片 ......... console.log("Base64", imgBase64); // base64 转 文件流(file) *方法见 44 // let file = this.dataURLtoFile(imgBase64, "123.jpeg") // console.log("file", file); },
// canvas转dataURL:canvas对象、转换格式、图像品质 function canvasToDataURL(canvas, format, quality) { return canvas.toDataURL(format||'image/jpeg', quality||1.0); } // DataURL转canvas function dataURLToCanvas(dataurl, cb){ var canvas = document.createElement('CANVAS'); var ctx = canvas.getContext('2d'); var img = new Image(); img.onload = function(){ canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); cb(canvas); }; img.src = dataurl; } // image转canvas:图片地址 function imageToCanvas(src, cb){ var canvas = document.createElement('CANVAS'); var ctx = canvas.getContext('2d'); var img = new Image(); img.src = src; img.onload = function (){ canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); cb(canvas); }; } // canvas转image function canvasToImage(canvas){ var img = new Image(); img.src = canvas.toDataURL('image/jpeg', 1.0); return img; } // File/Blob对象转DataURL function fileOrBlobToDataURL(obj, cb){ var a = new FileReader(); a.readAsDataURL(obj); a.onload = function (e){ cb(e.target.result); }; } // DataURL转Blob对象 function dataURLToBlob(dataurl){ 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 Blob([u8arr], {type:mime}); } // Blob转image function blobToImage(blob, cb){ fileOrBlobToDataURL(blob, function (dataurl){ var img = new Image(); img.src = dataurl; cb(img); }); } // image转Blob function imageToBlob(src, cb){ imageToCanvas(src, function (canvas){ cb(dataURLToBlob(canvasToDataURL(canvas))); }); } // Blob转canvas function BlobToCanvas(blob, cb){ fileOrBlobToDataURL(blob, function (dataurl){ dataURLToCanvas(dataurl, cb); }); } // canvas转Blob function canvasToBlob(canvas, cb){ cb(dataURLToBlob(canvasToDataURL(canvas))); } // image转dataURL function imageToDataURL(src, cb){ imageToCanvas(src, function (canvas){ cb(canvasToDataURL(canvas)); }); } // dataURL转image,这个不需要转,直接给了src就能用 function dataURLToImage(dataurl){ var img = new Image(); img.src = d; return img; } // DataUrl转为File /** * DataUrl转为File * @param {String} dataUrl - dataUrl地址 * @param {String} fileName - file文件名 */ dataURLtoFile(dataUrl, fileName){ 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}); } // url转base64 /** * url转base64 * @param {String} url - url地址 */ urlToBase64(url) { return new Promise ((resolve,reject) => { let image = new Image(); image.onload = function() { let canvas = document.createElement('canvas'); canvas.width = this.naturalWidth; canvas.height = this.naturalHeight; // 将图片插入画布并开始绘制 canvas.getContext('2d').drawImage(image, 0, 0); // result let result = canvas.toDataURL('image/png') resolve(result); }; // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror image.setAttribute("crossOrigin",'Anonymous'); // 加时间戳解决跨域问题 image.src = url + '?time=' + String(new Date().getTime()); // 图片加载失败的错误处理 image.onerror = () => { reject(new Error('转换失败')); }; }); } //使用例子 this.urlToBase64(this.Url).then(res=>{ console.log(res); })
const getScrollPosition = (el = window) => ({
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
})
getScrollPosition(); // {x: 0, y: 200}
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop
if (c > 0) {
window.requestAnimationFrame(scrollToTop) window.scrollTo(0, c - c / 8)
}
}
scrollToTop()
const detectDeviceType = () =>
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i
.test(navigator.userAgent) ?
'Mobile' : 'Desktop'
detectDeviceType() // "Mobile" or "Desktop"
function doNotify(title, options = {}, events = {}) { const notification = new Notification(title, options) for (let event in events) { notification[event] = events[event] } } function notify(title, options = {}, events = {}) { if (!('Notification' in window)) { return console.error('This browser does not support desktop notification') } else if (Notification.permission === 'granted') { doNotify(title, options, events) } else if (Notification.permission !== 'denied') { Notification.requestPermission().then(function (permission) { if (permission === 'granted') { doNotify(title, options, events) } }) } } notify( '中奖提示', { icon: 'https://sf1-ttcdn-tos.pstatp.com/img/user-avatar/f1a9f122e925aeef5e4534ff7f706729~300x300.image', body: '恭喜你,掘金签到一等奖', tag: 'prize' }, { onclick(ev) { console.log(ev) ev.target.close() window.focus() } } )
function treeDataTranslate(data, id = 'id', pid = 'pId') { let res = [] let temp = {} for (let i = 0; i < data.length; i++) { temp[data[i][id]] = data[i] } for (let k = 0; k < data.length; k++) { if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) { if (!temp[data[k][pid]]['children']) { temp[data[k][pid]]['children'] = [] } temp[data[k][pid]]['children'].push(data[k]) } else { res.push(data[k]) } } return res }
setInterval(function () { check() }, 4000) var check = function () { function doCheck(a) { if (('' + a / a)['length'] !== 1 || a % 20 === 0) { ;(function () {}['constructor']('debugger')()) } else { ;(function () {}['constructor']('debugger')()) } doCheck(++a) } try { doCheck(0) } catch (err) {} } check()
禁止使用F12打开控制台
window.onkeydown = window.onkeyup = window.onkeypress = function (event) {
if (event.keyCode == 123) {
event.preventDefault(); // 阻止默认事件行为
window.event.returnValue = false;
}
};
function toFullScreen() {
let elem = document.body
elem.webkitRequestFullScreen
? elem.webkitRequestFullScreen()
: elem.mozRequestFullScreen
? elem.mozRequestFullScreen()
: elem.msRequestFullscreen
? elem.msRequestFullscreen()
: elem.requestFullScreen
? elem.requestFullScreen()
: alert('浏览器不支持全屏')
}
function exitFullscreen() {
let elem = parent.document
elem.webkitCancelFullScreen
? elem.webkitCancelFullScreen()
: elem.mozCancelFullScreen
? elem.mozCancelFullScreen()
: elem.cancelFullScreen
? elem.cancelFullScreen()
: elem.msExitFullscreen
? elem.msExitFullscreen()
: elem.exitFullscreen
? elem.exitFullscreen()
: alert('切换失败,可尝试Esc退出')
}
let firstUpperCase = ([first, ...rest]) => first?.toUpperCase() + rest.join('')
// 1 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)] } // 2 function typeOf(obj){ Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() }
window.navigator.sendBeacon
window.addEventListener("beforeunload", (e) => {
const data = {name: "编程三昧"};
window.navigator.sendBeacon("http://127.0.0.1:1991/loginout", JSON.stringify(data));
});
// 从请求中拿到后台返回的文件名
let contentDisposition = res.headers['content-disposition'];
let patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*');
let result = patt.exec(contentDisposition)[1];
const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', result);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。