1.React介绍

扩展—–强制刷新

强制触发render渲染

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
import React, { Component } from 'react'

export default class demob extends Component {
constructor(){
super()

this.xiaoming="你好"
}
fun=()=>{
this.xiaoming="你坏"
console.log(this.xiaoming)
// 我们可以强制触发render重新渲染页面
this.forceUpdate()
}
render() {
return (
<>
<h1>强制刷新</h1>
<h1>{this.xiaoming}</h1>
<button onClick={this.fun}>点我修改</button>
</>
)
}
}

6.组件传值

组件默认是一个完整独立的个体。组件与组件之间的数据默认是不能相互使用的

正向传值–props

函数组件

子组件

1
2
3
4
5
6
7
8
9
10
11
// 1.把props当成函数的形参传入
let Zi=(props)=>{
return (
<div>
{/* 2.使用props来进行数据的展示 */}
ziziziziziziz--{props.title}
</div>
)
}

export default Zi

父组件进行传递

1
2
3
4
5
6
7
8
9
10
11
12
13
import Zi from "./zi.jsx"

let Fu=()=>{
return (
<div>
FFUFUFUFUFUFUF
{/* 父组件传递 */}
<Zi title="我是父组件的书"></Zi>
</div>
)
}

export default Fu

专业的写法

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
父组件

import Zi from "./zi.jsx"

let Fu=()=>{
// 定义数据
let obj={
title:"你好么么哒!!!!!"
}
return (
<div>
FFUFUFUFUFUFUF
{/* 父组件使用扩展运符传递 */}
<Zi {...obj}></Zi>
</div>
)
}

export default Fu

子组件
import React from 'react'

// 1.形参传入props
export default function Zi(props) {

let {title}=props

return (
<div>
Zi
<span>
{title}
</span>

</div>
)
}

类组件

1.子组件 this.props.xxx

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Component } from 'react'

export default class zi extends Component {
render() {
return (
<div>
zi
{/* 1.子组件定义props */}
<h1>父组件的数据式-----{this.props.title}</h1>
</div>
)
}
}

2.父组件传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { Component } from 'react'
import Zi from "./zi.jsx"
export default class fu extends Component {
render() {
return (
<div>
fu
{/* 父组件给子组件传递数据 */}
<Zi title="我式父组件的数据"></Zi>
</div>
)
}
}

专业的写法

子组件中使用结构来优化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { Component } from 'react'

export default class zi extends Component {
render() {
// 使用解构的方式见到了this。props的重复出现率
let {title,age,name,sex,love}=this.props
return (
<div>
zi
{/* 1.子组件定义props */}
<h1>父组件的数据式-----{title}</h1>
<h1>父组件的数据式-----{age}</h1>
<h1>父组件的数据式-----{name}</h1>
<h1>父组件的数据式-----{sex}</h1>
<h1>父组件的数据式-----{love}</h1>
</div>
)
}
}

父组件使用扩展运算符传递数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react'
import Zi from "./zi.jsx"
export default class fu extends Component {
render() {
let obj={
title:"我是title",
name:"我是name",
age:18,
sex:"男",
love:"女"
}
return (
<div>
fu
{/* 扩展运算符快速传递数据 */}
<Zi {...obj}></Zi>
</div>
)
}
}

this.props.children

思考

在react组件调用中我们的开标前和关标签中能否插入内容 ?

不能 因为组件是一个完整的独立的个体 默认不能插入

this.props.children 他表示所有组件的子节点(默认写上没有任何作用 在组件被调用的时候 如果我们在他的开关标签中插入dom元素 那么this.props.chilren 就会接收并且显示)

逆向传值–使用props接收一个函数

子组件把数据给父组件

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Component } from 'react'

export default class zi extends Component {
render() {
return (
<div>
zizizizzizi
{/* 1.逆向传值必须通过事件来触发 一个父组件传递过来的函数*/}
<button onClick={this.props.demofun}>点我进行逆向传值</button>
</div>
)
}
}

