[譯] 在你學習 React 之前必備的 JavaScript 基礎

dendionk發表於2019-06-01

寫在前面

為了不浪費大家的寶貴時間,在開頭申明一下,這篇文章針對的閱讀物件是:沒有寫過 React 或者剛剛才接觸 React 並且對於 ES6 的語法不太瞭解的同學,這是一篇基礎入門的文章,在一開始我並沒有準備翻譯一篇這樣的基礎文章,但是在閱讀完全文之後,我想起自己剛開始學習 React 時的迷茫,ES6 有那麼多,我需要掌握多少呢?對於一個急於上手 React 寫程式碼的人來說,這篇文章告訴你最基本要掌握的知識,讓你快速的寫起來。但是後期的提高,仍舊需要去夯實 Javascript 的基礎。

前言

在理想的狀態下,你可以在深入瞭解React之前瞭解 JavaScriptWeb 開發的所有知識。 不幸的是,我們生活在一個不完美的世界,所以在 React 之前把所有的JavaScript 都咀嚼一遍只會讓你舉步維艱。 如果你已經擁有一些 JavaScript 經驗,那麼在 React 之前你需要學習的只是實際用於開發 React 應用程式的 JavaScript 功能。 在學習 React之前你應該學會的JavaScript 的知識點:

  • ES6
  • 使用 let / const 宣告變數
  • 箭頭函式
  • 解構賦值
  • Mapfilter
  • ES6 模組系統

這是你將在 80% 的時間內使用的20%JavaScript 新特性,因此在本文中,我將幫助你學習所有這些特性。

建立 React 應用程式的探索

開始學習 React 的常見情況是執行 create-react-app 包,它會設定執行 React 所需的一切。 該過程完成之後,開啟 src / app.js 這裡給我們展示了整個應用程式中唯一的 React 類:


import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
    );
  }
}

export default App;

複製程式碼

如果之前你從未學習過 ES6 ,那麼你可能認為這個 class 語句是 React 的一個特性。 實際上這是 ES6 的一個新特性,這就是為什麼正確學習 ES6 可以讓你更好地理解 React 程式碼。 我們將從 ES6 的類開始。

ES6 的類

ES6 引入了 class 語法,類似於 JavaPythonOO(物件導向) 語言。 ES6 中的基本類如下所示:

class Developer {
  constructor(name){
    this.name = name;
  }

  hello(){
    return 'Hello World! I am ' + this.name + ' and I am a web developer';
  }
}
複製程式碼

class 語法後跟一個可用於建立新物件的識別符號(或一個名稱)。 始終在物件初始化中呼叫建構函式方法。 傳遞給這個物件的任何引數都將傳遞給新物件。 例如:

