- 判断对象为空
JSON.stringify(object) === '{}'
Object.keys(object).length === 0
- 在回调函数中this为undefined
如setTimeout(function() { this }, 1000)
的回调函数中this为undefined。
- 可使用箭头函数作为回调函数
如setTimeout(() => { this }, 1000)
。 - 可让this先赋值给一个变量
var scope = this
setTimeout(function() { scope }, 1000)
- 判断对象的值时一定要先做非空判断
否则运行会在此处停止,也不报错。
let a = {a: 1, b: 3}
if (a && a.c) {
console.log("a.c存在")
} else {
console.log("a.c不存在")
}
此时会走else
分支。
若使用下面代码
let a = {a: 1, b: 3}
if (a && a.c.d) {
console.log("a.c.d存在")
} else {
console.log("a.c.d不存在")
}
此时当代码运行到a.c.d处就会停止,不再执行后面代码。
正确写法为
let a = {a: 1, b: 3}
if (a && a.c && a.c.d) {
console.log("a.c.d存在")
} else {
console.log("a.c.d不存在")
}
也可以写成(a && a.c && a.c.d) ? a.c.d : ""
也可以使用链运算符(a?.c?.d) ? a.c.d : ""
- 导入excel转换为对象
importXLSX: function(callback) {
// 创建input file
let file = document.createElement('input')
file.setAttribute('id','filefilefilefilefilefilefile');
file.setAttribute('type','file');
file.setAttribute('accept','.xlsx');
file.setAttribute("style",'visibility:hidden');
document.body.appendChild(file);
// 监听选择事件
file.addEventListener('change', val => {
let xlsx = val.target.files[0]//取选择的第一个文件
if (xlsx) {
//将xlsx转换为对象
let reader = new FileReader()
reader.onload = function(e) {
let cfb = XLSX.read(e.target.result, {type: 'binary'})
let sheetName = cfb.SheetNames[0]//每个excel有多个工作表 这里取第一个
let oJS = XLSX.utils.sheet_to_json(cfb.Sheets[sheetName])
callback(oJS)
};
reader.readAsBinaryString(xlsx)
}
})
//触发点击事件弹出文件选择
file.click();
},
使用上面方法获取的对象,你会发现时间会变成一个数字,可使用下面方法来转换成正常时间。
formatExcelDate(num, format="yyyy-MM-dd HH:mm:ss") {
if (isNaN(Number(num))) {
return num
}
const time = new Date((num - 1) * 24 * 3600000 + 1)
time.setYear(time.getFullYear() - 70)
time.setHours(time.getHours() - 8)
const year = time.getFullYear() + ''
const month = time.getMonth() + 1 + ''
const day = time.getDate() + ''
const hours = time.getHours() + ''
const hours1 = time.getHours()%12 + ''
const minutes = time.getMinutes() + ''
const seconds = time.getSeconds() + ''
const option = {
"Y+": year,
"y+": year,
"M+": month,
"d+": day,
"H+": hours,
"h+": hours1,
"m+": minutes,
"s+": seconds,
// 有其他格式化字符需求可以继续添加,必须转化成字符串
}
for (let k in option) {
let ret = new RegExp("(" + k + ")").exec(format);
if (ret) {
if (ret[1].length > option[k].length) {
//如果format每项的长度大于日期对应的数值 即yyyyy和2021,此时要上2021前补0
format = format.replace(ret[1], option[k].padStart(ret[1].length, "0"))
} else {
//若小于 即yy与2021,此时只取后面的21
format = format.replace(ret[1], option[k].slice(option[k].length - ret[1].length))
}
}
}
return format
},
- 将对象导出为excel
exportXLSX: function(array, titles, fileName = "list.xlsx") {
if (!array || array.length == 0) return
let datas = []
// 将 {a: "测试", b: "张三"} 变成 {"标题": "测试", "姓名": "张三"}
for (let item of array) {
let dict = {}
for (let t in titles) {
if (t.indexOf("$") != -1) {
//t中有$ 向最里层取值
let itemValue = item
let keys = t.split("$")
for (let s of keys) {
itemValue = itemValue[s]
}
let titleValue = titles[t]
dict[titleValue] = itemValue
} else {
//t中没有$ 根据titleValue的类型取值
let last = array.indexOf(item) == (array.length - 1)//是否为最后一项
let titleValue = titles[t]
let itemValue = item[t]
while (titleValue) {
if (typeof(titleValue) == "string") {
//titleValue为字符串时 直接赋值
dict[titleValue] = itemValue;
if (last) {
//当最后一个元素时 将titles中的value变成中文字符串 以供json_to_sheet使用
//即 {c: {d: "年龄" }}, 变为 {c: "年龄"}
//若在第一个元素时修改 会影响后续元素的判断 所以在最后一个元素时修改
titles[t] = titleValue
}
break
} else if (typeof(titleValue) == "object") {
//支持嵌套判断 此处只判断是否为对象 请不要传正则、数组等 它们也是对象
let nextTitleKey = Object.keys(titleValue)[0]
let nextTitleValue = Object.values(titleValue)[0]
itemValue = itemValue[nextTitleKey]
titleValue = nextTitleValue
} else {
break
}
}
}
}
datas.push(dict)
}
// 创建一个工作薄对象
let wb = XLSX.utils.book_new()
// 将数据转换为工作表 表头为titles中的value
let ws = XLSX.utils.json_to_sheet(datas, { header: Object.values(titles) })
// 工作薄中添加一个表sheet 表的内容为ws
let sheetName = "sheet"
wb.SheetNames.push(sheetName)
wb.Sheets[sheetName] = ws
//写入的样式
let wopts = {
bookType: 'xlsx', bookSST: false, type: 'binary', cellStyles: true, showGridLines: false ,
}
//创建二进制对象写入转换好的字节流
let wbout = XLSX.write(wb, wopts)
let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
// 创建对象超链接
var href = URL.createObjectURL(blob);
// 创建a标签 模拟点击事件下载文件
let a = document.createElement('a')
a.setAttribute('id','downloaddownloaddownloaddownload')
a.setAttribute('href', href)
a.setAttribute('download', fileName)
a.setAttribute("style", 'visibility:hidden')
document.body.appendChild(a);
a.click()
setTimeout(function() {
//释放字节流
URL.revokeObjectURL(blob);
}, 100);
}
// 字符串转字符流
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;
}
titles支持如下
titles: {
a: "标题",
b: "姓名",
c: {
d: "年龄"
},
e: {
f: {
g: "地址"
}
},
"h$i$j": "特殊1",
"h$i$k": "特殊2",
l: {
m: "特殊3",//不支持导出下面的n 只会导出m
n: "特殊4"//不支持 请使用 "l$n": "特殊4"
}
}
- 在字符串中插入变量
let a = aaa
let b = "111" + a + "222"
let c = `111${a}222`
必须使用数字1左边的`,${}
才有效。
- 三相运算符
通常会使用let a = b ? b : ""
,当b为不为空时,a赋值为b,否则a赋值为""。
可写成let a = b || ""
,也能实现对应功能,这个写法会在 b 为false 0 null undefined
时执行;
可写成let a = b ?? ""
, 与 || 功能相同,但只有b为null undefined
时才会执行。