雜記(一)

介紹

記錄一些自己寫代碼過程中遇到的問題,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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章