VSCode中怎麼進行前端重構?方法淺析

2022-03-23 22:00:06
如何使用進行前端重構?下面本篇文章給大家介紹一下在VSCode中進行前端重構的方法,希望對大家有所幫助!

日常開發中,我們經常會碰到需要重構的時候,VS Code中的 「重構」 選單給我們提供了豐富了的操作。可以幫我們更高效地完成重構工作。【推薦學習:《》】

但是這個選單每次提供的操作都不一樣,如果臨時去使用的話,會帶來一定的困擾。所以常有同學不敢碰這個重構功能。

在這裡,總結一下常用的一些操作,給大家做做參考。

首先,來一個常見的重新命名,熱熱身!

重新命名

為什麼要重新命名:命名不清晰,無法讓人理解。

操作步驟:

  • 選中變數名,滑鼠右鍵選擇重新命名符號(Rename Symbol),或者使用快捷鍵 F2

  • 彈出框輸入想要修改的名字;

  • VSCode 會把後續相關的名字都改掉。

1.png

熱身完畢,下面我們進入正題!

重構操作

2.png

  • 選中要重構的內容,滑鼠右鍵選擇重構(Refactor),或者使用 Ctrl + Shift + R

  • 根據選中的內容,可能會出現以下內容供選擇重構:

    • import/export

      • Convert default export to named export
      • Convert named export to default export
      • Convert namespace import to named export
      • Convert named imports to namepace export
    • 函數/類

      • Move to a new File
    • 變數/表示式

      • Extract constant
      • 提取到封閉範圍的 constant
      • 提取到 Module 範圍的 constant
      • Convert to optional chain expression
      • 刪除未使用的宣告
      • 在未使用的宣告前
    • 字串

      • Convert to template string 轉換成模板字串
    • 表示式/函數

      • Extract function
      • 提取到當前函數裡的 inner function
      • 提取到 Module 範圍的 function
      • 提取到 global 範圍的 function
    • 物件方法

      • generate ‘get’ and ‘set’ accessors 生成get、set處理器
      • generate ‘get’ and ‘set’ accessors 生成get、set處理器
      • 將函數轉換成 ES2015類
      • 將所有函數轉換成類
      • 提取到 class 'xxx' 中的 Method
      • 提取到 class 'xxx' 中的 readonly field

魔法數位

為什麼要修改魔法數位?因為除進位制數之外,數位的實際意義無法被人看懂。

目標:定義一個常數值,寫清楚改數位的實際意義。

操作:

  • 選中魔法數位進行重構。根據需要,推薦選擇:

    • 提取到封閉範圍的 constant
    • 提取到 Module/global 範圍的 constant
    兩者都會定義一個常數,前者定義在當前函數內,後者則是整個模組/檔案中;
  • 程式碼抽取到新的變數中,並出現重新命名的輸入框;

  • 使用全大寫單詞,單詞使用「_」間隔。

例子:今年雙十一持續13天,計算除雙十一促銷結束的時間。

function promotionEndDate() {
  return new Date(new Date('2022-11-11').getTime() + 13 * 60 * 60 * 24 * 1000);
}

/**
 * 修改後:
 * 將開始時間 START_DATE,持續的天數 LASTING_DAYS 抽取出來做成變數
 * 如果只有一處使用,則在使用到的函數內定義;
 * 如果多處都有用,可以考慮放在函數外,模組內。
 */
function promotionEndDate() {
    const START_DATE = '2022-11-11';
    const LASTING_DAYS = 13;
    return new Date(new Date(START_DATE).getTime() + LASTING_DAYS * 60 * 60 * 24 * 1000);
}

複雜的邏輯條件

為什麼要修改複雜邏輯?複雜的邏輯,往往條件判斷繁多,閱讀難度比較高。

操作:

  • 選中複雜的邏輯條件進行重構。根據需要,選擇:

    • 提取到封閉範圍的 constant
    • 提取到當前函數裡的 inner function
    • 提取到 Module/global 範圍的 function
  • 程式碼抽離到一個新的變數/函數中,並出現重新命名的輸入框;

  • 使用駝峰命名,使用 is/has 起頭,每個單詞首字母大寫。

例子:返回指定的某個月有多少天

