- 原文地址:JavaScript Basics Before You Learn React
- 原文作者:Nathan Sebhastian
写在前面
为了不浪费大家的宝贵时间,在开头申明一下,这篇文章针对的阅读对象是:没有写过 React
或者刚刚才接触 React
并且对于 ES6
的语法不太了解的同学,这是一篇基础入门的文章,在一开始我并没有准备翻译一篇这样的基础文章,但是在阅读完全文之后,我想起自己刚开始学习 React
时的迷茫,ES6
有那么多,我需要掌握多少呢?对于一个急于上手 React
写代码的人来说,这篇文章告诉你最基本要掌握的知识,让你快速的写起来。但是后期的提高,仍旧需要去夯实 Javascript
的基础。
前言
在理想的状态下,你可以在深入了解 React 之前了解 JavaScript
和 Web
开发的所有知识。不幸的是,我们生活在一个不完美的世界,所以在 React
之前把所有的JavaScript
都咀嚼一遍只会让你举步维艰。如果你已经拥有一些 JavaScript
经验,那么在 React
之前你需要学习的只是实际用于开发 React
应用程序的 JavaScript
功能。在学习 React
之前你应该学会的JavaScript
的知识点:
-
ES6
类 - 使用
let
/const
声明变量 - 箭头函数
- 解构赋值
-
Map
和filter
-
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
语法,类似于 Java
或 Python
等 OO
(面向对象) 语言。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()
方法,JSX
,this.state
和其他方法。所有这些定义都在Component
类中。但正如我们稍后将看到的,class
不是定义 React Component
的唯一方法。如果你不需要状态和其他生命周期方法,则可以使用函数。
使用 ES6
中的 let
和 const
来声明变量
因为 JavaScript
的 var
关键字是声明全局的变量,所以在 ES6
中引入了两个新的变量声明来解决这个问题,即 let
和 const
。它们都用于声明变量。区别在于 const
在声明后不能改变它的值,而 let
则可以。这两个声明都是本地的,这意味着如果在函数作用域内声明 let
,则不能在函数外部调用它。
const name = "David";
let age = 28;
var occupation = "Software Engineer";
用哪个呢?
按以往经验来说,默认使用 const
声明变量。稍后当您编写应用程序时,当你意识到 const
的值需要更改,才是你应该将const
重构为 let
时。希望它会让你习惯新的关键字,并且你将开始认识到应用程序中需要使用 const
或 let
的模式。
我们什么时候在 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
开发人员,那么从常规函数语法转换为箭头语法可能会让您感到不舒服。当我学习箭头函数时,我用这两个简单的步骤来重写我的函数:
- 移除
function
关键字 - 在
()
后面加上=>
括号仍然用于传递参数,如果只有一个参数,则可以省略括号。
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
如您所见,我们将开发人员对象中的 firstName
和 lastName
分配给新变量 firstName
和 lastName
。现在,如果要将 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>;
}
Map
和 filter
虽然本文侧重于 ES6
,但需要提及 JavaScript
数组 Map
和 filter
方法,因为它们可能是构建 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 调试技巧 已经开始预售啦。
欢迎关注公众号「前端恶霸」,扫码关注,会有很多好东西等着你~