父组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from 'react'
import Zi from "./zi.jsx"
export default class fu extends Component {
fufun=()=>{

}
render() {
return (
<div>
fuffufufufuf
{/* 2.父组件给子组件传递一个函数 */}
<Zi demofun={this.fufun}></Zi>

</div>
)
}
}

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { Component } from 'react'

export default class zi extends Component {
render() {
return (
<div>
zizizizzizi
{/* 1.逆向传值必须通过事件来触发 一个父组件传递过来的函数*/}
{/* 3.给函数进行实参的传递 */}
<button onClick={this.props.demofun.bind(this,"我是子组件的数据")}>点我进行逆向传值</button>
</div>
)
}
}

父组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from 'react'
import Zi from "./zi.jsx"
export default class fu extends Component {
// 4.父组件设置形参接收子组件绑定的实参
fufun=(text)=>{
console.log("我是父组件的函数",text)
}
render() {
return (
<div>
fuffufufufuf
{/* 2.父组件给子组件传递一个函数 */}
<Zi demofun={this.fufun}></Zi>

</div>
)
}
}

同胞传值

Pubsub-js

react中默认是不能进行同胞传值的 如果我们要进行 那么必须依赖 pubsub-js(是-js 千万不要记错了)库来实现

1.npm install –save pubsub-js

2.抛出 在需要传递的组件中使用 Pubsub.publish(“自定义事件名”,”数据”) publish创建自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from 'react'
// 1.引用pubsub-js
import Pubsub from "pubsub-js"
export default class zia extends Component {
fun=()=>{
// 2.publish抛出自定义事件
Pubsub.publish("zia","我是zia的数据么么哒!!!!!")
}
render() {
return (
<div>zia
<button onClick={this.fun}>点我把数据传递到zib</button>

</div>
)
}
}

3.接收 在需要接收数据的组件中使用Pubsub.subscribe(“你监听的事件”,()=>{})subscribe 监听自定义事件

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
import React, { Component } from 'react'
// 3.引用pubsub
import Pubsub from "pubsub-js"
export default class zib extends Component {
constructor(){
super()
console.log("1.react初始化数据")
}
componentWillMount(){
console.log("2.在渲染之前调用")
}
componentDidMount() {
// 接收 监听同胞传值的自定义事件
// 回调函数的第一个形参是你监听的自定义事件的名字
// 回调函数的第二个形参就是自定义事件上绑定的数据
Pubsub.subscribe("zia",(a,b)=>{
console.log(a)
console.log(b)
})

}
render() {
console.log("3开始渲染")
return (
<div>zib</div>
)
}
}

状态提升–中间人模式

React中的状态提升概括来说,就是将多个组件需要共享的状态提升到它们最近的父组件

上.在父组件上改变这个状态然后通过props分发给子组件.

跨组件传值

context对象–上下文对象

react 组件间传递数据是通过 props 向下,是单向传递的,从父级一层一层地通过 props 地向下传递到子子孙孙,有的时候我们组件一层一层的嵌套多层,这样这种方式一层一层传递麻烦,如果想跃层传递,这就会用到 context

context:上下文对象

context很好的解决了跨组件传值的复杂度。可以快速的进行跨组件数据的传递。

想要使用context进行跨组件传值那么就要使用createContext()方法同时方法中给我们提供了两个对象:

Provider对象 生产者—->用来生产数据
Consumer对象 消费者—->用来使用数据

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
import React, { Component } from 'react'
// 1.创建context对象
const GlobalContext = React.createContext()

class Zia extends Component {
render() {
return (
<div>
我是第一个子组件
</div>
)
}
}
class Zib extends Component {
render() {
return (

<div>
我是第2个子组件
{/* 3.任意组件引入GlobalContext并调用context,使用GlobalContext.Consumer(消费者) */}

<GlobalContext.Consumer>
{/* 4.在回调函数中直接使用生产者的数据 */}
{

(value) => {
return <h1>{value.name}</h1>
}
}
</GlobalContext.Consumer>
</div>

)
}
}
export default class fu extends Component {
render() {
return (
// 2.在根组件件引入GlobalContext,并使用GlobalContext.Provider生产者
// 并且使用value属性传入数据
<GlobalContext.Provider value={{ name: "xiaoyang", age: 18 }}>
<div>
我是根组件
<Zia />
<Zib />
</div>
</GlobalContext.Provider>
)
}
}

