###npm install时安装最新版
npm install npm@latest -g
###更新npm package的版本
npm upgrade [package name] [other package name]
###兼容方式得到网页真正的scrollTop (chrome只支持document.body.scrollTop)
let scrollTop=document.body.scrollTop+document.documentElement.scrollTop;
###基于window.requestAnimationFrame
平滑位移到指定元素的函数
参数填选择器即可, 比如用于回到顶部时只需要ele.addEventListener(moveTo('body'));
function moveTo (sel) {
const tar = document.querySelector(sel)
if (tar) {
let doc = document
const docTop = function (...arg) {
if (arg.length === 0) {
return doc.body.scrollTop || doc.documentElement.scrollTop
} else if (arg.length === 1) {
doc.body.scrollTop = arg[0]
doc.documentElement.scrollTop = arg[0]
return docTop()
}
}
return function () {
const tarTop = tar.offsetTop
const clickTop = docTop()
let status
if (clickTop < tarTop) status = 'down'
else status = 'up'
const SPEED = Math.abs(tarTop - clickTop) / 60
let lastTop = undefined
const scrollStep = function () {
let scrollTop = docTop()
lastTop = scrollTop
if (status === 'down') {
scrollTop += SPEED
if (scrollTop > tarTop) {
scrollTop = tarTop
status = 'stop'
}
} else if (status === 'up') {
scrollTop -= SPEED
if (scrollTop < tarTop) {
scrollTop = tarTop
status = 'stop'
}
}
const thisTop = docTop(scrollTop)
if (thisTop === lastTop) {
status = 'stop'
}
if (status === 'stop') {
return
}
requestAnimationFrame(scrollStep)
}
scrollStep()
}
} else {
return undefined
}
}
函数节流+防抖
在我写懒加载的时候, 要对dom元素进行大量的操作, 而每次滚动滚轮, 都会触发12次scroll事件, 也就是说一瞬间内这个懒加载的函数都会被调用12次… 因而从头滚到尾时会造成严重的页面卡顿, 因此这里必须得对函数进行节流+防抖处理.
我理解的节流和防抖:
防抖是指, 像scroll这样的事件不要像你掰一下钢尺后那样, 一瞬间疯狂抖动的调用
节流是说, 假如一股脑的多次函数重复调用就像拧开的水龙头, 哗啦一下子, 我们要给它改成像没拧紧时, 滴答滴答的, 每隔一段时间才允许调用一次.
/**
* @function throttle
* @param cb {function} 要应用函数节流+防抖的回调函数
* @param delay {number} 设置cb如果执行的频率太快, 时间间隔小于atMost, 则在delay毫秒数后再次尝试执行
* @param atMost {number} 像水龙头水滴每隔一段时间才会滴一下那样, 每当cb最后一次执行后, 必须等待atMost毫秒才能再调用一次
*/
const throttle = function (cb, delay, atMost) {
let timeout = null
let startTime = +new Date()
return function () {
let currTime = +new Date()
clearTimeout(timeout)
if (currTime - startTime >= atMost) {
cb()
startTime = currTime
} else {
timeout = setTimeout(cb, delay)
}
}
}
用法也很简单
比如说我说的那个懒加载
// 初始化懒加载所需要的信息, 返回个函数
const loadImg = lazyLoad()
// 在从上向下的滚动页面时, 每隔0.6秒尝试一次懒加载
window.addEventListener('scroll', throttle( loadImg, 300, 600), false)
判断鼠标上下滚动
//监听页面滚动事件
function scrollEvent() {
var timeout = null
window.addEventListener('scroll', (e) => {
// 函数防抖
clearTimeout(timeout)
setTimeout(() => {
if (window.pageYOffset > 500) {
if (this.toTopBtnStyle === false) this.toTopBtnStyle = true
} else {
if (this.toTopBtnStyle === true) this.toTopBtnStyle = false
}
scrollFunc()
if (scrollDirection === 'down') {
} else if (scrollDirection === 'up') {
}
}, 200)
})
var scrollAction = {x: 'undefined', y: 'undefined'}
var scrollDirection
function scrollFunc () {
if (typeof scrollAction.x === 'undefined') {
scrollAction.x = window.pageXOffset
scrollAction.y = window.pageYOffset
}
var diffX = scrollAction.x - window.pageXOffset
var diffY = scrollAction.y - window.pageYOffset
if (diffX < 0) {
scrollDirection = 'right'
} else if (diffX > 0) {
scrollDirection = 'left'
} else if (diffY < 0) {
scrollDirection = 'down'
} else if (diffY > 0) {
scrollDirection = 'up'
} else {
// First scroll event
}
scrollAction.x = window.pageXOffset
scrollAction.y = window.pageYOffset
}
}
scrollEvent();
导入excel
最近操纵表格时频繁用到这两个功能
// npm install xlsx 或
// <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
handleFilePickerChange(e) {
let files = e.target.files;
let fileReader = new FileReader();
fileReader.readAsBinaryString(files[0]);
e.target.value = '';
fileReader.onload = (readerEv) => {
let workbook;
let datas = []; // 存取要读取的值
try {
let data = readerEv.target.result;
workbook = XLSX.read(data, { type: 'binary' }); // 二进制流方式读取
} catch (err) {
message( '文件类型不正确');
return;
}
// 遍历每张表读取
for (let sheet in workbook.Sheets) {
if (sheet in workbook.Sheets) {
let fromTo = workbook.Sheets[sheet]['!ref'];
datas = datas.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
break; // 如果只取第一张表
}
}
let updateDatas = [];
for (let row of datas) {
if ('课程' in row && '班级编号' in row && '用户姓名' in row && '用户手机号' in row) {
if (rowdataPassValidate()) {
updateDatas.push({
ClassNum: row.班级编号,
TestType: row.课程 === '四级' ? 0 : 1,
UserName: row.用户姓名,
CellPhone: row.用户手机号.toString(),
OperatorUID: ''
});
} else {
message( '请确保要上传的数据');
}
} else {
message( '请检查excel的表头是否正确');
return;
}
}
fetch( requestUrl, {
method: 'POST',
body: JSON.stringify(updateDatas),
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(response => response.json())
.then(result => {
if (Array.isArray(result) && result.length) {
this.uploadFailDialogVisible = true;
this.uploadFailInfo = result;
} else {
message('上传成功');
}
}).catch(err => console.log(err));
};
}
导出excel
// npm install xlsx filesaver 或
// <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
// <script src="https://unpkg.com/file-saver@2.0.0-rc.3/dist/FileSaver.min.js"></script>
exportToExcel() {
if (Array.isArray(this.arrayOfExportToExcel) && this.arrayOfExportToExcel.length) {
downloadExl(this.arrayOfExportToExcel);
}
}
function downloadExl(data, type) {
var keys = Object.keys(data[0]);
var firstRow = {};
keys.forEach(function (item) {
firstRow[item] = item;
});
data.unshift(firstRow);
var content = {};
// 把json格式的数据转为excel的行列形式
var sheetsData = data.map(function (item, rowIndex) {
return keys.map(function (key, columnIndex) {
return Object.assign({}, {
value: item[key],
position: (columnIndex > 25 ? getCharCol(columnIndex) : String.fromCharCode(65 + columnIndex)) + (rowIndex + 1),
});
});
}).reduce(function (prev, next) {
return prev.concat(next);
});
sheetsData.forEach(function (item, index) {
content[item.position] = { v: item.value };
});
//设置区域,比如表格从A1到D10,SheetNames:标题,
var coordinate = Object.keys(content);
var workBook = {
SheetNames: ["Sheet"],
Sheets: {
"Sheet": Object.assign({}, content, { "!ref": coordinate[0] + ":" + coordinate[coordinate.length - 1] }),
}
};
//这里的数据是用来定义导出的格式类型
var excelData = XLSX.write(workBook, { bookType: "xlsx", bookSST: false, type: "binary" });
var blob = new Blob([string2ArrayBuffer(excelData)], { type: "" });
saveAs(blob, "四六级打卡记录.xlsx");
}
//字符串转字符流
function string2ArrayBuffer(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;
}
// 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
function getCharCol(n) {
let temCol = "",
s = "",
m = 0
while (n > 0) {
m = n % 26 + 1
s = String.fromCharCode(m + 64) + s
n = (n - m) / 26
}
return s
}
function stringFromDate(date) {
if (date instanceof Date) {
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
} else {
return '';
}
}