介绍

记录一些自己写代码过程中遇到的问题,google来的一些技巧和方法。

Iconfont的symbol引入

  • Iconfont的symbol引入,最好链接前加https:头,防止受到package.json里homepage的影响(如果设置了的话)。
  • 除非是双色图标,否则不要在线修改其颜色,并批量去色,然后直接通过代码修改到自己需要的颜色。在线修改会写死fill属性,css改颜色就不能单纯的通过color来修改了。

Input 只显示下划线

可以通过设置背景为none,在设置border达到效果。

input{    background: none;    border-bottom: 1px solid #dbdbdb;    border-top: 0px;    border-left: 0px;    border-right: 0px;    }

对象数组根据某属性去重

一个比较精简的写法。

 const res = new Map(); return arr.filter((a) => !res.has(a. attr) && res.set(a. attr, 1))

深拷贝

JSON.parse(JSON.stringify(object))

img标签隐藏占位边框

img标签设置的width和height,如果src为空则会出现占位框。

img[src=""],img:not([src]) {        opacity: 0;    }

React中router问题

React中router跳转时,旧组件的componentWillUnmount和新组件的constructor并不是按顺序执行的。举个栗子,即旧组件销毁window.onresize会把新组件constructor添加的window.onresize监听销毁掉。但如果是在新组件componentDidMount中通过window.addEventListener则不会受到影响。

非同源文件下载

同源可以通过a标签的download属性下载,非同源则如下:

/** * 获取 blob * @param  {String} url 目标文件地址 * @return {Promise}  */function getBlob(url) {    return new Promise(resolve => {        const xhr = new XMLHttpRequest();        xhr.open('GET', url, true);        xhr.responseType = 'blob';        xhr.onload = () => {            if (xhr.status === 200) {                resolve(xhr.response);            }        };        xhr.send();    });}/** * 保存 * @param  {Blob} blob      * @param  {String} filename 想要保存的文件名称 */function saveAs(blob, filename) {    if (window.navigator.msSaveOrOpenBlob) {        navigator.msSaveBlob(blob, filename);    } else {        const link = document.createElement('a');        const body = document.querySelector('body');        link.href = window.URL.createObjectURL(blob);        link.download = filename;        // fix Firefox        link.style.display = 'none';        body.appendChild(link);                link.click();        body.removeChild(link);        window.URL.revokeObjectURL(link.href);    }}/** * 下载  最后直接调用download即可 * @param  {String} url 目标文件地址 * @param  {String} filename 想要保存的文件名称 */export function download(url, filename) {    getBlob(url).then(blob => {        saveAs(blob, filename);    });}

防抖函数

防抖动是将多次执行变为最后一次执行。

/** * 防抖函数,返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行 * * @param  {function} func        回调函数 * @param  {number}   wait        表示时间窗口的间隔 * @param  {boolean}  immediate   设置为ture时,是否立即调用函数 * @return {function}             返回客户调用函数 */export function debounce(func, wait = 200, immediate = false) {    let timer, context, args    // 延迟执行函数    const later = () => setTimeout(() => {        // 延迟函数执行完毕,清空缓存的定时器序号        timer = null        // 延迟执行的情况下,函数会在延迟函数中执行        // 使用到之前缓存的参数和上下文        if (!immediate) {            func.apply(context, args)            context = args = null        }    }, wait)    // 这里返回的函数是每次实际调用的函数    return function (...params) {        // 如果没有创建延迟执行函数(later),就创建一个        if (!timer) {            timer = later()            // 如果是立即执行,调用函数            // 否则缓存参数和调用上下文            if (immediate) {                func.apply(this, params)            } else {                context = this                args = params            }            // 如果已有延迟执行函数(later),调用的时候清除原来的并重新设定一个            // 这样做延迟函数会重新计时        } else {            clearTimeout(timer)            timer = later()            context = this            args = params        }    }}

节流函数

节流是将多次执行变成每隔一段时间执行。

/** * underscore 节流函数,返回函数连续调用时,func 执行频率限定为 次 / wait * * @param  {function}   func      回调函数 * @param  {number}     wait      表示时间窗口的间隔 * @param  {object}     options   如果想忽略开始函数的的调用,传入{leading: false}。 *                                如果想忽略结尾函数的调用,传入{trailing: false} *                                两者不能共存,否则函数不能执行 * @return {function}             返回客户调用函数 */_.throttle = function(func, wait, options) {    var context, args, result;    var timeout = null;    // 之前的时间戳    var previous = 0;    // 如果 options 没传则设为空对象    if (!options) options = {};    // 定时器回调函数    var later = function() {      // 如果设置了 leading,就将 previous 设为 0      // 用于下面函数的第一个 if 判断      previous = options.leading === false ? 0 : _.now();      // 置空一是为了防止内存泄漏,二是为了下面的定时器判断      timeout = null;      result = func.apply(context, args);      if (!timeout) context = args = null;    };    return function() {      // 获得当前时间戳      var now = _.now();      // 首次进入前者肯定为 true      // 如果需要第一次不执行函数      // 就将上次时间戳设为当前的      // 这样在接下来计算 remaining 的值时会大于0      if (!previous && options.leading === false) previous = now;      // 计算剩余时间      var remaining = wait - (now - previous);      context = this;      args = arguments;      // 如果当前调用已经大于上次调用时间 + wait      // 或者用户手动调了时间       // 如果设置了 trailing,只会进入这个条件      // 如果没有设置 leading,那么第一次会进入这个条件      // 还有一点,你可能会觉得开启了定时器那么应该不会进入这个 if 条件了      // 其实还是会进入的,因为定时器的延时      // 并不是准确的时间,很可能你设置了2秒      // 但是他需要2.2秒才触发,这时候就会进入这个条件      if (remaining <= 0 || remaining > wait) {        // 如果存在定时器就清理掉否则会调用二次回调        if (timeout) {          clearTimeout(timeout);          timeout = null;        }        previous = now;        result = func.apply(context, args);        if (!timeout) context = args = null;      } else if (!timeout && options.trailing !== false) {        // 判断是否设置了定时器和 trailing        // 没有的话就开启一个定时器        // 并且不能不能同时设置 leading 和 trailing        timeout = setTimeout(later, remaining);      }      return result;    };  };

设置git commit 模板

创建 .git-commit-template.txt
写入(头部建议空一行,行尾序列为LF(vscode可以更改)):

# <类型>: (类型的值见下面描述) <主题> (最多50个字)# 解释为什么要做这些改动# |<----  请限制每行最多72个字   ---->|# 提供相关文章和其它资源的链接和关键字# 例如: Github issue #23# --- 提交 结束 ---# 类型值包含#    feat (新特性)#    fix (bug修复)#    docs (文档改动)#    style (格式化, 缺失分号等; 不包括生产代码变动)#    refactor (重构代码)#    test (添加缺失的测试, 重构测试, 不包括生产代码变动)#    chore (更新grunt任务等; 不包括生产代码变动)# --------------------# 注意#    主题和内容以一个空行分隔#    主题限制为最大50个字#    主题行大写#    主题行结束不用标点#    主题行使用祈使名#    内容每行72个字#    内容用于解释为什么和是什么,而不是怎么做#    内容多行时以'-'分隔# --------------------

然后把该文件丢到你喜欢的位置。

//这个命令只能设置当前分支的提交模板git config commit.template [模板文件位置]//这个命令能设置全局的提交模板git config --global commit.template [模板文件位置]

完成!
更强烈的规范约束可以看这个优雅的提交你的 Git Commit Message。