React正在接管网络开发的世界,这是有充分理由的。 React由Facebook创建并于2013年发行,是一个开源JavaScript库,用于构建已经彻底改变前端开发的用户界面。
在本针对初学者的综合指南中,我们将介绍您需要知道的所有核心概念,以便与React一起启动并运行。您将学习基本主题,例如:
- React如何工作以及为什么有用
- JSX语法
- 组件,道具和状态
- 处理事件
- 虚拟DOM
- 使用表格
- 获取数据
- Routing
最后,您将对React基本面有一个可靠的掌握,并准备好构建应用程序。让我们开始!
React如何工作
在其核心上,反应都是关于组件的。一个React应用程序包含多个可重复使用的组件,每个组件负责渲染整体UI的一小部分。
例如,您可以拥有一个Navbar组件,侧边栏组件,表单组件等。
每个组件都会管理其内部状态并基于该状态渲染UI。当组件的状态更改时,React将有效地更新并重新渲染需要重新渲染的组件。这要归功于React对虚拟DOM的使用。
虚拟DOM是实际DOM的JavaScript表示。当组件的状态更改时,React将结果的虚拟DOM与以前的虚拟DOM进行比较。
然后,它算出了同步它们所需的最小实际DOM操作集。
这意味着您不必担心自己更改DOM - 反应会自动处理幕后。
这最终允许与传统的JavaScript应用程序手动操纵DOM。
React还利用单向数据流。状态通过道具从父零件传递到子女组件。
当需要更新状态时,它是通过回调函数完成的,而不是直接修改状态。
这种单向数据流使您的应用程序中的状态管理更加容易。它还有助于隔离组件,因为每个组件都与国家的本地副本一起工作,而不是依靠全球状态。
总而言之,这是React的一些关键优势:
- 声明性 - React使用声明代码来基于状态而不是手动更新DOM的命令代码渲染UI。
- 基于组件的 - 构建封装的组件来管理自己的状态。
- 学习一次,在任何地方写下 - 可用于Web,Mobile,VR甚至本地桌面应用程序。
- 高性能 - 虚拟DOM使反应非常快速有效。
JSX语法
React使用称为JSX的JavaScript的语法扩展来描述UI的外观。 JSX看起来像HTML和JavaScript的组合:
const element = <h1>Hello, world!</h1>;
此语法被处理到标准的JavaScript函数调用和对象中。 Babel通常在React Apps中用于将JSX代码转换为常规JavaScript,浏览器可以理解。
一个关键区别是JSX使用className而不是添加CSS类的类,因为类是JavaScript中的一个保留单词。
您可以通过用卷曲括号包裹JSX代码中的任何有效的JavaScript表达式:
const name = 'John';
const element = <h1>Hello, {name}</h1>;
JSX元素可以像HTML元素一样具有属性。但是,您不能使用类似类和类似的关键字,因为它们是在JavaScript中保留的。相反,react dom组件期望诸如htmlfor和className之类的属性:
const element = <div className="container">
<label htmlFor="name">Enter name:</label>
<input id="name" />
</div></code></pre>
You can also nest child elements inside a parent JSX element:
<pre><code class="language-javascript">const element = (
<div>
<h1>I am the title</h1>
<p>This is a paragraph</p>
</div>
)
JSX允许我们编写看起来像HTML的标记,还可以让我们在该标记中使用JavaScript的全部功能。这就是使反应对UI开发如此有用的原因。
组件,道具和状态
组件是任何React应用程序的构件。组件是一个独立的UI件,可封装标记和逻辑。
这是一个简单按钮组件的示例:
function Button(props) {
return <button>{props.text}</button>;
}
此功能接受道具作为参数,访问道具上的文本属性,然后返回显示按钮元素的JSX。
组件可以是函数或类。功能组件更简单,因为它们只需要接收道具并返回JSX。
有一个组件后,您可以通过将JSX传递给ReactDOM.render()
:
将其渲染
const root = document.getElementById('root');
ReactDOM.render(
<Button text="Click me"/>,
root
);
组件可以嵌套在其他组件中以构建复杂的UI:
function App() {
return (
<div>
<Button text="Save" />
<Button text="Cancel" />
</div>
)
}
道具是数据传递到组件的方式。它们是不变的,不应在组件内更改。
状态保存可以随时间变化的数据,从而触发UI更新。创建组件时应初始化状态:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: 0};
}
}
只能使用setState()修改状态:
this.setState({count: this.state.count + 1});
调用setState()触发器会反应以新状态值重新渲染组件。这是React如何使UI与数据同步。
处理事件
用反应元素处理事件类似于用DOM元素处理事件。有一些关键语法差异:
- 用骆驼而不是小写(OnClick变为onClick)命名的React事件
- 您将功能作为事件处理程序而不是字符串传递
例如,要处理单击事件:
function Button(props) {
function handleClick() {
console.log('Clicked!');
}
return <button onClick={handleClick}>Click Me</button>
}
请注意,HandleClick是一种普通的JS函数,包含您要在单击元素时要运行的任何代码。
您还可以绑定构造函数中的事件处理程序:
class Button extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// event handler logic
}
render() {
return <button onClick={this.handleClick}>Click Me</button>
}
}
绑定呼叫创建了一个新函数,该函数范围为组件实例。这使您可以访问道具并在处理程序内正确陈述道具。
您也可以将自定义参数传递给事件处理程序:
<button onClick={() => this.handleClick(id)} />
这对于传递元素或其他数据的ID很有用。
虚拟dom
使React如此性能的核心功能之一是使用虚拟DOM。
让我们考虑UI更新如何在没有虚拟DOM的情况下工作。当状态发生变化时,React必须操纵实际的DOM才能直接更改渲染内容。对于具有较大DOMS和频繁更新的应用程序,这可能很慢。
相反,React在内存中保持UI的轻量级虚拟表示。该虚拟DOM是React组件和实际DOM之间的抽象层。
当状态在组件中发生变化时,React通过组合应用程序的组件树来创建一个新的虚拟DOM树。
然后将新的虚拟DOM与先前的虚拟DOM进行比较。此过程称为“分散”。
反应准确地算出了哪些虚拟DOM节点通过此扩散过程发生了变化。最后,React仅更新实际DOM中的那些更改的DOM节点。
由于虚拟DOM可以快速更新而无需触摸真实的DOM,因此性能得到显着提高。
React必须只对真实DOM进行有针对性的更新,而不是从头开始重新渲染所有内容。这使得重新渲染过程更快,更有效。
开发人员根本不必考虑虚拟DOM。这是完全由React处理的实现细节。但是,了解其在引擎盖下的工作方式可以帮助解释React的性能优势。
钩
在React 16.8中引入了钩子以使用状态,而功能组件中的其他React特征则引入。
。在挂钩之前,功能组件只能根据其道具渲染UI - 它们缺乏像只有类组件的状态这样的能力。
挂钩允许功能组件做所有类都可以做的事情,除了上下文和生命周期方法之类的功能。一些常用的内置钩子包括:
usestate:将状态添加到功能组件:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
使用效果:添加了从功能组件中执行副作用的能力:
import { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = You clicked ${count} times;
});
return (
//...
)
}
usecontext:从函数组件中消耗上下文:
const ThemeContext = React.createContext('light');
function Button() {
const theme = useContext(ThemeContext);
return (
<button className={theme}>OK</button>
);
}
与内置的钩子一起,您可以创建自定义钩以共享可重复使用的逻辑。
使用表格
反应中的形式处理涉及:
- 将状态添加到跟踪表单输入值
- 聆听输入上的变更事件以更新该状态
- 渲染以设置输入值时从状态访问值
例如:
class Form extends React.Component {
state = {name: ''};
handleChange = (e) => {
this.setState({name: e.target.value})
}
render() {
return (
<>
<input
value={this.state.name}
onChange={this.handleChange}
/>
<p>{this.state.name}</p>
</>
)
}
}
受控的与不受控制的组件
React表格可以使用受控或不受控制的组件:
- 控制:由React状态处理的值
- 不受控制的:DOM本身处理的值
使用不受控制的组件,您使用refs来访问dom输入值,而不是直接访问状态。
处理多个输入
您可以分别跟踪每个输入的状态:
state = {
name: '',
email: ''
};
handleNameChange = (e) => {
this.setState({name: e.target.value});
}
handleEmailChange = (e) => {
this.setState({email: e.target.value});
}
render() {
return (
<>
<input
value={this.state.name}
onChange={this.handleNameChange}
/>
<input
value={this.state.email}
onChange={this.handleEmailChange}
/>
</>
)
}
或将状态作为一个对象管理:
state = {
formData: {
name: '',
email: ''
}
};
handleChange = (e) => {
this.setState({
formData: {
...this.state.formData,
[e.target.name]: e.target.value
}
});
}
render() {
return (
<>
<input
name="name"
value={this.state.formData.name}
onChange={this.handleChange}
/>
// ...
</>
)
}
这使用计算的属性名称仅更新formdata中的一个密钥。
处理提交
使用一个防止默认提交的提交处理程序,然后调用函数来处理表单值:
handleSubmit = (e) => {
e.preventDefault();
this.processForm();
}
processForm() {
// send data to server
}
render() {
return (
<form onSubmit={this.handleSubmit}>
// inputs
<button>Submit</button>
</form>
)
}
验证
有诸如Formik之类的库可以帮助验证。您也可以在提交时进行验证:
handleSubmit = (e) => {
e.preventDefault();
// validate form
if(valid) {
this.processForm();
}
}
通过以状态跟踪用户向用户显示验证错误。
获取数据
使用效果挂钩可用于在安装和状态更改上获取数据:
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/some-api')
.then(res => res.json())
.then(setData);
}, []); // empty deps = only on mount
//...
}
空阵列意味着此效果只能在安装座上,而不是在重新租户上运行。
您也可以在状态更改中获取:
useEffect(() => {
// refetch data
}, [someStateVar]);
现在,如果有变化,它将重新运行。
- 处理加载状态
获取时,数据将为null。您可以跟踪状态:
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetchData().then(data => {
setData(data);
setLoading(false);
})
}, [])
然后在显示数据之前检查加载:
return (
{loading && <p>Loading...</p>}
{data && <DisplayData data={data} />}
)
- 错误处理
通过添加捕获量来处理错误:
useEffect(() => {
setLoading(true);
fetchData()
.then(setData)
.catch(error => {
// handle error
})
.finally(() => setLoading(false))
}, [])
或使用尝试/捕获:
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const data = await fetchData();
setData(data);
} catch (error) {
// handle error
} finally {
setLoading(false);
}
}
fetchData();
}, [])
跟踪错误状态要显示给用户。
路由
用于在React中进行路由,通常使用React路由器库。
首先,用
然后使用<链接>创建链接而不是锚标记:
<Link to="/about">About</Link>
并使用<路由>定义路由:
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
完全匹配路径完全是“ /". p>)
路由组件接收历史,位置和匹配道具。
匹配路由的组件将渲染。
路由器可以使用推动和替换进行导航:
history.push('/about')
路由参数:
<Route path="/user/:id" component={User} />
// User component
const { id } = this.props.match.params;</code></pre>
Query strings:
<pre><code class="language-javascript"><Link to="/posts?sortBy=newest" />
// Get search string
const { search } = this.props.location;
// ?sortBy=newest
// Parse with query-string pkg
import queryString from 'query-string';
const { sortBy } = queryString.parse(search);
// newest
嵌套路线:
<Route path="/users" component={Users}>
<Route path=":id" component={User} />
</Route>
重定向:
<Redirect from="/old-path" to="/new-path" />
有条件:
<Route
path="/dashboard"
render={() => (
loggedIn ? (
<Dashboard />
) : (
<Redirect to="/login" />
)
)}
/>
处理404:
<Switch>
<Route exact path="/" />
<Route component={NotFound} />
</Switch>
编程导航:
const history = useHistory();
history.push('/login');
结论
涵盖了React的核心基础知识!有了这个基础,您应该准备开始构建应用程序。
关键要点包括:
- React全部关于模块化,可重复使用的组件
- JSX混合HTML和JavaScript宣布UI
- Props将数据传递到组件中,State拥有随时间变化的数据
- 虚拟DOM通过最小化DOM更新来提高性能
希望您喜欢阅读本指南,并有动力开始您的Python编程旅程。
如果您发现这篇文章令人兴奋,请在Learnhub Blog上找到更多令人兴奋的帖子;我们编写从Cloud computing到Frontend Dev,Cybersecurity,AI和Blockchain的所有技术。