# React 入门

# 什么是虚拟DOM

JS对象的形式,来表示 DOM 和 DOM 之间的嵌套关系

# 项目构建

  • package.json 文件基本依赖

    {
      "dependencies": {
        "react": "^16.12.0",
        "react-dom": "^16.12.0"
      },
      "devDependencies": {
        "@babel/core": "^7.8.4",
        "@babel/plugin-proposal-class-properties": "^7.8.3",
        "@babel/plugin-transform-runtime": "^7.8.3",
        "@babel/preset-env": "^7.8.4",
        "@babel/preset-react": "^7.8.3",
        "@babel/runtime": "^7.8.4",
        "babel-loader": "^8.0.6",
        "webpack": "^4.41.6",
        "webpack-cli": "^3.3.11",
        "webpack-dev-server": "^3.10.3"
      }
    }  
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
  • babel.config.js 配置

    module.exports = {
      presets: ["@babel/preset-env", "@babel/preset-react"],
      plugins: [
        "@babel/plugin-transform-runtime",
        "@babel/plugin-proposal-class-properties"
      ]
    };
    
    1
    2
    3
    4
    5
    6
    7
  • webpack.config.js 基础

    const path = require('path')
    
    module.exports = {
      mode: "none",
      entry: "./src/index.js",
      output: {
        path: path.join(__dirname, "./dist"),
        filename: "bundle.js"
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            use: "babel-loader",
            exclude: /node_modules/
          }
        ]
      },
      devServer: {
        contentBase: "./dist",
        hot: true,
        open: true
      }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

# Hello World

import React from 'react'
import ReactDOM from "react-dom";

class App extends React.Component {
  constructor() {
    super(...arguments)
  }
  render() {
    return (
      <div>Hello World</div>
    );
  }
}

