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) 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
| 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'
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() { 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 { 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'
import Pubsub from "pubsub-js" export default class zia extends Component { fun=()=>{ 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'
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'
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 ( <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
| import {createStore} from "redux"
let data={ name:"xiaoyang", age:18, sex:"男" }
let reducer=(state=data,action)=>{ return state }
let store=createStore(reducer)
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'
import store from "../store/index.js" export default class demoa extends Component { 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=()=>{ 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'
import store from "../store/index.js" export default class demoa extends Component { state={ name:store.getState().name }
componentDidMount() { store.subscribe(()=>{ this.setState({ name:store.getState().name }) })
}
fun=()=>{ 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
| 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
|
import demoam from "./modules/demoam.js" import demobm from "./modules/demobm.js"
import {combineReducers} from "redux"
let reducer=combineReducers({ demoam, demobm })
export default reducer
|
5.把合并好的模块 注入到redux实例中
1 2 3 4 5 6 7 8
| import {createStore} from "redux"
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"
import { Provider } from "react-redux" import store from "./store/index.js" ReactDOM.render( <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'
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> ) } }
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'
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> ) } }
export default connect(state=>({state}))(demob)
|
修改
在组件中调用dispatch就可以直接完成修改操作
1 2 3 4 5
| add=()=>{ this.props.dispatch({type:"AGE_NUMBER_ADD_ONE",num:3}) }
|