博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
③ React 条件渲染、组件生命周期、表单与事件
阅读量:3965 次
发布时间:2019-05-24

本文共 9638 字,大约阅读时间需要 32 分钟。

查看专栏其它文章:


React


本人是个新手,写下博客用于自我复习、自我总结。

如有错误之处,请各位大佬指出。
学习资料来源于:尚硅谷


条件渲染

在 React 中,你可以创建不同的组件来封装各种你需要的行为。然后还可以根据应用的状态变化只渲染其中的一部分。

React 中的条件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI。


元素变量

为了更方便的使用,我们可以使用变量来储存元素,它可以帮我们有条件的渲染组件的一部分,而输出的其他部分不会更改。

例:

class LoginControl extends React.Component {
constructor(props) {
super(props); this.handleLoginClick = this.handleLoginClick.bind(this); this.handleLogoutClick = this.handleLogoutClick.bind(this); this.state = {
isLoggedIn: false}; } handleLoginClick() {
this.setState({
isLoggedIn: true}); } handleLogoutClick() {
this.setState({
isLoggedIn: false}); } render() {
const isLoggedIn = this.state.isLoggedIn; let button; if (isLoggedIn) {
button =
; } else {
button =
; } return (
{
button}
); }}function UserGreeting(props) {
return

欢迎回来!

;}function GuestGreeting(props) {
return

请先注册。

;}function Greeting(props) {
const isLoggedIn = props.isLoggedIn; if (isLoggedIn) {
return
; } return
;}function LoginButton(props) {
return ( );}function LogoutButton(props) {
return ( );}ReactDOM.render(
, document.getElementById('example'));

与运算符 和 三目运算符

你可以通过用花括号包裹代码在 JSX 中嵌入任何表达式 ,也包括 JavaScript 的逻辑与 &&,它可以方便地条件渲染一个元素。

function Mailbox(props) {
const unreadMessages = props.unreadMessages; return (

Hello!

{
unreadMessages.length > 0 &&

您有 {
unreadMessages.length} 条未读信息。

}
);} const messages = ['React', 'Re: React', 'Re:Re: React'];ReactDOM.render(
, document.getElementById('example'));

在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。

因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。

对于三目运算符

render() {
const isLoggedIn = this.state.isLoggedIn; return (
{
isLoggedIn ? (
) : (
)}
);}

除此以外,我们有时并不想从多个组件中选择出一个渲染,而只是想 显示 / 隐藏 某一个组件,此时让 render 方法返回 null 即可。比如:

function WarningBanner(props) {
if (!props.warn) {
return null; } return (
警告!
);} class Page extends React.Component {
constructor(props) {
super(props); this.state = {
showWarning: true} this.handleToggleClick = this.handleToggleClick.bind(this); } handleToggleClick() {
this.setState({
showWarning: !this.state.showWarning }); } render() {
return (
); }} ReactDOM.render(
, document.getElementById('example'));

组件生命周期

组件对象从创建到死亡,它会经历特定的生命周期阶段。React 就为组件对象创建了一系列的勾子函数( 即生命周期回调函数 ),在这些特定的生命周期阶段回调。之后我们在定义组件时,可以重写这些特定的生命周期回调函数,用来做特定的工作。

组件的生命周期可分成三个状态:

Mounting:已插入真实 DOM

Updating:正在被重新渲染

Unmounting:已移出真实 DOM

生命周期的方法有:

componentWillMount 在渲染前调用,在客户端也在服务端。

componentDidMount 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。

componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。

shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。(可以在你确认不需要更新组件时使用)

componentWillUpdate 在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。

componentWillUnmount 在组件从 DOM 中移除之前立刻被调用

这些方法的详细说明,可以参考。

