该篇是阅读React官方文档学习React的笔记内容
React是什么
React是用于构建用户界面的JavaScript库。由FaceBook开发的,能简单,快速,高效地开发复杂和交互式的Web和移动UI。优点体现在开发效率、维护、组合扩展、生态、组件化思想等。现在,React有一个很大的支持社区。
React的特点:
- 声明式。配合使用JSX,以声明式编写UI, 使得代码编写容易,容易理解和维护。
- 组件化。通过React组件来构建各种UI,组件拥有状态,当状态数据改变时,React能有效地更新并正确地渲染组件。
- 跨平台。一次学习,随处编写。可以在Web开发中使用,也可以使用 Node 进行服务器渲染,还可以使用基于React的 React Native 开发原生移动应用。
Hello React
因为React本身是一个JavaScript库,所以只要在HTML文件中通过script 标签引入相关的一些js文件,就可以直接用React来编写UI了。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, React!</h1>,
document.getElementById('root')
);
</script>
</body>
</html>
复制代码
JSX
JSX(JavaScript XML)是 JavaScript 定义的一套用于描述UI的扩展语法。使用JSX来编写UI,使得代码的可读性更好。在React开发中,经常会使用JSX来写组件。
JSX语法
JSX语法有如下一些规则:
- 自定义组件使用是必须首字母大写,首字母不大写会直接解析为同名html标签
- 属性名称用camelCase来定义
- 对于字符串值,用引号
- 对于表达式,用大括号,可以在大括号内放置任何有效的 JavaScript 表达式。
- 一个标签里面没有内容,可以使用 /> 来闭合标签
- JSX中编写注释用大括号将/* */语句包起来
<div>
<div className="shopInfo"></div>;
<div tabIndex="0"></div>;
<img src={user.avatarUrl}></img>;
{/* 注释写在这里 */}
Hello, {name}!
{/* 多行注释
也同样有效。 */}
</div>
复制代码
JSX和HTML的区别有
- key、ref 和 dangerouslySetInnerHTML属性只在JSX中存在
- 使用到HTML的标记元素的class属性名称在JSX中是className
- JSX中事件要使用小驼峰式写法
- style中的css属性要使用小驼峰式写法
React元素
React元素就是JSX表达式的值,通过React元素来渲染屏幕上的内容。ReactDOM 会负责更新 DOM 来与 React 元素保持一致。 将一个React元素渲染到HTML的节点(假设id = 'root')上的方法是把它们传入ReactDOM.render()方法中
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
复制代码
ReactDOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态,从而提高性能。
React组件
React组件使用一个名为 render() 的方法,接收输入的数据并返回需要展示的内容,展示的内容是由React元素构成的。 最简单的React组件
- 创建一个继承于React.Component的class
- 创建render方法并实现
class Welcome extends React.Component {
render() {
return <div>Hello</div>;
}
}
复制代码
自定义组件名称必须以大写字母开头。
在React应用中,UI是由一系列React组件构建起来的。这些组件将整个UI分成小的、独立的甚至是可重用的部分。一个组件的变动不会影响到另一个组件。
组件数据管理
React元素会将 JSX 所接收的属性(attributes)转换为单个对象传递给组件,这个对象被称之为 “props”。
组件有两个很重要的属性props 和 state。
组件使用外部数据 this.props
组件维护内部数据 this.state 和 this.setState()
组件的props属性是只读的,它们总是在整个应用中从父组件传递到子组件。子组件永远不能将 prop 送回父组件。这有助于维护单向数据流。即组件不能修改自身的props。
组件的state属性是私有的,并且完全受控于当前组件。随用户操作、网络响应或者其他变化而需要动态更新UI的可以通过更新其state来实现。
- 修改this.state需要通过this.setState()方法,不要直接修改this.state
- state的更新可能是异步的
- state的更新会被合并
当组件的状态发生变化时,组件会再次调用render()方法重新渲染。
React组件生命周期
分三个阶段:挂载阶段、更新阶段和卸载阶段,始终使用props 参数来调用父类的构造函数
挂载阶段:组件即将开始被添加到DOM阶段。
更新阶段:一旦组件被添加到DOM,它只有在 props 或state发生变化时才可能更新和重新渲染。
卸载阶段:组件被销毁并从 DOM 中删除。这是组件生命周期的最后阶段。
一些重要的生命周期方法:
- componentWillMount() – 在渲染之前执行,在客户端和服务器端都会执行。
- componentDidMount() – 仅在第一次渲染后在客户端执行。
- componentWillReceiveProps() – 当从父类接收到 props 并且在调用另一个渲染器之前调用。
- shouldComponentUpdate() – 根据特定条件返回 true 或 false。如果你希望更新组件,请返回true 否则返回 false。默认情况下,它返回 false。
- componentWillUpdate() – 在 DOM 中进行渲染之前调用。
- componentDidUpdate() – 在渲染发生后立即调用。
- componentWillUnmount() – 从 DOM 卸载组件后调用。用于清理内存空间。
React组件事件处理
React元素同html标签元素一样,可以响应事件,其语法要求是
- React事件的命名采用小驼峰
- 传入一个函数作为事件处理函数
- 需要显示调用preventDefault方法来阻止默认行为
- 在 JavaScript 中,类的方法默认不会绑定 this, 所以如果直接在React元素的响应事件方法中访问this,得到的值是undefined,因此,需要通过bind绑定。 在构造函数中绑定
class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>;
}
}
复制代码
直接在render函数中绑定
class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
}
}
复制代码
如果不想绑定bind,可以用箭头函数。
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
复制代码
在 render 方法中使用 Function.prototype.bind 和 箭头函数 都会在每次组件渲染时创建一个新的函数, 这会影响性能。
5. 事件处理函数传递参数
<button onClick={() => this.handleClick(id)} />
// 等价
<button onClick={this.handleClick.bind(this, id)} />
复制代码
向事件处理函数传递参数时,如果事件处理函数是箭头函数,事件对象必须显式的进行传递,如果是bind方式,事件对象可以被隐式传递。
组件更多语法
基本上就是将js的语法和JSX组合起来灵活的构建组件,比如条件语句、循环语句等。组件的className也可以是变量,根据不同的值来展示对应的样式。
class Demo extends React.Component {
const numbers = [1, 2, 3, 4, 5];
const isShow = props.isShow
render() {
return <h1>Hello</h1>;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
const showItem = isShow ? <div> showItem </div> : null
return (
<ul>{listItems}</ul>
{showItem}
);
}
}
复制代码
因为JSX允许在大括号中嵌入任何表达式,所以上面render方法中的变量对应的表达式可以直接放到return中,替换掉变量
以下内容研究不深,等以后在实际开发中涉及到相关知识点的时候再回来研究🤦♀️
React调试插件
React Developer Tools 插件: chrome.google.com/webstore/de…
代码分割
为了按需加载代码,提高性能,React支持和提供了一些组件
- 动态 import() 语法
- React.lazy,React.lazy 目前只支持默认导出(default exports)
- Suspense组件
- 异常捕获组件
- 路由分割
Context
Context提供了一种在组件之间共享数据的方式,而不需要显式地通过props属性由父及子的传递数据。
渲染错误捕获
React支持自定义错误边界组件来捕获渲染出错的子组件。
如果一个React组件中定义了 static getDerivedStateFromError() 或 componentDidCatch() 这两个生命周期方法中的任意一个(或两个)时,那么它就变成一个错误边界。当抛出错误后,可在getDerivedStateFromError() 方中更改状态变量来控制渲染备用UI ,在componentDidCatch() 方法中打印错误信息
React.forwardRef
Refs 是React 元素的一个属性,用于对 render() 返回的特定元素或组件的引用。即给JSX元素 ref 属性,然后就可以通过ref属性值来获取该节点的引用。常用场景有
- 需要管理焦点、选择文本或媒体播放时
- 触发式动画
- 与第三方 DOM 库集成
React.Fragment
React.Fragment 可以聚合一个子元素列表,但是不会在DOM中增加额外节点。
在 React 中, <></> 是 <React.Fragment/> 的语法糖。
React.Fragment 有属性值key
高阶组件
高阶组件是参数为组件,返回值为新组件的函数,也就是通过一个函数将一个组件转换为另一个组件。
高阶组件是基于React的组合特性而形成的设计模式。主要是为了复用组件的逻辑。
不要在render方法中使用高阶组件,因为每次都会生成新的组件,导致子树每次渲染都会卸载、和重新挂载,并且无法保留之前组件及其子组件的状态。
HOC可用于许多任务,例如:
代码重用,逻辑和引导抽象
渲染劫持
状态抽象和控制
Props 控制
更多文章
React官网:
reactjs.org/
zh-hans.reactjs.org/
React概览
www.taniarascia.com/getting-sta…
深入解析为什么 key 是必须的
zh-hans.reactjs.org/docs/reconc…
Robin Pokorny 的深度解析使用索引作为 key 的负面影响 medium.com/@robinpokor…