Open violet0sea opened 6 years ago
生成随机的Id(0-9a-zA-Z)
function randomId(len = 4) {
let str = "";
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
while(len--) {
const range = Math.floor(Math.random() * 62);
str += arr[range];
}
return str;
}
timestamp时间格式化MM/DD/YYYY
/**
* 一位日期补0
*/
function format2Two(number) {
let str = '' + number;
if(str.length === 1) {
str = '0' + str;
}
return str;
}
/**
* 时间格式化 MM/DD/YYYY
*/
export function getFormatDate(timeStamp) {
const date = new Date(timeStamp);
const year = date.getFullYear();
const month = format2Two(date.getMonth() + 1);
const day = format2Two(date.getDate());
return `${month}/${day}/${year}`;
}
H5唤起app
var startTime = new Date();
window.location.href = '<scheme>';
var timer = setTimeout(function() {
if(new Date() - startTime < 2000) {
window.location.href = ‘<download page url>’
} else {
clearTimeout(timer);
}
});
React 使用html2canvas将网页绘制为图片
<button id="save_image_locally" onClick={this.dowload}>download img</button>
dowload() {
const dom = document.querySelector('.App-header');
html2canvas(dom)
.then(canvas => {
var a = document.createElement('a');
a.href = canvas.toDataURL("image/jpeg"); // can be png
a.download = 'download.jpg';
a.click();
})
}
React upload file function
1.已formData binary格式发送
upload(e) {
const file = e.target.files[0];
console.log(file);
const formData = new FormData();
formData.append('file', file);
axios.post(<upload url>, formData)
}
2.已base64的格式发送
upload =(e)=> {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
let params={};
params.pic = reader.result;
axios.post(<upload url>, params)
}
if (file && file.type.match('image.*')) {
reader.readAsDataURL(file)
}
}
stackoverflow上的deepClone,神奇
function deepClone(obj, hash = new WeakMap()) {
if(Object(obj) !== obj || obj instanceof Function) {
return obj;
}
if(hash.has(obj)) {
return hash.get(obj);
}
let result;
try {
result = new obj.constructor();
} catch(err) {
result = Object.getPrototypeOf(obj);
}
hash.set(obj, result);
return Object.assign(result, ...Object.keys(obj).map(
key => ({[key]: deepClone(obj[key], hash)})
));
}
解决浏览器关闭时发送请求的问题 产品需求时编辑时发送一个正在编辑的状态给服务端,防止其他人同时修改,修改完毕或者取消时解除状态,大部分情况下这样的逻辑都是可行的。但是,如果处于编辑状态时关闭浏览器会如何?目前就浏览器的形为来看,如果直接发送ajax请求,由于是异步的会被取消。那有没有什么方法可以在浏览器关闭前发送请求,其实并不关心请求的响应,仅仅只是发送请求,也适用于数据上报的情形 解决方案
1. 如果要发送get请求
function sendQuery(params){
const img = new Image();
const path = '/content/cms/doc/action/edit';
const {query} = params;
img.src = `${path}?${query}`;
}
2.如果发送post请求, navigator.sendBeacon的第二个参数时请求体
sendQuery({query: `docId=${'c60e0704'}&flag=0`})
function sendBeacon(params) {
const path = '/content/cms/doc/action/edit';
const {query} = params;
navigator.sendBeacon(`${path}?${query}`, {});
}
sendBeacon({query: `docId=${'c60e0704'}&flag=0`})
function debounce(fn, wait, immediately) {
let timer;
return function debouncedFun() {
const callNow = immediately && !timer;
if (callNow) {
fn.apply(this, arguments);
}
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
timer = null;
fn.apply(this, arguments);
}, wait);
};
}
function throttle(fn, wait) {
let lastTime;
let timer;
return function() {
const now = +new Date();
// 每次触发时需要更新剩余时间防止两次执行的间隔远大于wait
const remaining = lastTime ? lastTime + wait - now : 0;
clearTimeout(timer);
if (remaining > 0) {
timer = setTimeout(() => {
lastTime = now;
fn.apply(this, arguments);
}, remaining);
} else {
lastTime = now;
fn.apply(this, arguments);
}
};
}
function Task() {
var cache = [];
var index = 0;
var add = function (fn, time) {
cache.push({ fn, time });
};
var run = async function () {
const task = cache[index++];
if (!task) {
index = 0;
return;
}
const res = sleep(task.fn, task.time);
res.then(fn => {
fn();
run();
})
};
return { add, run };
}
function sleep(fn, time) {
return new Promise((resolve, reject) => {
setTimeout(resolve, time, fn)
})
}
var t1 = new Task()
t1.add(() => { console.log(100) }, 100)
t1.add(() => { console.log(1000) }, 1000)
t1.add(() => { console.log(2000) }, 2000)
t1.run()
function Task() {
var list = [];
var index = 0;
var add = function (fn, time) {
list.push(asyncTask(fn, time));
};
var run = function () {
var currentFun = list[index];
typeof currentFun === 'function' && currentFun(next);
};
var next = function() {
if(index >= list.length - 1) {
index = 0
return;
}
var currentFun = list[++index];
typeof currentFun === 'function' && currentFun(next);
}
return { add, run };
}
function asyncTask(fn, wait) {
return function(next) {
setTimeout(() => {
fn();
next();
}, wait);
}
}
var t1 = new Task()
t1.add(() => { console.log(100) }, 100)
t1.add(() => { console.log(1000) }, 1000)
t1.add(() => { console.log(2000) }, 2000)
t1.run()
/**
* 表单校验策略
*/
var validStrategy = {
nonEmptyString(str, errorMsg) {
if (str === '') {
return errorMsg
}
},
nonEmptyArray(arr, errorMsg) {
if (Array.isArray(arr) && arr.length > 0) {
return errorMsg
}
},
stringMaxLength(str, maxLength, errorMsg) {
if (str.length > maxLength) {
return errorMsg
}
}
}
/**
* 校验类
* 返回add & start
* add(value, rules) // value: 校验值 rules[{strategy, payload}]
* strategy可以传递function,接收value作为参数,可以针对当前值做自定义的校验规则
* 比如当前值依赖另一个值是否存在
* payload 里面必须传递errorMsg作为失败的返回,其他字段可以自定义用于校验策略里的验证
*/
function Validator() {
let validatorList = []
function add(value, rules) {
for (var i = 0; i < rules.length; i++) {
const rule = rules[i]
const { strategy, payload } = rule
if (typeof strategy === 'string') {
normalCheck(value, strategy, payload)
}
if (typeof strategy === 'function') {
customFunction(value, strategy, payload)
}
}
}
function normalCheck(value, strategy, payload) {
const validFun = validStrategy[strategy]
if (typeof validFun !== 'function') {
throw new Error(`表单校验的strategy[${strategy}]不存在`)
}
validatorList.push(function() {
return validFun.apply(null, [value, payload])
})
}
function customFunction(value, isValidFun, payload) {
const boundFun = function() {
if (!isValidFun(value)) {
return payload.errorMsg
}
}
validatorList.push(boundFun)
}
function start() {
for (var i = 0, len = validatorList.length; i < len; i++) {
const validFun = validatorList[i]
const errorMsg = validFun()
if (errorMsg) {
return errorMsg
}
}
}
return {
add,
start
}
}
var valid = new Validator()
var checkedValue = 'long'
valid.add(checkedValue, [
{
strategy: 'nonEmptyString',
payload: {
errorMsg: 'no empty'
}
},
{
strategy: 'stringMaxLength',
payload: {
maxLength: 5,
errorMsg: 'beyound max length of 5'
}
},
{
strategy: function(value) {
if (value.indexOf('https://') === -1) {
return false
}
return true
},
payload: {
errorMsg: 'function check fail'
}
}
])
var errorMsg = valid.start()
if (errorMsg) {
console.log(errorMsg)
}
function MyPromise(cb) {
this._value;
this._status = 'pending';
this.successCbs = [];
this.failureCbs = [];
var self = this;
function resolveFun(value) {
self._value = value;
self._status = 'fulfilled';
setTimeout(() => {
self.successCbs.forEach(fn => fn(value));
}, 0);
}
function rejectFun(err) {
self._value = err;
self._status = 'fulfilled';
setTimeout(() => {
self.failureCbs.forEach(fn => fn(err));
}, 0)
}
cb(resolveFun, rejectFun);
}
MyPromise.prototype.then = function(fulfilled, rejected) {
if(this._status === 'pending') {
if(typeof fulfilled === 'function') {
this.successCbs.push(fulfilled);
}
if(typeof rejected === 'function') {
this.failureCbs.push(rejected);
}
} else if(this._status === 'fulfilled') {
fulfilled(this._value);
} else {
rejected(this._value);
}
}
var pp = new MyPromise((res, rej) => {
setTimeout(() => {
res(100)
}, 1000)
})
pp.then(val => {
console.log('succ', val)
}, err => {
console.log('err', err)
})
const config = {
rootMargin: '0px 0px 50px 0px',
threshold: 0
};
// register the config object with an instance
// of intersectionObserver
let observer = new IntersectionObserver(function (entries, self) {
// iterate over each entry
entries.forEach(entry => {
// process just the images that are intersecting.
// isIntersecting is a property exposed by the interface
if (entry.isIntersecting) {
// custom function that copies the path to the img
// from data-src to src
preloadImage(entry.target);
// the image is now in place, stop watching
self.unobserve(entry.target);
}
});
}, config);
function preloadImage(ele) {
const src = ele.getAttribute('data-src');
ele.src = src;
};
const imgs = document.querySelectorAll("img[’data-src‘]");
imgs.forEach(img => {
observer.observe(img);
});
获取浏览器的query