学习 React 之前的 JavaScript 基础知识
在理想情况下,您可以在深入研究 React 之前了解有关 JavaScript 和 Web 开发的所有知识。
不幸的是,我们生活在一个不完美的世界,因此在 React 之前学习所有的 JavaScript 只会让你付出惨痛的代价。
如果您已经具有一些 JavaScript 经验,那么在 React 之前您需要学习的只是实际用于开发 React 应用程序的 JavaScript 功能。
在学习 React 之前,你应该熟悉 JavaScript 的以下方面:
您 80% 的时间都会用到 20% 的 JavaScript 功能,因此在本教程中我将帮助您学习所有功能。
探索 Create React App
开始学习 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 的 class 开始。
ES6 类
ES6 引入了类语法,其使用方式与 Java 或 Python 等面向对象语言类似。ES6 中的基本类如下所示:
class Developer {
constructor(name){
this.name = name;
}
hello(){
return 'Hello World! I am ' + this.name + ' and I am a web developer';
}
}
class
语法后面跟着一个标识符(或简称为名称),可用于创建新对象。该constructor
方法始终在对象初始化时调用。任何传递给对象的参数都将传递到新对象中。例如:
var nathan = new Developer('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a web developer
一个类可以根据需要定义任意数量的方法,在本例中,我们有hello
一个返回字符串的方法。
类继承
一个类可以extends
定义另一个类,并且从该类初始化的新对象将具有这两个类的所有方法。
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.
另一个类extends
通常被称为子类或子类,而被扩展的类被称为父类或超类。子类也可以覆盖父类中定义的方法,这意味着它将用新定义的方法替换父类中的方法定义。例如,让我们覆盖以下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
就是这样。类中hello
的方法Developer
已被覆盖。
在 React 中使用
现在我们了解了 ES6 类和继承,我们可以理解 中定义的 React 类了src/app.js
。这是一个 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
类内部。但正如我们稍后会看到的,类并不是定义 React 组件的唯一方法。如果你不需要状态和其他生命周期方法,你可以使用函数。
使用 ES6 声明变量let
和const
由于 JavaScriptvar
关键字声明变量时会将其声明为全局变量,因此 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>
)
}
}
由于问候语在整个应用程序生命周期内不会改变,因此我们const
在这里使用它来定义它。
箭头函数
箭头函数是 ES6 的一项新功能,它在现代代码库中被广泛使用,因为它可以保持代码的简洁性和可读性。此功能允许我们使用更短的语法编写函数。
// regular function
const testFunction = function() {
// content..
}
// arrow function
const testFunction = () => {
// content..
}
如果你是一位经验丰富的 JS 开发者,从常规函数语法过渡到箭头语法一开始可能会有些不适应。我在学习箭头函数时,使用了以下两个简单的步骤来重写函数:
- 删除函数关键字
=>
在后面添加粗箭头符号()
括号仍然用于传递参数,如果只有一个参数,则可以省略括号。
const testFunction = (firstName, lastName) => {
return firstName+' '+lastName;
}
const singleParam = firstName => {
return firstName;
}
隐式回报
如果箭头函数只有一行,则可以返回值而无需使用return
关键字和花括号{}
const testFunction = () => 'hello there.';
testFunction();
在 React 中使用
创建 React 组件的另一种方法是使用箭头函数。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
如您所见,我们将developer
对象中的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>;
}
解构数组也用于 React 的useState
钩子上:
const [user, setUser] = useState('');
地图和过滤器
虽然本教程主要关注 ES6,但 JavaScript 数组map
和filter
方法也需要提及,因为它们可能是构建 React 应用程序时最常用的 ES5 特性之一,尤其是在处理数据时。
这两个方法在数据处理中用得比较多。例如,假设一个 API 的 fetch 返回一个 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>
)
}
}
我们还可以在渲染中过滤数据。
<ul>
{users
.filter(user => user.age > 26)
.map(user => <li>{user.name}</li>)
}
</ul>
ES6 模块系统
src/app.js
ES6 模块系统使 JavaScript 能够导入和导出文件。为了解释这一点,我们再看一遍代码。
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 React, { Component } from 'react';
在最后一行我们看到这样的export default
语句:
export default App;
为了理解这些语句,我们首先讨论一下模块语法。
模块其实就是一个 JavaScript 文件,它使用 关键字导出一个或多个值(可以是对象、函数或变量) 。首先,在目录中export
创建一个名为util.js
src
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
import k from './util.js';
console.log(k(4)); // returns 16
但是对于命名导出,必须使用花括号和确切的名称进行导入。或者,导入可以使用别名,以避免两个不同的导入使用相同的名称:
// 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
。我们还导入了另一个节点模块react-dom
,它使我们能够将 React 组件渲染为 HTML 元素。
至于 PWA,它是一项使 React 应用程序离线运行的功能,但由于默认情况下禁用,因此一开始无需学习它。最好在对构建 React 用户界面有足够的信心后再学习 PWA。
结论
React 的优点在于它不会像其他 Web 框架那样在 JavaScript 之上添加任何外部抽象层。
这就是 React 在 JS 开发者中如此受欢迎的原因。它充分利用了 JavaScript 的精髓,使用户界面的构建更加简单易维护。
React 应用程序中的 JavaScript 确实比 React 特定的语法更多,因此一旦你更好地理解了 JavaScript(特别是 ES6),你就可以自信地编写 React 应用程序。
但这并不意味着你必须精通 JavaScript 才能开始编写 React 应用。现在就去写一个吧,随着机会的到来,你会成为一名更优秀的开发者。
如果您喜欢这篇文章,请考虑在 Twitter 上关注我,以便在我发布新的编程相关文章时收到通知。
文章来源:https://dev.to/codewithnathan/javascript-basics-before-you-learn-react-38en