ReactDOM.render(<App/>, document.getElementById('root'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 组件

  • 组件可以是一个函数

    import React from "react" // 必须引入react
    
    const List = (props) => {
      return (
        <h2>这是标题</h2>
      )
    }
    
    export default List;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 可以是继承 React.Component 的类

    import React, { Component } from 'react'
    
    class ListC extends Component {
      render() {
        return (
          <h2>这是conponent标题</h2>
        )
      }
    }
    
    export default ListC
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

# State

组件内的数据定义在 state 上,如果需要改变 state 数据时,需要通过 setState 函数来改变

// setState 函数参数
void setState (
    function|object nextState,
    [function callback]
)
1
2
3
4
5

setState 函数是个异步函数,修改后的 state 可以在它的回调函数中访问。

// ListC.js
constructor() {
  super(...arguments)
  this.state = {
    h1: "这是conponent标题"
  };
}

handleClick() {
  this.setState({
    h1: '修改的state'
  }, () => {
    console.log(this.state.h1) // 修改的state
  })
  console.log(this.state.h1) // 这是conponent标题
}
// 或者
handleClick() {
  this.setState(
    (prevState, props) => { // 修改前回调
      console.log(prevState, props); // 可以访问修改前state和props
      return {
        h1: "修改的state"
      }
    },
    () => {
      console.log(this.state.h1);
    }
  );
  console.log(this.state.h1)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# Props

父组件与子组件通信

  • 通过在 props传入消息给子组件

    // List.js
    const List = (props) => {
      return (
        <h2>{ props.name }</h2>
      )
    }
    // index.js
    render() {
      return (
        <div>
          <List name="这是函数组件" />
        </div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  • 通过子组件 props 挂载函数通信

    // ListC.js
    handleClick() {
      console.log(this)
      this.props.myClick('这是子组件的消息') // 挂载在子组件上的事件
    }
    // index.js
    myClick(val) { // 可以通过子组件上函数访问子组件中的内容
      console.log(`父组件:` + val);
    }
    
    render() {
      return (
        <div>
          <ListC myClick={this.myClick.bind(this)} />
        </div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

# 生命周期

# componentWillMount

  • 组件即将被渲染到页面之前
  • 这个时期可以开启定时器,发送请求等操作

# componentDidMount

  • 组件已被渲染,此时可以访问 DOM 元素,进行相关的 DOM 操作

# componentWillUpdate

  • 组件被更新前触发

# componentDidUpdate

  • 组件被更新完后触发
  • 页面产生新的 DOM 元素

# componentWillUnmount

  • 组件被销毁时触发
// ListC.js
import React, { Component } from 'react'
import Item from './Item'

class ListC extends Component {
  constructor() {
    super(...arguments);
  }
  
  // 生命周期
  componentWillMount() {
    console.log(`willMount`);
  }

  componentDidMount() {
    console.log(`didMount`);
  }

  componentWillUpdate() {
    console.log(`willUpdate`);
  }

  componentDidUpdate() {
    console.log(`didUpdate`);
  }

  componentWillUnmount() {
    console.log(`unmount`);
  }

  handleClick() {
    this.setState(
      (prevState, props) => {
        console.log(prevState, props);
        return {
          h1: "修改的state"
        };
      },
      () => {
        console.log(this.state.h1);
      }
    );
    console.log(this.state.h1);
  }

  render() {
    return (
      <div>
        <h2 onClick={this.handleClick.bind(this)}>{this.state.h1}</h2>
        <Item/>
      </div>
    );
  }
}

// Item.js
import React, { Component } from "react";

class Item extends Component {
  constructor() {
    super(...arguments);
  }

  // 生命周期
  componentWillMount() {
    console.log(`这是item willMount`);
  }


  componentDidMount() {
    console.log(`这是item didMount`);
  }

  componentWillUpdate() {
    console.log(`这是item willUpdate`);
  }

  componentDidUpdate() {
    console.log(`这是item didUpdate`);
  }

  componentWillUnmount() {
    console.log(`unmount`);
  }

  render() {
    return <h3>这是item</h3>;
  }
}

export default Item;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

初始化组件依次打印

// willMount
// 这是item willMount
// 这是item didMount
// didMount
1
2
3
4

组件更新时打印

// willUpdate
// 这是item willUpdate
// 这是item didUpdate
// didUpdate
1
2
3
4

先触发父组件 wiiMount先渲染完子组件,才渲染父组件

# 事件处理

  • 直接在DOM元素上写小驼峰事件名称
  • 注意使用bind来改变 this 的指定
// ListC.js
handleClick() {
  console.log(`事件处理`);
}

render() {
  return (
    <div>
      <h2 onClick={this.handleClick.bind(this)}>{this.state.h1}</h2>
      <Item/>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13

怎么向事件传值

<h2 onClick={this.handleClick.bind(this, '传值')}>{this.state.h1}</h2>
<h2 onClick={e => this.handleClick("呵呵")}></h2>
1
2

# 渲染

# 条件渲染

可以像 JavaScript 一样来做条件渲染或者三目运算

const ItemShow = (props) => {
  if (props.isShow) {
    return <p>这是条件渲染</p>
  }
  return null
}
1
2
3
4
5
6

# 列表渲染

使用map函数渲染

render() {
  return (
    <h3>
      这是Item{" "}
      {
        [1, 2, 3].map(item => {
          return <ItemShow key={item} isShow={true} value={item} />;
        })
      }
    </h3>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12

# 类 slot

const List = (props) => {
  return (
    <h2>{ props.children }</h2> // 通过 props.children 来做占位符
  )
}
1
2
3
4
5

# Refs 操作 DOM

通过 React.createRef 来创建 ref

class Test extends React.Component {
  constructor(props) {
      super(props);
      // 创建
      this.listC = React.createRef();
  }
  componentDidMount(){
  	// 获取
      console.log(this.listC);
  }
  render() {
  	 // 赋值
      return <ListC ref={this.listC}/>
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 上下文Context

# React.createContext

  • 创建一个 context 对象
const MyContext = React.createContext(defaultValue);
1

# Context.Provider

  • 每个 Context 对象都附带一个 Provider React 组件
  • value 属性值可以传递其后代所有组件
  • 当 value 属性发生变化,后代组件都将重新渲染
<MyContext.Provider value={/* some value */}>
1

# Class.contextType

  • 可以给 class 组件分配上 contextType 属性
  • 使用 this.context 访问
  • 在任何生命周期方法中引用
import { AppContext } from './../store/common-context'

class Item extends Component {

  constructor() {
    super(...arguments);
    console.log(this.context)
  }
  ...
}

Item.contextType = AppContext

export default Item;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
更新于: 8/26/2020, 9:22:12 AM