var nathan = new Developer('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a web developer
複製程式碼

類可以定義任意它所需的方法,在這種情況下,我們定義了一個返回字串的 hello 方法。

類繼承

類可以擴充套件另一個類的定義,從該類初始化的新物件將具有這兩個類的所有方法。

class ReactDeveloper extends Developer {
  installReact(){
    return 'installing React .. Done.';
  }
}

var nathan = new ReactDeveloper('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a web developer
nathan.installReact(); // installing React .. Done.
複製程式碼

繼承另一個類的類,通常稱為 child 類或 sub 類,而正在擴充套件的類稱為 parent 類或 super 類。 子類也可以覆蓋父類中定義的方法,這意味著它將使用自己定義的新方法來替換父類方法的定義。 例如,讓我們覆蓋 hello 函式:

class ReactDeveloper extends Developer {
  installReact(){
    return 'installing React .. Done.';
  }

  hello(){
    return 'Hello World! I am ' + this.name + ' and I am a REACT developer';
  }
}

var nathan = new ReactDeveloper('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a REACT developer
複製程式碼

就這樣,我們重寫了 Developer 類中的 hello 方法。

在React 中使用

現在我們瞭解了 ES6 的類和繼承,我們可以理解 src / app.js 中定義的 React 類。 這是一個 React 元件,但它實際上只是一個普通的 ES6 類,它繼承了從 React 包匯入的 React Component 類的定義。

import React, { Component } from 'react';

class App extends Component {
  // class content
  render(){
    return (
      <h1>Hello React!</h1>
    )
  }
}
複製程式碼

這使得我們能夠使用 render() 方法,JSXthis.state 和其他方法。 所有這些定義都在Component 類中。 但正如我們稍後將看到的,class 不是定義 React Component 的唯一方法。 如果你不需要狀態和其他生命週期方法,則可以使用函式。

使用 ES6 中的 letconst 來宣告變數

因為 JavaScriptvar 關鍵字是宣告全域性的變數,所以在 ES6 中引入了兩個新的變數宣告來解決這個問題,即 letconst 。 它們都用於宣告變數。 區別在於 const 在宣告後不能改變它的值,而 let 則可以。 這兩個宣告都是本地的,這意味著如果在函式作用域內宣告 let ,則不能在函式外部呼叫它。

const name = "David";
let age = 28;
var occupation = "Software Engineer";
複製程式碼

用哪個呢?

按以往經驗來說,預設使用 const 宣告變數。 稍後當您編寫應用程式時,當你意識到 const 的值需要更改,才是你應該將const 重構為 let 時。 希望它會讓你習慣新的關鍵字,並且你將開始認識到應用程式中需要使用 constlet 的模式。

我們什麼時候在 React 中使用呢?

在我們需要變數的時候:

import React, { Component } from 'react';

class App extends Component {
  // class content
  render(){
    const greeting = 'Welcome to React';
    return (
      <h1>{greeting}</h1>
    )
  }
}
複製程式碼

在整個應用的生命週期中 greeting 並不會發生改變,所以我們在這裡使用 const

箭頭函式

箭頭函式是 ES6 的一種新特性,在現代程式碼庫中幾乎被廣泛使用,因為它使程式碼簡潔易讀。 它允許我們使用更短的語法編寫函式。

// regular function
const testFunction = function() {
  // content..
}

// arrow function
const testFunction = () => {
  // content..
}
複製程式碼

如果您是一位經驗豐富的 JS 開發人員,那麼從常規函式語法轉換為箭頭語法可能會讓您感到不舒服。 當我學習箭頭函式時,我用這兩個簡單的步驟來重寫我的函式:

  1. 移除 function 關鍵字
  2. () 後面加上 =>

括號仍然用於傳遞引數,如果只有一個引數,則可以省略括號。

const testFunction = (firstName, lastName) => {
  return firstName+' '+lastName;
}

const singleParam = firstName => {
  return firstName;
}
複製程式碼

隱藏的 return

如果箭頭函式只有一行,則可以返回值而無需使用 return 關鍵字以及大括號。

const testFunction = () => 'hello there.';
testFunction(); 
複製程式碼

React 中的使用

const HelloWorld = (props) => {
  return <h1>{props.hello}</h1>;
}
複製程式碼

等同於 ES6 的類元件

class HelloWorld extends Component {
  render() {
    return (
      <h1>{props.hello}</h1>;
    );
  }
}
複製程式碼

React 應用程式中使用箭頭功能可使程式碼更簡潔。 但它也會從元件中刪除狀態的使用。 這種型別的元件稱為無狀態功能元件。 你會在許多 React 教程中看到這個名字。

解析陣列和物件的賦值

ES6 中引入的最有用的新語法之一,解構賦值只是複製物件或陣列的一部分並將它們放入命名變數中。 一個簡單的例子:

const developer = {
  firstName: 'Nathan',
  lastName: 'Sebhastian',
  developer: true,
  age: 25,
}

//destructure developer object
const { firstName, lastName } = developer;
console.log(firstName); // returns 'Nathan'
console.log(lastName); // returns 'Sebhastian'
console.log(developer); // returns the object
複製程式碼

如您所見,我們將開發人員物件中的 firstNamelastName 分配給新變數 firstNamelastName 。 現在,如果要將 firstName 放入名為 name 的新變數中,該怎麼辦?

const { firstName:name } = developer;
console.log(name); // returns 'Nathan'
複製程式碼

解構也適用於陣列,使用索引而不是物件鍵:

const numbers = [1,2,3,4,5];
const [one, two] = numbers; // one = 1, two = 2
複製程式碼

你可以通過傳入 , 來在解構的過程中跳過一些下標:

const [one, two, , four] = numbers; // one = 1, two = 2, four = 4
複製程式碼

React 中的使用

最常見是在方法中解構 state:

reactFunction = () => {
  const { name, email } = this.state;
};
複製程式碼

或者是在無狀態的函式元件中,結合之前提到的例子:

const HelloWorld = (props) => {
  return <h1>{props.hello}</h1>;
}
複製程式碼

我們可以立即簡單地解構引數:

const HelloWorld = ({ hello }) => {
  return <h1>{hello}</h1>;
}
複製程式碼

Mapfilter

雖然本文側重於 ES6 ,但需要提及 JavaScript 陣列 Mapfilter 方法,因為它們可能是構建 React 應用程式時最常用的 ES5 功能之一。 特別是在處理資料上。

這兩種方法在處理資料時使用得更多。 例如,假設從 API 結果中獲取返回 JSON 資料的陣列:

const users = [
  { name: 'Nathan', age: 25 },
  { name: 'Jack', age: 30 },
  { name: 'Joe', age: 28 },
];
複製程式碼

然後我們可以在 React 中呈現專案列表,如下所示:

import React, { Component } from 'react';

class App extends Component {
  // class content
  render(){
    const users = [
      { name: 'Nathan', age: 25 },
      { name: 'Jack', age: 30 },
      { name: 'Joe', age: 28 },
    ];

    return (
      <ul>
        {users
          .map(user => <li>{user.name}</li>)
        }
      </ul>
    )
  }
}
複製程式碼

我們同樣可以在 render 中篩選資料

<ul>
  {users
    .filter(user => user.age > 26)
    .map(user => <li>{user.name}</li>)
  }
</ul>
複製程式碼

ES6 模組系統

ES6 模組系統使 JavaScript 能夠匯入和匯出檔案。 讓我們再看一下 src / app.js 程式碼來解釋這一點。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
    );
  }
}