function monthDay(year, month) {
    var day31 = [1, 3, 5, 7, 8, 10, 12];
    var day30 = [4, 6, 9, 11];
    if (day31.indexOf(month) > -1) {
        return 31;
    } else if (day30.indexOf(month) > -1) {
        return 30;
    } else {
        if ((year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) {
            return 29;
        } else {
            return 28;
        }
    }
}

/**
 * 修改後
 * 是否閏年在日期處理常式中會經常使用,所以將其提取到當前模組的最外層了
 */
function monthDay(year, month) {
    ...
    if (day31.indexOf(month) > -1) {
        return 31;
    } else if (day30.indexOf(month) > -1) {
        return 30;
    } else {
        if (isLeapYear(year)) {
            return 29;
        } else {
            return 28;
        }
    }
}

function isLeapYear(year) {
    return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
}

寫了註釋的程式碼片段

更推薦程式碼即註釋的理念。我們寫註釋之前要想明白為什麼需要註釋?

  • 如果程式碼本身已經很清晰,應該刪除註釋。
  • 如果抽取程式碼片段,取個合適的名字,能讓程式碼易於閱讀,也可以刪除註釋。

目標:將程式碼片段抽取出來做成函數,函數以此程式碼塊的具體功能做命名。

操作:

  • 選擇程式碼塊,重構(Refactor)。選擇:

    • 提取到當前函數裡的 inner function

例子:ajax 請求

function ajax(options) {
  options = options || {};
  options.type = (options.type || 'GET').toUpperCase();
  options.dataType = options.dataType || 'json';
  const READY_STATE = 4;
  const NET_STATUS = {
    OK: 200,
    RIDERCT: 300
  };
  const params = this.formatAjaxParams(options.data);
  let xhr;

  // 建立 - 非IE6 - 第一步
  if (window.XMLHttpRequest) {
    xhr = new window.XMLHttpRequest();
  } else { // IE6及其以下版本瀏覽器
    xhr = new window.ActiveXObject('Microsoft.XMLHTTP');
  }

  // 連線 和 傳送 - 第二步
  if (options.type === 'GET') {
    ...
  } else if (options.type === 'POST') {
    ...
  }
  
  // 接收 - 第三步
  xhr.onreadystatechange = function () {
    if (xhr.readyState === READY_STATE) {
      ...
    }
  };
}

// 修改後
function ajax(options) {
  ...
  let xhr;

  create();
  connectAndSend();
  recieve();

  function create() {...}
  function connectAndSend() {...}
  function recieve() {...}
}

過長的函數

功能拆分做成外部函數,再在內部呼叫。

操作:

  • 選擇程式碼塊重構,選擇:

    • 提取到 Module/Global 範圍的 function
  • 程式碼塊會生成一個函數,並攜帶必要的引數

例子:上個例子中,可以將 ajax 的接收模組獨立成模組的function

function ajax(options) {
  ...

  create();
  recieve();
  connectAndSend(options, xhr, params);
}
function connectAndSend(options, xhr, params) {
  if (options.type === 'GET') {
    ...
  } else if (options.type === 'POST') {
    ...
  }
}

重複的程式碼/過長的檔案

操作:

  • 選擇程式碼塊重構,選擇 Move to a new file

  • 程式碼會遷移到以當前函數/類作為檔名的檔案中;如果有多個類/函數,會以第一個類/函數做命明

  • 將函數/類使用 export 暴露出去;

  • 在原檔案中用 import 引入函數/類。

例子:日期處理常式:

3.png

移動到新檔案後:

4.png

index.js 中,還能跳轉到定義的程式碼,但是實際上並沒有引入。

5.png

重新命名,修復 import/export;

6.png

import/export

default 和命名、名稱空間和命名的轉換。

// named
export function nextMonthDay(year, month) {}

// default
export default function nextMonthDay(year, month) {}

// namepace 
import * as refactor from './refactor';

// named
import { nextMonthDay } from './refactor';

物件方法

生成get、set處理器

const person = {
  age: 32
};

// 生成get、set處理器
const person = {
  _age: 32,
  get age() {
    return this._age;
  },
  set age(value) {
    this._age = value;
  },
};

模板字串

字串拼接,快速轉換成模板字串:

class Person{
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  getFullName() {
    return this.firstName + ' ' + this.lastName;
  }
}

// 模板字串
class Person{
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

生成get、set處理器,與物件方法的結果類似。

提取到 class xxx 的 Method, 與上面寫註釋的程式碼、重複程式碼提取的類似。

在此不再複述。

提供 ES 2015 類轉換,支援原型方法轉換。

const Person = function() {
  this.age = 32;
};
Person.prototype.getAge = function() {
  return this.age;
}
Person.prototype.setAge = function(value) {
  return this.age = value;
}

// ES 2015 類
class Person {
  constructor() {
    this.age = 32;
  }
  getAge() {
    return this.age;
  }
  setAge(value) {
    return this.age = value;
  }
}

總結

重構程式碼的方法還有很多,這裡暫時列了一些。希望對大家有所幫助。

剩下的內容,大家可以在重構程式碼時,多點點這個重構選單,看看是否有驚喜。

更多關於VSCode的相關知識,請存取:!!

以上就是VSCode中怎麼進行前端重構?方法淺析的詳細內容,更多請關注TW511.COM其它相關文章!