译-在你学习-React-之前必备的-JavaScript-基础

36次阅读

共计 7768 个字符,预计需要花费 20 分钟才能阅读完成。

  • 原文地址:JavaScript Basics Before You Learn React
  • 原文作者:Nathan Sebhastian

写在前面

为了不浪费大家的宝贵时间,在开头申明一下,这篇文章针对的阅读对象是:没有写过 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 调试技巧 已经开始预售啦。

欢迎关注公众号「前端恶霸」,扫码关注,会有很多好东西等着你~

正文完
 0