React是用于构建用户界面的JavaScript库,起源于Facebook的内部项目,该公司对市场上所有 JavaScript MVC框架都不满意,决定自行开发一套,用于架设Instagram的网站。于2013年5月开源。
React从一开始就被设计为逐步采用,你可以根据需要使用尽可能少或尽可能多的React。
你可以使用React作为CDN中的<script>标签,或者作为npm上的React包。
一、组件 & Props
组件允许你将 UI 拆分为独立可复用的代码片段,并对每个片段进行独立构思。组件 API
从概念上讲,组件类似于JavaScript函数。它们接受任意输入(即“props”),并返回用于描述页面展示内容的 React 元素。
1.1 函数组件与 class 组件
定义组件最简单的方式就是编写 JavaScript 函数:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。
除了接受输入数据(通过this.props
访问)之外,组件还可以维护内部状态数据(通过this.state
访问)。
当组件的状态数据发生变化时,将通过重新调用render()来更新呈现的标记。
使用外部插件的组件
class MarkdownEditor extends React.Component {
constructor(props) {
super(props);
this.md = new Remarkable();
this.handleChange = this.handleChange.bind(this);
this.state = { value: 'Hello, **world**!' };
}
handleChange(e) {
this.setState({ value: e.target.value });
}
getRawMarkup() {
return { __html: this.md.render(this.state.value) };
}
render() {
return (
<div className="MarkdownEditor">
<h3>Input</h3>
<label htmlFor="markdown-content">
Enter some markdown
</label>
<textarea
id="markdown-content"
onChange={this.handleChange}
defaultValue={this.state.value}
/>
<h3>Output</h3>
<div
className="content"
dangerouslySetInnerHTML={this.getRawMarkup()}
/>
</div>
);
}
}
root.render(<MarkdownEditor />);
二、create-react-app
2.1 创建 react-app
第一种:
npx create-react-app my-app
npm start
Starts the development server.
npm run build
Bundles the app into static files for production.
npm test
Starts the test runner.
npm run eject
Removes this tool and copies build dependencies, configuration files and scripts into the app directory. If you do this, you can’t go back!
We suggest that you begin by typing:
cd my-app
npm start
第二种:
npm init react-app my-app
第三种:
yarn create react-app my-app
cd my-app
yarn start
2.2 Add React to a Website
步骤1:向HTML添加DOM容器
<div id="like_button_container"></div>
我们赋予这个 <div>
一个唯一的id HTML属性。这将允许我们稍后从JavaScript代码中找到它,并在其中显示一个React组件。
步骤2:添加脚本标签
接下来,在HTML页面的</body>
标签之前添加三个
<!-- ... other HTML ... -->
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<!-- Load our React component. -->
<script src="like_button.js"></script>
</body>
前两个标记加载React。第三个将加载组件代码。
步骤3:创建一个React组件
'use strict';
const e = React.createElement; //创建React Element的一种简写形式
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = { liked: false };
}
render() {
if (this.state.liked) {
return 'You liked this.';
}
return e(
'button',
{ onClick: () => this.setState({ liked: true }) },
'Like'
);
}
}
const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(e(LikeButton));
重用组件
通常,你可能希望在 HTML 页面的多个位置展示 React 组件。
为生产环境压缩 JavaScript 代码
在将网站部署到生产环境之前,请注意,未简化的JavaScript会显著降低用户浏览网页的速度。
<script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
可选:用JSX尝试 React
在上面的例子中,我们只依赖于浏览器本身支持的特性。这就是为什么我们使用JavaScript函数调用来告诉React要显示什么:
const e = React.createElement;
// Display a "Like" <button>
return e(
'button',
{ onClick: () => this.setState({ liked: true }) },
'Like'
);
然而,React也提供了一个使用JSX的选项:
// Display a "Like" <button>
return (
<button onClick={() => this.setState({ liked: true })}>
Like
</button>
);
这两个代码片段是等价的。虽然JSX是完全可选的,但许多人发现它对编写UI代码很有帮助——无论是用React还是用其他库。
在你的项目中尝试JSX的最快方法是添加这个<script>
标签到你的页面:
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
现在,可以在任何<script>
标记中使用JSX,只需向其添加type="text/babel"
属性即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function MyApp() {
return <h1>Hello, world!</h1>;
}
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<MyApp />);
</script>
<!--
Note: this page is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Read this section for a production-ready setup with JSX:
https://reactjs.org/docs/add-react-to-a-website.html#add-jsx-to-a-project
In a larger project, you can use an integrated toolchain that includes JSX instead:
https://reactjs.org/docs/create-a-new-react-app.html
You can also use React without JSX, in which case you can remove Babel:
https://reactjs.org/docs/react-without-jsx.html
-->
</body>
</html>
这种方法适用于学习和创建简单的演示。然而,它使你的网站变慢,不适合生产。设置一个JSX预处理器来自动转换所有<script>
标记。
将JSX添加到项目中
添加JSX很像添加CSS预处理器。唯一的要求是在您的计算机上安装Node.js。
在终端进入项目文件夹:
Step 1: Run npm init -y (if it fails, here’s a fix)
Step 2: Run npm install babel-cli@6 babel-preset-react-app@3
运行JSX预处理器
创建一个名为src的文件夹,然后运行terminal命令:
npx babel --watch src --out-dir . --presets react-app/prod
不要等待它完成—该命令为JSX启动一个自动监视程序。
三、 引入JSX
const element = <h1>Hello, world!</h1>;
这种有趣的标记语法既不是字符串也不是HTML。
它被称为JSX,是JavaScript的语法扩展。我们建议在React中使用它来描述UI应该是什么样子。JSX可能会让您想起模板语言,但它附带了JavaScript的全部功能。
React不需要使用JSX,但大多数人发现,在JavaScript代码中使用UI时,它作为可视化辅助很有帮助。它还允许React显示更多有用的错误和警告消息。
3.1 在JSX中嵌入表达式
在下面的例子中,我们声明了一个名为name的变量,然后在JSX中使用它,把它用花括号括起来:
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
可以在JSX的花括号中放入任何有效的JavaScript表达式。例如,2 + 2,user。firstName或formatName(user)都是有效的JavaScript表达式。
在下面的例子中,我们将调用JavaScript函数formatName(user)的结果嵌入到<h1>
元素中。
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
为了可读性,我们将JSX拆分为多行。虽然这不是必需的,但在执行此操作时,我们也建议将其包装在圆括号中,以避免自动插入分号的陷阱。
3.2 JSX也是一个表达式
编译之后,JSX表达式成为常规的JavaScript函数调用,并计算为JavaScript对象。
这意味着可以在if语句和for循环中使用JSX,将它赋值给变量,接受它作为参数,并从函数中返回它:
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
3.3 用JSX指定属性
可以使用引号来指定字符串文字作为属性:
const element = <a href="https://www.reactjs.org"> link </a>;
也可以使用大括号在属性中嵌入JavaScript表达式:
const element = <img src={user.avatarUrl}></img>;
在属性中嵌入JavaScript表达式时,不要在花括号周围加上引号。您应该在同一个属性中使用引号(用于字符串值)或花括号(用于表达式),但不能同时使用引号和花括号。
由于JSX更接近JavaScript而不是HTML, React DOM使用camelCase属性命名约定而不是HTML属性名称。
例如,在JSX中,class变成className, tabindex变成tabindex。
3.4 用JSX指定子节点
如果一个标签是空的,你可以立即用/>
关闭它,就像XML:
const element = <img src={user.avatarUrl} />;
JSX标签可能包含子标签:
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
3.5 JSX防止注入攻击
在JSX中嵌入用户输入是安全的:
const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;
默认情况下,React DOM会在呈现JSX中嵌入的任何值之前转义它们。因此,它确保了您永远不能注入应用程序中没有显式编写的任何内容。在呈现之前,所有内容都转换为字符串。这有助于防止XSS (cross-site-scripting,跨站点脚本)攻击。
3.6 JSX代表对象
Babel将JSX编译为React.createElement()
调用。
这两个例子是一样的:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React.createElement()
执行一些检查来帮助你编写没有bug的代码,但本质上它创建了一个像这样的对象:
// Note: this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
这些对象称为“React元素(React elements)”。你可以把它们看作是你想在屏幕上看到的东西的描述。React读取这些对象并使用它们来构造DOM并保持其最新。
我们建议为您选择的编辑器使用“Babel”语言定义,这样ES6和JSX代码都能正确地突出显示。
FiraCode 字体
WebStorm现在提供了对ES2015+的支持,不需要安装任何额外的扩展。但是,您可能需要启用它。