redux

redux是什么?

redux就是一个javascript的状态管理工具 可以集中的管理react中多个组件的状态 让我们组件之间数据传递变得非常的简单

redux是一个第三方的 也就是说他可以在react中用 也可以在vue中进行使用

如果组件需要进行跨层级传值 传统的方式 就是组件一层层的进行逆向传值传递到他们最近的一个父组件身上 然后再一层层的进行正向传值

redux的三大原则

1.单一数据源 :整个项目的数据都被存储在一个store对象中

2.state是只读的:如果我们想改变state的数据 那么必须触发action里面的修改动作来执行修改

3.使用纯函数来进行修改:reducer就是一个函数 我们通过reducer中的state和action动作来进行数据的修改

redux使用

1.下载redux npm install –save redux

2.在项目的文件夹中创建一个store文件夹(容纳redux的代码)

3.在新建一个文件容纳基本代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1.创建redux对象(先引用redux创建方法createStore)
import {createStore} from "redux"
// 6.创建创建state数据
let data={
name:"xiaoyang",
age:18,
sex:"男"
}
// 5.创建reducer 是一个方法 其中保存的就是redux中存储的变量和修改变量的方法
// state就是数据状态
// action 修改上面数据状态的一些动作
// 7.把上面的数据传递给state
let reducer=(state=data,action)=>{
// 8把state return
return state
}
// 2.开始创建redux对象
// 4.把状态和修改状态的方法传递到初始化redux中
let store=createStore(reducer)
// 3.暴露redux对象
export default store
读取redux中的数据

store.getState().你要读取的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react'
// 1.引用redux
import store from "../store/index.js"
export default class demoa extends Component {
// 2.把数据复制给组件的state中进行保存
state={
name:store.getState().name
}

render() {
return (
<div>
<h1>redux的基本使用</h1>
{/* 3.读取 */}
<h1>使用数据---{this.state.name}</h1>
</div>
)
}
}

基本数据修改

我们需要通过dispatch()来调用写在action中的修改动作

千万不要和vuex搞混了 因为在vuex中 dispatch触发action是进行异步操纵的触发器

但是但是 在redux中 dispatch触发 的这个action里面存储的是修改状态的动作

1
2
3
4
5
fun=()=>{
// 通过dispatch来修改数据
// store.dispach({type:"你要触发的修改动作"})
store.dispach({type:"USER_UP_NAME"})
}

编写修改数据的动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {createStore} from "redux"

let data={
name:"xiaoyang",
age:18,
sex:"男"
}

let reducer=(state=data,action)=>{
// 创建修改动作
switch (action.type) {
case "USER_UP_NAME":
console.log({...state,name:"我变了"})
return {...state,name:"我变了"}
break;

default:
return state
break;
}
}
let store=createStore(reducer)

export default store

但是大家运行后发现 数据修改了 但是页面并没有发生改变

原因很简单 因为 虽然你数据变了 但是组件中的render并没有重新执行 那么页面当然不会修改了

subscribe() 监听redux state的状态 改变就会触发

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
import React, { Component } from 'react'
// 1.引用redux
import store from "../store/index.js"
export default class demoa extends Component {
// 2.把数据复制给组件的state中进行保存
state={
name:store.getState().name
}

// 我们可以监控这redux中的state数据 如果redux中的数据改变了
// 我重启读取下并且在触发组件中的render那么 页面的内容就会改变
componentDidMount() {

store.subscribe(()=>{
// 当redux中的state数据改变了 那么subscribe就会触发
this.setState({
name:store.getState().name
})
})

}

fun=()=>{
// 通过dispatch来修改数据
// store.dispach({type:"你要触发的修改动作"})
store.dispatch({type:"USER_UP_NAME"})
}

render() {
return (
<div>
<h1>redux的基本使用</h1>
{/* 3.读取 */}
<h1>使用数据---{this.state.name}</h1>
<button onClick={this.fun}>点我修改上面的数据</button>
</div>
)
}
}

