一、JSX
在学习react之前,我们必须先了解什么是JSX,实质就是JavaScript +XML 的一个扩展语法,有以下的特点:
-
可以作为值使用
-
不是字符串
-
不是HTML
-
可以配合JavaScript 表达式一起使用
-
对大小写敏感,标签名用小写,组件用大写
-
所有标签都必须闭合
const div = <div className="main">
<header>
<h1>欢迎进入 React 的世界</h1>
<p>没有 JSX 的 <br />React 世界是黑暗的</p>
</header>
</div>;
为了有效的防止 XSS 注入攻击,React DOM 会在渲染的时候把内容(字符串)进行转义,所以字符串形式的标签是不会作为 HTML 标签进行处理的
二、Render
使用 React 构建视图,构建的是一个虚拟DOM(纯对象),JSX就是虚拟DOM的语法糖
在我们平时日常写的JSX中,会通过React.createElement进行一个代码转义
其用法如下:
React.createElement(type,props,children1,....childrenN)
-
返回值:构建好的虚拟DOM
-
type类型(标签名|组件名) -
props null|{}元素对应的属性 -
children子节点(包括文本节点)
最终虚拟DOM还是需要渲染真实DOM的,这时候我们就需要了解下RenctDom.render
其用法如下:
ReactDOM.render(VDOM,container,[callback]):将构建好的虚拟DOM,渲染成真实DOM
-
VDOM要构建的视图 -
container挂载节点(容器,将构建好的视图放在哪个真实元素中) -
callback可选参数, 真实DOM渲染完的回调函数
function App() {
return (
<div className="App">
stydy react
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
三、插值表达式
在React中,插值表达式通过一对大括号{}使用,可以接受一个javascript表达式
表达式有什么?
-
各种运算符
-
函数调用
-
变量或常量
而在插值表达式中,表达式的计算结果必须为 ReactElement
那什么是ReactElement?
-
React 构建的虚拟DOM
-
string | number 会 原样输出
-
boolean | null | undefined 会被忽略为空
-
数组:去掉连接符后进行输出,有几位就输出几个子节点
-
注释
{/*内容*/} -
函数会被忽略
四、类组件
组件类必须继承 React.Component,同时必须有render方法
可以设置state属性存放组件的状态(类似vue中data属性),当组件状态有修改时,会对组件进行更新,从而完成组件的视图更新
修改组件的状态是通过组件的setState方法完成
基本用法如下:
this,setState(updater, [callback])
updater是用于更新数据,可以是Function或者Object
callback为更新成功后的回调函数
react 通常会集齐一批需要更新的组件,然后一次性更新来保证渲染的性能,因此setState方法是一个异步的方法
state = {
x : 0
}
this.setState(x+1)
this.setState(x+2)
this.setState(x+3)
this.state.x // 3
如果想要使用更新后的state进行操作,我们可以在setState回调函数中编写
state = {
x : 0
}
this.setState(x+1,() => {
console.log(this.state.x) // 1
})
console.log(this.state.x) // 0
setState采取的是浅合并的策略
state = {
x : 0,
y : 1
}
this.setState({
x : 1
})
// 不会覆盖state中y的值
上述例子有点类似Object.assign
this.state = Object.assign(this.state,{x:1})
注意:直接通过this.state.xxx='xxx'这种形式修改数据,并不会使页面视图完成更新
关于事件绑定,我们尤其需要关注this的指向问题
<button onClick={this.handlerClick}>递增</button>
建议使用箭头函数的方式进行事件的声明
handlerClick = ()=>{
// ...
}
也可以在constructor中对事件进行绑定(不推荐)
constructor{
this.handlerClick = this.handlerClick.bind(this)
}
完整示例代码
import {Component} from "react";
class App extends Component {
state = { // 类似于 Vue 中的 data 属性
count: 1
}
handlerClick = ()=>{
const {count} = this.state;
this.setState({
count: count + 1
});
}
render(){
const {count} = this.state;
return <div>
<p>{count}</p>
<button onClick={this.handlerClick}>递增</button>
</div>
}
}
五、列表渲染
通过数组的map方法,需要为每个成员设置key值,用于diff算法更高效比较
const data = {
a:{
title: "列表-1"
},
b:{
title: "列表-2"
},
c:{
title: "列表-3"
}
}
const dataArr = Object.keys(data).map((item,index)=><li key= {index}>{data[item].title}</li>);
const list = <ul>{dataArr}</ul>;
六、条件输出
在插槽表达式中使用if关键字
const fn=(nub)=>{
if(nub < 5){
return "小于5";
}
if(nub < 10){
return "小于10";
}
if(nub < 20){
return "小于20";
}
return "大于等于20"
}
const div = <div>
<div>左侧不成立||返回右侧 - {2<0||"不成立"}</div>
<div>左侧成立&&返回右侧 - {2>0&&"成立"}</div>
<div>条件?成立:不成立 - {2<0?"成立":"不成立"}</div>
<div>{fn(20)}</div>
</div>;