1.JSX的基本使用
获取变量,插值
<p>{this.state.name}</p>
表达式
{this.state.flag? 'yes':'no'}
class关键字冲突,应该使用className
style={{font-size:50px;}}
原生html
const rawHtml='<span>666</span>';
const rawData={
_html:rawHtml//注意必须是这种格式
};
<p dangerouslySetInnerHtml={rawData}></p>
JSX的条件渲染
render(){
const blackBtn=<Button className="black-btn">black Btn</Button>
const whiteBtn=<Button className="white-btn">white Btn</Button>
//if else 语句
if(this.state.color='white'){
return blackBtn
}
else { return whiteBtn}
//条件渲染
return <div>
{ this.state.color==='white'? whiteBtn:blackBtn}
</div>
//&&
return <div>
{ this.state.color==='white'&&whiteBtn}
</div>
JSX的列表循环
render(){
return <ul>
{this.state.list.map((item,index)=>{
return <li key={index.id}> index{index};title{item.title}</li>
})}
</ul>
}
2.React事件绑定this
constroctur(){
this.handleClick=this.handleClick.bind(this);
}
render(){
return(
<Button onClick={handleClick}></Button>
)
}
handleClick(){
xxxxxxxx
}
3.this.setState使用不可变值
this.state.count++;//错误
this.setState({
count:this.state.count+1
});
注意,在进行this.setState的操作时,不能直接对this.state.list进行push,pop,splice等,这样违反不可变值
4.React生命周期
//挂载时
componentDidMount
//更新时
componentDidUpdate
//卸载时
componentWillUnMount
5.React高级特性
1.函数组件
1.输入props,输出jsx
2.没有实例,没有生命周期,没有state
3.不能拓展其他方法
当class组件只接收props,没有state,这时候就可以将函数组件简写为class组件
//class组件
class abc extends Component{
constructor(props){
super(props)
}
render(){
const {list}=this.props;
return <ul>{list.map((item,index)=>{
return <li key={item.index}>
<span>{item.title}</span></li>})}
</ul>
}
}
//由于该class组件只有props属性,没有state,所以可以将它简写为函数组件
function abc(props){
const {list}=this.props;
return <ul>{
list.map((item,index)=>{
return <li key={item.index}>
<span>{item.title}</span>
</li>
})
}</ul>
}
两种组件的选择:如果仅仅是输入props输出JSX,最好使用函数组件,而如果在组件中要用到生命周期函数,要用到state等,则应该使用class组件
2.受控组件和非受控组件
非受控组件:初始值可以使用state当中的值,但组件本身的值不和state中的值关联和绑定
3.React Protals
组件会按照既定层次嵌套渲染,如何让组件渲染到父组件以外?这时候就要用到Protals
render(){
//正常情况下
return <div className="demo">{this.props.children}</div>
//可以使用Protals渲染到body上,fixed元素要放在body上,有更好的浏览器兼容性
return ReactDOM.createProtal(
<div className="demo">{this.props.children}</div>,docunment.body//DOM节点
)
}
4.Context
当向子组件传递语言,主题等公共信息时,使用props太繁琐,使用redux小题大做,此时就可以使用Context
1.创建Context
const ThemeContext=React.createContext('light');
2.生产Context
render(){
return <ThemeContext.Provider value={this.state.theme}>
<button></button>
<list></list>
</ThemeContext.Provider>
}
3.使用context
如果是class组件的话,
button.contextType=ThemeContext;
并且在button组件的内部
render(){
const theme=this.context;//使用this.context来获取theme值
}
如果是函数组件的话,
function list(props){
<ThemeContext.Consumer>
{value=><p>the theme is {value}</p>}
</ThemeContext.Consumer>
}
5.异步组件
如何使用异步组件
const Demo=React.lazy(()=>import(./demo));
class App extends Compontent{
render(){
<p>这是一个异步组件</p>
<React.Suspense fallback={<div>Loding...</div>}>
<Demo/>
</React.Suspense>
}
}
6.性能优化
shouldComponentUpdate
//SCU的基本用法
shouldComponentUpdate(nextProps,nextState){
if(nextState.count!===this.state.count){
return true//进行渲染
}
return false//不重复渲染
}
//React 默认父组件有更新,则子组件会无条件更新
通过使用SCU判断子组件是否有更新,如果有更新才进行重新渲染,这样就避免了重复渲染
PureComponent
在SCU当中实现了浅比较,如果第一层属性相同,则SCU返回false,不进行重复渲染,如果第一层属性不同,SCU才返回true,并且进行渲染
class demo extends React.pureComponent{
//相当于增加了SCU(){浅比较}
}
memo
class demo extends React.Component{
}
function preNext(preProps,nextProps){
//比较函数
}
export default React.memo(demo,preNext);
immutable.js
const map1=immutable.Map({a:1,b:2,c:3});
const map2=map1.set('b',50);
map1.get('b');//2
map2.get('b');//50
7.关于组件公共逻辑的抽离
高阶组件(HOC)
//高阶组件不是一种功能,而是一种模式
const HOCFactory=(Component)=>{
class HOC extends React.Component{
constroctur(props){
super(props);}
//在此定义多个组件的公共逻辑
}
render(){
return <Component {...this.props}/>//返回拼装的结果
}
return HOC
};
const EnhancedComponent1=HOCFactory(WarpedComponent1);
const EnhancedComponent2=HOCFactory(WarpedComponent2);
8.Render Props
Render Props的核心思想
通过一个函数将class组件的state作为props传递给纯函数组件
class Factory extends Component{
constroctur(){
this.state={
/*state 即多个组件的公共逻辑的数据*/}
a:555,
b:666
}
render(){
<div>{this.props.render(this.state)}</div>}
}
const App=()=>{
<Factory render={
(props)=><p>{props.a},{props.b}/>
}
9.Redux单向数据流
1.dispatch(action)
2.reducer返回NewState
3.subscribe触发通知
10.异步action
使用中间件
redux-thunk
redux-saga
redux-promise
11.React-Router路由模式
1.哈希模式 如http://abc/#/user/20
2.H5 history模式 如http://abc/user/10
后者需要server端支持,因此无特殊要求选择前者
import React from 'react'
import {
/哈希路由/
HashRouter as Router,
Switch,
Route
} from 'react-router-dom'
import {
/h5 history路由/
BrowserRouter as Router,
Sitch,
Route
} from 'react-router-dom'
function routerComponent(){
return(
<Router>
<Switch>
<Route path="/">
<Home/>
</Route>
<Route path="/project/:id">
<Project/>
</Route>
<Route path="*">
<Not Found/>
</Route>
</Switch>
</Router>
)
}
路由跳转
1.使用Link标签实现路由跳转
import React from 'react'
import {Link,useParams} from 'react-router-dom'
function Project(){
const {id}=useParams();
return(
<div link="/">首页</div>)
}
2.使用js实现路由跳转
import React from 'react'
import { useHistory } from 'react-router-dom'
function Trash(){
let history=useHistory();
function handleClick(){
history.push('/');
}
return (
<div>
<Button type="primary" onClick={handleClick}>回到首页<Button/>
</div>
)
}
12.React-Router路由配置(懒加载)
import {BrowserRouter as Router ,Switch,Route} from 'react-dom-router'
import React ,{Suspense,lazy} from 'react'
const Home=lazy(()=>import('./routes/Home'));
const About=lazy(()=>import('./routes/About'));
const App=()=>{
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Suspense>
</Router>
};