合并reducer(把redux拆分成一个个的模块)

随着项目的体积越来越大 项目的state和修改的动作也会越来越多

1.新建一个reducer.js(就是一个合并工厂 把今后拆分的一个个的小模块合并起来)

2.新建一个文件夹modules 里面放置我们拆分的一个个的小模块

3.开始拆分 把原来写在一起的state和原来写在一起的动作查分出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 里面存放的就是demoa的state数据和demoa的修改动作
let data={
name:"xiaoyang",

}

let demoam=(state=data,action)=>{
// 创建修改动作
switch (action.type) {
case "USER_UP_NAME":
console.log({...state,name:"我变了"})
return {...state,name:"我变了"}
break;

default:
return state
break;
}
}

export default demoam

4.开始合并reducers.js中进行

1
2
3
4
5
6
7
8
9
10
11
12
13
// reducer合并工厂中吧modules文件夹中多个小模块进行合并
// 1.把你要合并的所有模块引用进来
import demoam from "./modules/demoam.js"
import demobm from "./modules/demobm.js"
// 2.引用合并模块的方法
import {combineReducers} from "redux"
// 3.开始合并
let reducer=combineReducers({
demoam,
demobm
})
// 4.暴露
export default reducer

5.把合并好的模块 注入到redux实例中

1
2
3
4
5
6
7
8
import {createStore} from "redux"

// 引用合并好的reducer
import reducer from "./reducers.js"

let store=createStore(reducer)

export default store

大家会发现 我们合并好模块之后 在页面不显示数据了 因为我们把内容都合并成了模块所以要使用的时候

store.getState().模块名.xxxx

redux的数据执行流程

react-redux

react-redux 是一个专门为react开发的状态管理工具 而redux是第三方的

之前redux的写法 和react的耦合度太高 (在react中吧第三方的redux集成在项目里面 会造成代码的可读性太低)

react-redux 就可以简化我们在react中使用redux的复杂度

使用

1.下载 npm install –save react-redux

2.我们需要在项目的全局组件之上 设置Provider 发布者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
import ReactDOM from 'react-dom';

import App from "./components/demob.jsx"

// 1.引用provider
import { Provider } from "react-redux"
import store from "./store/index.js"
ReactDOM.render(
// 2.使用provider把redux对象传递到所有的子组件身上
// 3.传入store对象
<Provider store={store}>
<App />
</Provider>,

document.getElementById('root')
);


2.设置组件与redux的连接

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
import React, { Component } from 'react'
// 1.引用react-redux给我们提供的连接方法
// connect是一个函数 当这个函数被调用的时候就是一个高阶组件
import {connect} from "react-redux"
class demob extends Component {
add=()=>{

}
del=()=>{

}
render() {
return (
<div>
demob
<h1>读取redux存储的age</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.del}>点我-1</button>
</div>
)
}
}
// connect是一个函数 当这个函数被调用的时候就是一个高阶组件
// 第一个() 就是调用函数的语法
// 第二个() 就是高阶组件的语法
export default connect()(demob)

3.得到redux中的数据

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
import React, { Component } from 'react'
// 1.引用react-redux给我们提供的连接方法
// connect是一个函数 当这个函数被调用的时候就是一个高阶组件
import {connect} from "react-redux"
class demob extends Component {
add=()=>{

}
del=()=>{

}
render() {
return (
<div>
demob
{/* 使用react-redux读取数据 this.props.state.模块名.xxx */}
<h1>读取redux存储的age--{this.props.state.demobm.age}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.del}>点我-1</button>
</div>
)
}
}
// connect是一个函数 当这个函数被调用的时候就是一个高阶组件
// 第一个() 就是调用函数的语法
// 第二个() 就是高阶组件的语法
// 形参的state今后就是redux中的数据
export default connect(state=>({state}))(demob)
修改

在组件中调用dispatch就可以直接完成修改操作

1
2
3
4
5
add=()=>{
// react-redux修改数据
// 还是使用dispatch触发action的动作
this.props.dispatch({type:"AGE_NUMBER_ADD_ONE",num:3})
}