在你學(xué)習(xí)React之前必備的JavaScript基礎(chǔ)
寫在前面
為了不浪費(fèi)大家的寶貴時(shí)間,在開頭申明一下,這篇文章針對(duì)的閱讀對(duì)象是:沒有寫過 React 或者剛剛才接觸 React 并且對(duì)于 ES6 的語法不太了解的同學(xué),這是一篇基礎(chǔ)入門的文章,在一開始我并沒有準(zhǔn)備翻譯一篇這樣的基礎(chǔ)文章,但是在閱讀完全文之后,我想起自己剛開始學(xué)習(xí) React 時(shí)的迷茫,ES6 有那么多,我需要掌握多少呢?對(duì)于一個(gè)急于上手 React 寫代碼的人來說,這篇文章告訴你最基本要掌握的知識(shí),讓你快速的寫起來。但是后期的提高,仍舊需要去夯實(shí) Javascript 的基礎(chǔ)。
前言
在理想的狀態(tài)下,你可以在深入了解React之前了解 JavaScript 和Web 開發(fā)的所有知識(shí)。 不幸的是,我們生活在一個(gè)不***的世界,所以在 React 之前把所有的JavaScript 都咀嚼一遍只會(huì)讓你舉步維艱。 如果你已經(jīng)擁有一些 JavaScript 經(jīng)驗(yàn),那么在 React 之前你需要學(xué)習(xí)的只是實(shí)際用于開發(fā) React 應(yīng)用程序的 JavaScript 功能。 在學(xué)習(xí) React之前你應(yīng)該學(xué)會(huì)的JavaScript 的知識(shí)點(diǎn):
- ES6 類
- 使用 let / const 聲明變量
- 箭頭函數(shù)
- 解構(gòu)賦值
- Map 和 filter
- ES6 模塊系統(tǒng)
這是你將在 80% 的時(shí)間內(nèi)使用的20% 的 JavaScript 新特性,因此在本文中,我將幫助你學(xué)習(xí)所有這些特性。
創(chuàng)建 React 應(yīng)用程序的探索
開始學(xué)習(xí) React 的常見情況是運(yùn)行 create-react-app 包,它會(huì)設(shè)置運(yùn)行 React 所需的一切。 該過程完成之后,打開 src / app.js 這里給我們展示了整個(gè)應(yīng)用程序中唯一的 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;
如果之前你從未學(xué)習(xí)過 ES6 ,那么你可能認(rèn)為這個(gè) class 語句是 React 的一個(gè)特性。 實(shí)際上這是 ES6 的一個(gè)新特性,這就是為什么正確學(xué)習(xí) ES6 可以讓你更好地理解 React 代碼。 我們將從 ES6 的類開始。
ES6 的類
ES6 引入了 class 語法,類似于 Java 或 Python 等 OO(面向?qū)ο? 語言。 ES6 中的基本類如下所示:
- class Developer {
- constructor(name){
- this.name = name;
- }
- hello(){
- return 'Hello World! I am ' + this.name + ' and I am a web developer';
- }
- }
class 語法后跟一個(gè)可用于創(chuàng)建新對(duì)象的標(biāo)識(shí)符(或一個(gè)名稱)。 始終在對(duì)象初始化中調(diào)用構(gòu)造函數(shù)方法。 傳遞給這個(gè)對(duì)象的任何參數(shù)都將傳遞給新對(duì)象。 例如:
- var nathan = new Developer('Nathan');
- nathan.hello(); // Hello World! I am Nathan and I am a web developer
類可以定義任意它所需的方法,在這種情況下,我們定義了一個(gè)返回字符串的 hello 方法。
類繼承
類可以擴(kuò)展另一個(gè)類的定義,從該類初始化的新對(duì)象將具有這兩個(gè)類的所有方法。
- 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.
繼承另一個(gè)類的類,通常稱為 child 類或 sub 類,而正在擴(kuò)展的類稱為 parent 類或 super 類。 子類也可以覆蓋父類中定義的方法,這意味著它將使用自己定義的新方法來替換父類方法的定義。 例如,讓我們覆蓋 hello 函數(shù):
- 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 中使用
現(xiàn)在我們了解了 ES6 的類和繼承,我們可以理解 src / app.js 中定義的 React 類。 這是一個(gè) React 組件,但它實(shí)際上只是一個(gè)普通的 ES6 類,它繼承了從 React 包導(dǎo)入的 React Component 類的定義。
- import React, { Component } from 'react';
- class App extends Component {
- // class content
- render(){
- return (
- <h1>Hello React!</h1>
- )
- }
- }
這使得我們能夠使用 render() 方法,JSX ,this.state 和其他方法。 所有這些定義都在Component 類中。 但正如我們稍后將看到的,class 不是定義 React Component 的唯一方法。 如果你不需要狀態(tài)和其他生命周期方法,則可以使用函數(shù)。
使用 ES6 中的 let 和 const 來聲明變量
因?yàn)?JavaScript 的 var 關(guān)鍵字是聲明全局的變量,所以在 ES6 中引入了兩個(gè)新的變量聲明來解決這個(gè)問題,即 let 和 const 。 它們都用于聲明變量。 區(qū)別在于 const 在聲明后不能改變它的值,而 let 則可以。 這兩個(gè)聲明都是本地的,這意味著如果在函數(shù)作用域內(nèi)聲明 let ,則不能在函數(shù)外部調(diào)用它。
- const name = "David";
- let age = 28;
- var occupation = "Software Engineer";
用哪個(gè)呢?
按以往經(jīng)驗(yàn)來說,默認(rèn)使用 const 聲明變量。 稍后當(dāng)您編寫應(yīng)用程序時(shí),當(dāng)你意識(shí)到 const 的值需要更改,才是你應(yīng)該將const 重構(gòu)為 let 時(shí)。 希望它會(huì)讓你習(xí)慣新的關(guān)鍵字,并且你將開始認(rèn)識(shí)到應(yīng)用程序中需要使用 const 或 let 的模式。
我們什么時(shí)候在 React 中使用呢?
在我們需要變量的時(shí)候:
- import React, { Component } from 'react';
- class App extends Component {
- // class content
- render(){
- const greeting = 'Welcome to React';
- return (
- <h1>{greeting}</h1>
- )
- }
- }
在整個(gè)應(yīng)用的生命周期中 greeting 并不會(huì)發(fā)生改變,所以我們?cè)谶@里使用 const
箭頭函數(shù)
箭頭函數(shù)是 ES6 的一種新特性,在現(xiàn)代代碼庫中幾乎被廣泛使用,因?yàn)樗勾a簡(jiǎn)潔易讀。 它允許我們使用更短的語法編寫函數(shù)。
- // regular function
- const testFunction = function() {
- // content..
- }
- // arrow function
- const testFunction = () => {
- // content..
- }
如果您是一位經(jīng)驗(yàn)豐富的 JS 開發(fā)人員,那么從常規(guī)函數(shù)語法轉(zhuǎn)換為箭頭語法可能會(huì)讓您感到不舒服。 當(dāng)我學(xué)習(xí)箭頭函數(shù)時(shí),我用這兩個(gè)簡(jiǎn)單的步驟來重寫我的函數(shù):
- 移除 function 關(guān)鍵字
- 在 () 后面加上 =>
括號(hào)仍然用于傳遞參數(shù),如果只有一個(gè)參數(shù),則可以省略括號(hào)。
- const testFunction = (firstName, lastName) => {
- return firstName+' '+lastName;
- }
- const singleParam = firstName => {
- return firstName;
- }
隱藏的 return
如果箭頭函數(shù)只有一行,則可以返回值而無需使用 return 關(guān)鍵字以及大括號(hào)。
- 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 應(yīng)用程序中使用箭頭功能可使代碼更簡(jiǎn)潔。 但它也會(huì)從組件中刪除狀態(tài)的使用。 這種類型的組件稱為無狀態(tài)功能組件。 你會(huì)在許多 React 教程中看到這個(gè)名字。
解析數(shù)組和對(duì)象的賦值
ES6 中引入的最有用的新語法之一,解構(gòu)賦值只是復(fù)制對(duì)象或數(shù)組的一部分并將它們放入命名變量中。 一個(gè)簡(jiǎn)單的例子:
- 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
如您所見,我們將開發(fā)人員對(duì)象中的 firstName 和 lastName 分配給新變量 firstName 和 lastName 。 現(xiàn)在,如果要將 firstName 放入名為 name 的新變量中,該怎么辦?
- const { firstName:name } = developer;
- console.log(name); // returns 'Nathan'
解構(gòu)也適用于數(shù)組,使用索引而不是對(duì)象鍵:
- const numbers = [1,2,3,4,5];
- const [one, two] = numbers; // one = 1, two = 2
你可以通過傳入 , 來在解構(gòu)的過程中跳過一些下標(biāo):
- const [one, two, , four] = numbers; // one = 1, two = 2, four = 4
在 React 中的使用
最常見是在方法中解構(gòu) state:
- reactFunction = () => {
- const { name, email } = this.state;
- };
或者是在無狀態(tài)的函數(shù)組件中,結(jié)合之前提到的例子:
- const HelloWorld = (props) => {
- return <h1>{props.hello}</h1>;
- }
我們可以立即簡(jiǎn)單地解構(gòu)參數(shù):
- const HelloWorld = ({ hello }) => {
- return <h1>{hello}</h1>;
- }
Map 和 filter
雖然本文側(cè)重于 ES6 ,但需要提及 JavaScript 數(shù)組 Map 和 filter 方法,因?yàn)樗鼈兛赡苁菢?gòu)建 React 應(yīng)用程序時(shí)最常用的 ES5 功能之一。 特別是在處理數(shù)據(jù)上。
這兩種方法在處理數(shù)據(jù)時(shí)使用得更多。 例如,假設(shè)從 API 結(jié)果中獲取返回 JSON 數(shù)據(jù)的數(shù)組:
- const users = [
- { name: 'Nathan', age: 25 },
- { name: 'Jack', age: 30 },
- { name: 'Joe', age: 28 },
- ];
然后我們可以在 React 中呈現(xiàn)項(xiàng)目列表,如下所示:
- 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 中篩選數(shù)據(jù)
- <ul>
- {users
- .filter(user => user.age > 26)
- .map(user => <li>{user.name}</li>)
- }
- </ul>
ES6 模塊系統(tǒng)
ES6 模塊系統(tǒng)使 JavaScript 能夠?qū)牒蛯?dǎo)出文件。 讓我們?cè)倏匆幌?src / app.js 代碼來解釋這一點(diǎn)。
- 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;
要理解這些語句,我們先討論模塊語法。
模塊只是一個(gè) JavaScript 文件,它使用 export 關(guān)鍵字導(dǎo)出一個(gè)或多個(gè)值(可以是對(duì)象,函數(shù)或變量)。 首先,在 src 目錄中創(chuàng)建一個(gè)名為 util.js 的新文件
- touch util.js
然后我們?cè)谶@里面寫一個(gè)函數(shù),使用一個(gè)默認(rèn)導(dǎo)出
- export default function times(x) {
- return x * x;
- }
或多個(gè)命名的導(dǎo)出
- 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));
每個(gè)模塊可以有多個(gè)命名導(dǎo)出但只有一個(gè)默認(rèn)導(dǎo)出。 可以導(dǎo)入默認(rèn)導(dǎo)出,而無需使用花括號(hào)和相應(yīng)的導(dǎo)出函數(shù)名稱:
- // 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
但是對(duì)于命名導(dǎo)出,必須使用花括號(hào)和確切名稱導(dǎo)入。 或者,import可以使用別名來避免兩個(gè)不同的導(dǎo)入具有相同的名稱:
- // 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 以獲取相應(yīng)的包名稱。 因此,如果您要導(dǎo)入本地文件,請(qǐng)不要忘記使用正確的路徑。
在 React 中使用
顯然我們已經(jīng)在 src / App.js 文件中看到了這個(gè),然后在 index.js 文件中看到了導(dǎo)出的 App 組件的呈現(xiàn)方式。 我們暫時(shí)忽略 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();
請(qǐng)注意如何從 ./App 目錄導(dǎo)入 App ,并省略了 .js 擴(kuò)展名。 我們只能在導(dǎo)入 JavaScript 文件時(shí)省略文件擴(kuò)展名,但在其他文件中我們必須包含擴(kuò)展名,例如 .css 。 我們還導(dǎo)入另一個(gè) node 模塊 react-dom ,這使我們能夠?qū)?React 組件呈現(xiàn)為 HTML元素。
至于 PWA ,它是使 React 應(yīng)用程序脫機(jī)工作的一項(xiàng)功能,但由于默認(rèn)情況下它已被禁用,因此無需在開始時(shí)學(xué)習(xí)它。 在你有足夠的信心構(gòu)建 React 用戶界面之后,***學(xué)習(xí) PWA 。
總結(jié)
React 的優(yōu)點(diǎn)在于它不會(huì)像其他 Web 框架一樣在 JavaScript 之上添加任何外部抽象層。 這就是為什么 React 變得非常受 JS 開發(fā)人員歡迎的原因。 它只是使用***的 JavaScript 來使構(gòu)建用戶界面更容易和可維護(hù)。 在 React 應(yīng)用程序中,確實(shí)有比 React specix 語法更多的 JavaScript ,所以一旦你更好地理解了 JavaScript - 特別是 ES6 - 你就可以自信地編寫 React 應(yīng)用程序了。 但這并不意味著您必須掌握 JavaScript 的所有內(nèi)容才能開始編寫 React 應(yīng)用程序。 現(xiàn)在去寫一個(gè),隨著機(jī)會(huì)的到來,你將成為一個(gè)更好的開發(fā)者。
感謝閱讀,我希望你學(xué)到一些新東西:)