在这里插入图片描述
这里的this.forceUpdate()。它的作用就是重新 render,但是会跳过 shouldComponentUpdate(),包括每个子组件的 shouldComponentUpdate()。可能需要使用它是因为如下情况:我们已知,当组件的 state 或 props 改变时,组件将重新渲染。 但如果你的 render() 方法依赖于一些其他数据,比如该数据并没有定义在 state 上,但又想达到这个变量更新时去刷新 render,此时就可以通过调用 forceUpdate() 重新渲染;或者state里的某个变量层次太深,更新的时候没有自动触发render。这时候就可以手动调用 forceUpdate 自动触发 render


在这些勾子函数中,有一些比较重要:(经常使用)

  1. render(): 初始化渲染或更新渲染调用

  2. componentDidMount(): 调用 定时器 或者 发送AJAX请求等操作

  3. componentWillUnmount(): 做一些收尾工作, 如: 清理定时器

  4. componentWillReceiveProps(): 后续需要时再说

演示代码:

class Clock extends React.Component {
constructor(props) {
super(props); this.state = {
date: new Date()}; } componentDidMount() {
this.timerID = setInterval(function(){
this.setState({
date: new Date() }); }.bind(this),1000); } componentWillUnmount() {
clearInterval(this.timerID); } render() {
return (

Hello, world!

现在是 {
this.state.date.toLocaleTimeString()}.

); }}ReactDOM.render(
, document.getElementById('example'));

在这里,每当 Clock 组件第一次加载到 DOM 中的时候,我们都想生成定时器,这在 React 中被称为挂载

同样,每当 Clock 生成的这个 DOM 被移除的时候,我们也会想要清除定时器,这在 React 中被称为卸载

这段代码的执行顺序

当 被传递给 ReactDOM.render() 时,React 调用 Clock 组件的构造函数。 由于 Clock 需要显示当前时间,所以使用包含当前时间的对象来初始化 this.state 。

React 然后调用 Clock 组件的 render() 方法。这时 React 了解了屏幕上应该显示什么内容,然后 React 更新 DOM 以匹配 Clock 的渲染输出。

当 Clock 的输出插入到 DOM 中时,React 调用 componentDidMount() 生命周期钩子。 在其中,Clock 组件要求浏览器设置一个定时器,每秒钟都更新时间。在其中,Clock 组件通过调用 setState() 来调度UI更新。 通过调用 setState() ,React 知道状态已经改变,并再次调用 render() 方法来确定屏幕上应当显示什么。 这一次,render() 方法中的 this.state.date 将不同,所以渲染输出将包含更新的时间,并相应地更新 DOM。

一旦 Clock 组件被从 DOM 中移除,React 会调用 componentWillUnmount() 这个钩子函数,定时器也就会被清除。


在此基础上,我们把所有生命周期勾子函数加入,来验证一下生命周期执行顺序

class Clock extends React.Component {
constructor(props) {
super(props); console.log('constructor(): 创建组件对象'); this.state = {
date: new Date()}; this.removeComponent = this.removeComponent.bind(this); } componentWillMount () {
console.log('componentWillMount(): 初始化将要挂载') } componentDidMount() {
console.log('componentDidMount(): 初始化已经挂载') this.timerID = setInterval(function(){
this.setState({
date: new Date() }); }.bind(this),1000); } componentWillReceiveProps(newProps) {
console.log('componentWillReceiveProps(): 接收到新prop') } shouldComponentUpdate(newProps, newState) {
console.log('shouldComponentUpdate(): 确认已接收新props或state') return true; } componentWillUpdate (nextProps, nextState) {
console.log('componentWillUpdate(): 将要更新') } componentDidUpdate (prevProps, prevState) {
console.log('componentDidUpdate(): 已经更新') } componentWillUnmount() {
console.log('componentWillUnmount(): 将要被移除') clearInterval(this.timerID); } removeComponent () {
ReactDOM.unmountComponentAtNode(document.getElementById('example')) } render() {
console.log('render() 渲染组件') return (

Hello, world!

现在是 {
this.state.date.toLocaleTimeString()}.

); }}ReactDOM.render(
, document.getElementById('example'));

输出结果:

在这里插入图片描述
(这里因为未传递 props,所以componentWillReceiveProps 未执行)