export default App;
複製程式碼

在第一行程式碼中我們看到 import 語句:

import React, { Component } from 'react';
複製程式碼

在第一行程式碼中我們看到 export default 語句:

export default App;
複製程式碼

要理解這些語句,我們先討論模組語法。

模組只是一個 JavaScript 檔案,它使用 export 關鍵字匯出一個或多個值(可以是物件,函式或變數)。 首先,在 src 目錄中建立一個名為 util.js 的新檔案

touch util.js
複製程式碼

然後我們在這裡面寫一個函式,使用一個預設匯出

export default function times(x) {
  return x * x;
}
複製程式碼

或多個命名的匯出

export function times(x) {
  return x * x;
}

export function plusTwo(number) {
  return number + 2;
}
複製程式碼

然後我們可以在 src/App.js 中引入它。

import { times, plusTwo } from './util.js';

console.log(times(2));
console.log(plusTwo(3));
複製程式碼

每個模組可以有多個命名匯出但只有一個預設匯出。 可以匯入預設匯出,而無需使用花括號和相應的匯出函式名稱:

// in util.js
export default function times(x) {
  return x * x;
}

// in app.js
export k from './util.js';

console.log(k(4)); // returns 16
複製程式碼

但是對於命名匯出,必須使用花括號和確切名稱匯入。 或者,import可以使用別名來避免兩個不同的匯入具有相同的名稱:

// in util.js
export function times(x) {
  return x * x;
}

export function plusTwo(number) {
  return number + 2;
}

// in app.js
import { times as multiplication, plusTwo as plus2 } from './util.js';
複製程式碼

直接這樣引入名稱:

import React from 'react';
複製程式碼

將使 JavaScript 檢查node_modules 以獲取相應的包名稱。 因此,如果您要匯入本地檔案,請不要忘記使用正確的路徑。

在 React 中使用

顯然我們已經在 src / App.js 檔案中看到了這個,然後在 index.js 檔案中看到了匯出的 App 元件的呈現方式。 我們暫時忽略 serviceWorker 部分。

//index.js file

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
複製程式碼

請注意如何從 ./App 目錄匯入 App ,並省略了 .js 副檔名。 我們只能在匯入 JavaScript 檔案時省略副檔名,但在其他檔案中我們必須包含副檔名,例如 .css 。 我們還匯入另一個 node 模組 react-dom ,這使我們能夠將 React 元件呈現為 HTML元素。

至於 PWA ,它是使 React 應用程式離線工作的一項功能,但由於預設情況下它已被禁用,因此無需在開始時學習它。 在你有足夠的信心構建 React 使用者介面之後,最好學習 PWA

總結

React 的優點在於它不會像其他 Web 框架一樣在 JavaScript 之上新增任何外部抽象層。 這就是為什麼 React 變得非常受 JS 開發人員歡迎的原因。 它只是使用最好的 JavaScript 來使構建使用者介面更容易和可維護。 在 React 應用程式中,確實有比 React specix 語法更多的 JavaScript ,所以一旦你更好地理解了 JavaScript - 特別是 ES6 - 你就可以自信地編寫 React 應用程式了。 但這並不意味著您必須掌握 JavaScript 的所有內容才能開始編寫 React 應用程式。 現在去寫一個,隨著機會的到來,你將成為一個更好的開發者。 感謝閱讀,我希望你學到一些新東西:)

最後

小冊 你不知道的 Chrome 除錯技巧 已經開始預售啦。

歡迎關注公眾號 「前端惡霸」,掃碼關注,會有很多好東西等著你~

[譯] 在你學習 React 之前必備的 JavaScript 基礎

相關文章