- 获取变量,插值
{this.state.name}
- 表达式
- {this.state.flag? 'yes':'no'}
- class关键字冲突,应该使用className
- style={{font-size:50px;}}
- 原生html
- const rawHtml='666';
- const rawData={
- _html:rawHtml//注意必须是这种格式
- };
- <p dangerouslySetInnerHtml={rawData}>p>
-
- JSX的条件渲染
- render(){
- const blackBtn=<Button className="black-btn">black BtnButton>
- const whiteBtn=<Button className="white-btn">white BtnButton>
- //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>
- }
- constroctur(){
- this.handleClick=this.handleClick.bind(this);
- }
-
- render(){
- return(
- <Button onClick={handleClick}>Button>
- )
- }
-
- handleClick(){
- xxxxxxxx
- }
- this.state.count++;//错误
-
- this.setState({
- count:this.state.count+1
- });
- 注意,在进行this.setState的操作时,不能直接对this.state.list进行push,pop,splice等,这样违反不可变值
- //挂载时
- componentDidMount
- //更新时
- componentDidUpdate
- //卸载时
- componentWillUnMount
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组件
非受控组件:初始值可以使用state当中的值,但组件本身的值不和state中的值关联和绑定
组件会按照既定层次嵌套渲染,如何让组件渲染到父组件以外?这时候就要用到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节点
- )
- }
当向子组件传递语言,主题等公共信息时,使用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>
- }
如何使用异步组件
- const Demo=React.lazy(()=>import(./demo));
-
- class App extends Compontent{
-
- render(){
- <p>这是一个异步组件p>
- <React.Suspense fallback={<div>Loding...div>}>
- <Demo/>
- React.Suspense>
- }
-
- }
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
高阶组件(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);
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}/>
- }
1.dispatch(action)
2.reducer返回NewState
3.subscribe触发通知
使用中间件
redux-thunk
redux-saga
redux-promise
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>
- )
- }
- 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>
- };