这也就验证了之前图中提到的生命周期流程

①第一次初始化渲染显示: ReactDOM.render()

* constructor(): 创建对象初始化state
* componentWillMount() : 将要插入回调
* render() : 用于插入虚拟DOM回调
* componentDidMount() : 已经插入回调
(以上只执行一次)

②每次更新state: this.setState()

* componentWillUpdate() : 将要更新回调
* render() : 更新(重新渲染)
* componentDidUpdate() : 已经更新回调
(以上执行n次)

③移除组件: ReactDOM.unmountComponentAtNode(containerDom)

* componentWillUnmount() : 组件将要被移除回调
(以上只执行一次)


组件API

在React 组件中其实还有很多用法:

设置状态:setState

替换状态:replaceState

设置属性:setProps

替换属性:replaceProps

强制更新:forceUpdate

获取DOM节点:findDOMNode

判断组件挂载状态:isMounted

因为这部分有些内容不是很常用,所以就不在这里赘述了。具体使用方法看该文章: 即可。


表单与事件

HTML 表单元素与 React 中的其他 DOM 元素有所不同,因为表单元素本身就能够保留一些内部状态。比如 <input> <textarea> <select> 这类表单元素会维持自身状态,并根据用户输入进行更新。但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新。举例如下:

class HelloMessage extends React.Component {
constructor(props) {
super(props); this.state = {
value: 'hello!'}; this.handleChange = this.handleChange.bind(this); } handleChange(event) {
this.setState({
value: event.target.value}); } render() {
var value = this.state.value; return

{
value}

; }}ReactDOM.render(
, document.getElementById('example'));

在 React 中,不使用 selected 属性,而在根 select 标签上用 value 属性来表示选中项:

class FlavorForm extends React.Component {
constructor(props) {
super(props); this.state = {
value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) {
this.setState({
value: event.target.value}); } handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() {
return (
); }} ReactDOM.render(
, document.getElementById('example'));

当你有处理多个 input 元素时,你可以通过给每个元素添加一个 name 属性,来让处理函数根据 event.target.name 的值来选择做什么:

class Reservation extends React.Component {
constructor(props) {
super(props); this.state = {
isGoing: true, numberOfGuests: 2 }; this.handleInputChange = this.handleInputChange.bind(this); } handleInputChange(event) {
const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({
[name]: value }); } render() {
return (
); }}

转载地址:http://qmyki.baihongyu.com/

你可能感兴趣的文章
SQL - SQL Server中如何获取当前年,月,日,时,分,秒
查看>>
SQL - SQL Server 性能优化之SQL语句总结
查看>>
Docker - docker-compose常用命令
查看>>
SQL - SQL Server判断字符串中是否有中文
查看>>
SQL - SQL Server查询近7天的连续日期
查看>>
SQL - SQL Server中如何取年、月、日 -DATEPART函数
查看>>
SQL - SQL Server 一列或多列重复数据的查询,删除
查看>>
NET - .NET Core WebAPI + Vue + Axios 导出Excel / CSV
查看>>
NET - NET Core Quartz.net开源作业调度框架使用详解
查看>>
NET - NET Core quartz.net 时间表达式----- Cron表达式详解
查看>>
NET - .NET Core 之 Abp Audit-Logging
查看>>
NET - .NET Core 之 Abp AuditLog 将不同的Controller实体的审计日志存储到不同的Table
查看>>
NET - .NET Core 之 Azure Key Vault 密钥保管库的使用
查看>>
NET - .NET Core 之 Abp 整合 Quartz
查看>>
Docker - Docker Desktop(WSL2)修改镜像存储位置
查看>>
NET - NET Core使用Log4net的SqlServer AdoNetAppender 报程序集错误
查看>>
NET - NET Core中使用Log4net输出日志到数据库中去
查看>>
NET - NET Core 迁移nuget包缓存到指定位置
查看>>
Spring - SpringBoot 集成 swagger2
查看>>
SQL - 深入理解MySQL索引之B+Tree
查看>>