最近迷上了React。在工作以来逐渐对ES6语法熟悉,再上手React是真的被这个框架“迷”住了。公司大部分的项目都是基于vue和uniapp。虽然说vue的开发模式逻辑很清晰。解耦了模板样式和js。但奈何vue需要牢记的规则太多了。对代码的复用只能依靠抽离组件或使用mixin。而React的写法让我有种重回js怀抱的感觉。
本文对React入门常用知识点进行盘点,其他相关知识点文章链接:
环境
使用React我们需要导入的是以下三项东西:
- react:react的核心代码
- react-dom:将react渲染到Dom上的核心代码
- babel:用于解析ES6语法和JSX语法
常用的开发模式
//创建React组件
class App extends React.Component {
constructor() {
super(props)
this.state = {}
}
render() {
return (<div>Hello React</div>)
}
}
//渲染函数
ReactDOM.render(<App />,element)
JSX语法
即JavaScript XML,能让我们在js中写标记语言。(注JSX的解析依赖babel)。以下是JSX使用的时候需要注意的点
//JSX的注释
{/* 在这里面写但行或多行注释 */}
//解析后能够显示的类型和不能显示的类型
//1.可以显示的类型
String
Number
Array
//2.不能够显示的类型
Boolean
Null
undefined
//3.对象类型不能作为子元素
//JSX可以使用的嵌入表达式
1.运算符表达式
2.三元运算符
3.执行一个函数
//对于单标签结尾的标签,必须使用/结尾,即<img />
除了上述一些JSX使用的小细节,下面还有我们使用JSX写标签属性的方式
//JSX绑定普通属性
<h2 title={title}>我是标题</title>
//JSX绑定class属性
<div className={"box title" + (active ? "active" : "")}>我是div元素</div>
//JSX绑定style样式
<div style="{{color:"red",fontSize:"18px"}}">我是div</div>
render函数中JSX绑定事件
绑定事件的格式是:onClick = { 事件名称 }
各种修改this的方式和优劣
//在render函数中绑定事件,事件调用的函数中this默认是undefined。需要使用一些方式修改this的指向才能正常调用函数
//1.bind的方式修改this指向
class App extends React.Component {
constructor() {
//..
this.btnClick = this.btnClick.bind(this)
}
render() {
return <div onClick={this.btnClick}>doSome</div>
}
btnClick() { //.. }
}
//2.调用的函数使用箭头函数的方式声明
class App extends React.Components {
//..
render () {
return <div onClick={this.btnClick}>doSome</div>
}
btnClick = () => { //.. }
}
//3.事件绑定的JSX表达式中使用箭头函数,箭头函数中再调用对应的方法
class App extends React.Components {
//..
render () {
return <div onClick={ (event) => { this.btnClick(event,param1,param2) }}>doSome</div>
}
btnClick(event,param1,param2) { //.. }
}
推荐使用第三种方案
React条件渲染
常见的条件渲染的方式:
- 条件判断语句 适合逻辑代码非常多的时候
//..
render() {
let welcome = null;
if(true) {
welcome = <h2>欢迎回来</h2>
}else {
welcome = <h2>您好,请先登录</h2>
}
return (
<div>
{ welcome }
</div>
)
}
···
- 三目运算符
let { isLogin } = this.state
<h2>{ isLogin ? "登录成功" : null }</h2>
- 逻辑与表达式
let { isLogin } = this.state
<h2>{ isLogin && "登录成功"}</h2>
React列表渲染
JSX对于列表渲染会直接渲染数组中的值。看一下例子
//...
const listArray = ['列表1','列表2','列表3'];
render() {
return (
<div>{ listArray.map( (item,index) => {
return <li key={ index }>{ item }</li>
} ) }</div>
)
}
当然也可以搭配数组其他的高阶api进行使用,例如Array.filter(),Array.every(),Array.some(),Array.slice()等等...
render函数可以返回的内容
我们熟悉的render函数除了可以返回JSX语法外。还可以返回如下内容
- 数组或fragments
- Portals
- 字符串或数值类型
- 布尔值或null
React类组件的生命周期
生命周期用于描述一个事物从创建到销毁。 React中的组件生命周期其实指的是组件从创建到销毁的各个过程提供了不同的函数,当组件在进入到某个特定的时期会调用对应的生命周期函数。
React类组件常用的生命周期:
- 挂载完成阶段:
componentDidMount - 更新完成阶段:
componentDidUpdate - 即将卸载阶段:
componentWillUnmount牢记一副图
React中setState是异步还是同步?
在React中,我们使用setState进行更新组件的状态,再达到重新渲染的目的,由于页面可能会频繁更新状态。为了提高性能,在React中setState大多情况下都是异步的。而第二个参数的回调函数中或生命周期componentDidUpdate中可以获取得到异步修改值后的state的值。
虽然大多情况下setState是异步的,但在有些时候setState是同步的,例如:
在组件声明周期或React合成事件中,setState是异步的;
在setTimeout或者在原生dom事件中,setState是同步的;
setState数据的合并
setState做的处理实际上是通过Object.assign()函数,将新的对象和旧的state进行合并操作。
在函数中进行多次setState操作,实际上只是操作一次。因为在React内部会对多次setState进行处理。用assign合并成一次操作,那么,当我们确实需要多次setState都能生效。我们应该这样写:
//setState第一个参数除了接受一个对象之外或者可以接受一个函数
//prevState为上次修改setState的值
this.setState((prevState,props)=>{
return {
counter:prevState.counter + 1
}
})
为什么setState要传一个不可变的数据?
因为在shouldComponentUpdate中会经常用更新前的state和更新后的state做对比,对于对象来说,比较的是内存中的地址指。如果修改的state是在原来的对象上进行操作,那么在比较的时候,即使修改了对象。他们进行对比返回的还是true。