react
框架库
react-router
路由pubsub
音讯治理redux
状态治理ant-design
UI库
要点
jsx
最初翻译过去就是React.createElement
办法createElement(element,options,content)
elment
元素名称options
属性对象content
属性外面的内容demo: createElement('h1',{id:'test'},'hello react')
- 虚构dom解析后是Object
jsx注意事项
- 变量用一个大括号括起来;
- 如果援用
class
款式,须要用className
- 定义的
jsx
不须要引号,如果有多层,用小括号括起来 - 内联款式
style
要用对象的模式,且属性要用驼峰命名 - 只容许一个根标签
- 标签必须闭合
自定义组件以大写字母结尾
const name='zhangsan'const Rdom=( <div> <h1 className='test' style={{fontSize:'20px'}}>{name}<h1> <h1 className='test' style={{fontSize:'20px'}}>{name}<h1> </div>)
react
创立函数组件- 函数名大写,且要有返回值
援用须要用标签,且标签要有闭合
function Demo(){ return <h1>demo test</h1>}ReactDOM.render(<Demo/>,document.getElementById('test'))
react
创立类组件- 自定义组件类必须继承
React.Component
- 类组件外面必须定义
render
办法,并且须要返回值 - 调用组件,渲染到页面,组件是命名是大写结尾
- 调用组件会
new
一个组件,而后调用render
办法,且类外面this
指向的是组件创立的实力对象,也叫组件实力对象。
class MyComponent extends React.Component{ render(){ return ( <h1>test</h1> ) } } ReactDOM.render(<MyComponent/>,document.getElementById('test'))
- 自定义组件类必须继承
react
事件以及state
1.节点绑定事件须要用
on
+事件名,须要驼峰命名2.事件的回调函数须要用
bind
从新绑定,否则this
会失落,或者用箭头函数赋值给属性,绑定该属性3.
state
对象外面须要定义须要变动的状态(属性)4.更改
state
外面的状态,须要用this.setState
办法5.自定义办法须要用箭头函数赋值给属性,或者用
bind
办法绑定this
class ChangeWeather extends React.Component{ constructor(){ super() this.state={ flag:true } this.changeFlag=this.changeFlag.bind(this) } render(){ const {flag}=this.state return ( <h1 onClick={this.changeFlag}>今天天气很{flag?'好':'不好'}</h1> ) } changeFlag(){ this.setState({ flag:!this.state.flag }) } } ReactDOM.render(<ChangeWeather/>,document.getElementById('test'))
//下面例子精简版class ChangeWeather extends React.Component { state = { flag: true } render() { const { flag } = this.state return ( <h1 onClick={this.changeFlag}>今天天气很{flag ? '好' : '不好'}</h1> ) } changeFlag = () => { this.setState({ flag: !this.state.flag }) } } ReactDOM.render(<ChangeWeather />, document.getElementById('test'))
react
外面的props
1.通过标签传递属性,能够通过扩大运算符进行传递
2.组件外面通过
props
援用3.如果是变量须要用大括号的模式进行传递
class ChangeWeather extends React.Component{ render (){ return ( <div> {this.props.title} {this.props.age} {this.props.obj.test} {this.props.test} </div> ) } } const obj={ test:123 } ReactDOM.render(<ChangeWeather title="title" age={18} obj={obj} {...obj}/>, document.getElementById('test'))
props
的属性限度以及默认值1.16.x版本之前是用
React.propsType.xxxx
进行限度,之后的版本是须要引入propstype.js
,而后再类的propTypes
属性下面进行定义2.限度属性的时候,间接定义到类下面进行限度
3.如果是函数限度传的类型为
func
,而不是function
4.如果没有传值,须要给默认值,须要再类的
defaultProps
属性下面进行定义默认值5.定义的这些规定须要咋渲染之前进行定义
6.定义的属性规定也能够用动态属性进行定义
static
//间接定义到类下面class ChangeWeather extends React.Component{ render (){ return ( <div> {this.props.title} {this.props.age} {this.props.obj.test} {this.props.test} </div> ) } } //须要再渲染之前进行规定定义,在类的propTypes下面进行定义 ChangeWeather.propTypes = { title: PropTypes.string.isRequired, fun:PropTypes.func.isRequired//函数要用func这个类型 } //默认值须要再类的defaultProps属性下面进行定义 ChangeWeather.defaultProps={ title:"fdsaf", fun:function(){} } const obj={ test:123, } ReactDOM.render(<ChangeWeather title="test" age={18} obj={obj} {...obj}/>, document.getElementById('test'))
//用动态属性的形式class ChangeWeather extends React.Component { static propTypes = { title: PropTypes.string.isRequired, fun: PropTypes.func.isRequired } static defaultProps = { title: "fdsaf", fun: function () { } } render() { return ( <div> {this.props.title} {this.props.age} {this.props.obj.test} {this.props.test} </div> ) } } const obj = { test: 123, } ReactDOM.render(<ChangeWeather title="test" age={18} obj={obj} {...obj} />, document.getElementById('test'))
react
外面的ref
1.在节点外面通过
ref
属性进行绑定2.在逻辑外面通过
refs
承受3.承受的
ref
是一个实在节点class Test extends React.Component{ render(){ return ( <div> <input ref="input1" type="text"/> <button onClick={this.btnClick}>点击</button> </div> ) } btnClick=() => { const {input1}=this.refs alert(input1.value) } } ReactDOM.render(<Test/>,document.getElementById('test'))
4.
ref
通过回调形式获取/* ref 回调函数的模式 */ class Reftest extends React.Component{ inputel=null btnClick=() => { alert(this.inputel.value) } render(){ return ( <div> <input type="text" ref={(el)=>{this.inputel=el}}/> <button onClick={this.btnClick}>点击 </button> </div> ) } } ReactDOM.render(<Reftest/>,document.getElementById('test'))
ref
如果用内联的形式进行获取,在数据更新的 时候会调用两次回调函数,第一次会给回调函数传null
第二次会传以后的节点。解决办法为间接用绑定的回调函数。只会调用一次回调函数,不会调用屡次。然而内联和绑定的形式不会有任何影响。开发中个别用内联的形式进行开发。ref
的创立形式三,通过React.createRef
的形式创立。该函数调用后会返回一个对象,key
为current
的对象,值为节点。有多少个ref
就要调用几次后面的函数。官网举荐写法/* ref React.createRef的形式 */ class Test extends React.Component{ //有多少个就要创立多少个 refstest=React.createRef(); btnclick=()=>{ console.log(this.refstest.current.value); } render(){ return ( <div> //这里了是须要绑定下面返回的属性 <input ref={this.refstest} type="text"/> <button onClick={this.btnclick}>点击</button> </div> ) } } ReactDOM.render(<Test/>,document.getElementById('test'))
react
的非受控组件
- 所有的表单组件现用现取的组件。取值须要用到
ref
react
的受控组件所有的输入框的值都存到状态外面,相似
vue
的双向绑定/* 受控组件*/ class Test extends React.Component { state = { name: '' } getTestValue = (e) => { this.setState({ name: e.target.value }) } handleClick = () => { console.log(this.state.name); } render() { return ( <div> <input type="text" onChange={this.getTestValue} /> <button onClick={this.handleClick}>点击</button> </div> ) } } ReactDOM.render(<Test />, document.getElementById('test'))
函数的柯力化以及高阶函数
1.高阶函数:
1.1函数返回一个函数
1.2 函数传参,该参数为一个函数
2.柯力化函数:
2.1函数返回函数,最初返回的函数一起解决后面函数的参数。
class Test extends React.Component { state = { name: '' } getTestValue = (name) => { return (event) => { console.log(name,event); } } handleClick = () => { console.log(this.state.name); } render() { return ( <div> <input type="text" onChange={this.getTestValue('test')} /> <button onClick={this.handleClick}>点击</button> </div> ) } } ReactDOM.render(<Test />, document.getElementById('test'))
react
的申明周期ReactDOM.unmountComponentAtNode(el)
卸载组件//只有一获取值就销毁组件class Test extends React.Component { getValue(key, e) { ReactDOM.unmountComponentAtNode(document.getElementById('test')) } render() { return ( <div> <input type="text" onChange={(e) => { this.getValue('userName', e) }} /> </div> ) } } ReactDOM.render(<Test />, document.getElementById('test'))
react
组件生命周期1.
componentDidMount
//组件挂在时调用,只调用一次2.componentWillUnmount //组件行将销毁
/* 组件生命周期演示 */ class Test extends React.Component { state = { count: 1 } timer = null; render() { const { count } = this.state; return ( <div> <div> 数字:{count}</div> <div onClick={this.removeTimer}>点击我</div> </div> ) } // 组件挂载 componentDidMount() { this.timer = setInterval(() => { let { count } = this.state; count += 1; this.setState({ count, }) }, 200) } // 组件行将卸载 componentWillUnmount() { clearInterval(this.timer) } removeTimer = () => { // 移除以后组件 ReactDOM.unmountComponentAtNode(document.getElementById('test')) } } ReactDOM.render(<Test />, document.getElementById('test'))
子组件生命周期执行程序
constructor
componentWillMount
render
componentDidMount
componentWillUnmount
getSnapshotBeforeUpdate
//初始化的申明周期执行程序class Demo extends React.Component { constructor(props) { super(props) console.log('constructor'); this.state = { count: 1 } } componentWillMount() { console.log('componentWillMount'); } componentWillUnmount() { console.log('componentWillUnmount'); } render() { console.log('render'); const { count } = this.state return ( <div> <div>展现的count:{count}</div> <div onClick={this.btnClick}>点击我</div> <div onClick={this.remove}>卸载组件</div> </div> ) } remove = () => { ReactDOM.unmountComponentAtNode(document.getElementById('test')) } btnClick = () => { let { count } = this.state count += 1; this.setState({ count, }) } } ReactDOM.render(<Demo />, document.getElementById('test'))
class A extends React.Component{ state={ count:1 } render(){ console.log('render'); const {count}=this.state return ( <div> <B name={count}/> <div>count {count}</div> <div onClick={this.btnClick}>点击我</div> </div> ) } // 跟新的时候会走这个生命周期,必须要返回true或者false,若返回false就不会执行前面的申明周期 shouldComponentUpdate(){ console.log('shouldComponentUpdate'); return true } componentWillUpdate(){ console.log('componentWillUpdate'); } componentDidUpdate(){ console.log('componentDidUpdate'); } btnClick=() => { let {count}=this.state count+=1; this.setState({ count , }) } } class B extends React.Component{ //父组件传递的props更新了才会调用这个生命周期,首次不会调用该生命周期 componentWillReceiveProps(){ console.log('componentWillReceiveProps'); } render(){ return ( <div>{this.props.name}</div> ) } } ReactDOM.render(<A />, document.getElementById('test'))
class Demo extends React.Component { state = { arr: [] } componentDidMount() { setInterval(() => { const { arr } = this.state; this.setState({ arr: ['新闻' + (arr.length + 1), ...arr] }) }, 1000) } // 新的申明周期,在更新前执行,能够像componentDidUpdate申明周期外面传递一个参数 getSnapshotBeforeUpdate() { return this.refs.list.scrollHeight } componentDidUpdate(prepops, prestates, scrollheight) { console.log(this.refs.list.scrollHeight, '...', scrollheight); this.refs.list.scrollTop += this.refs.list.scrollHeight - scrollheight } render() { return ( <div> <div className="list" ref="list"> { this.state.arr.map((item, index) => { return ( <div key={index} className="li">{item}</div> ) }) } </div> </div> ) } } ReactDOM.render(<Demo />, document.getElementById('test'))
react diff
算法- 通过数据渲染成虚构
dom
- 通过
key
值去判断是否存在雷同的值,如果key
值雷同,判断对应的内容是否雷同,若内容雷同复用原来的dom
,如果不雷同,创立新的dom
渲染到页面,如果key
值不雷同间接生成dom
渲染到页面 - 应用
index
作为key
值存在的问题:可能会使效率低下(旧dom
可能复用不了),页面错位(若数据存在逆反操作)。
- 通过数据渲染成虚构
react
脚手架1.全局装置
npm i -g create-react-app
2.进入要创立我的项目的目录控制台执行
create-react-app projectName
即创立胜利款式模块化
1.利用文件名
XXX.module.css
,引入形式import hello from './xxx.module.css'
在用的中央用hello.className
的模式进行2.利用
less
进行嵌套react
组件父子通信1.父传子利用
props
进行传递2.子传父利用
props
给子组件传递函数,子组件通过props
接管该函数,而后调用,且能够传值。- 公共用的状态放到父组件中(状态晋升),状态定义到哪里,对应的办法就对应在哪个组件中
解决跨域
利用
package.json
的proxy
字段进行代理。申请的时候用本地的域名加端口号加接口名进行申请//pageage.json "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ], "proxy":"http://localhost:5000"
//申请的地址,端口号为本地的3000,3000代理到服务器为端口号5000的服务器axios.get('http://localhost:3000/students') .then((res) => { console.log(res.data) }) }
2.在我的项目目录src/下新建setupProxy.js文件,而后写入如下代码:
const proxy = require('http - proxy - middleware');module.exports = function (app) { app.use(proxy('/api', { target: 'http://localhost:5000', secure: false, changeOrigin: true, pathRewrite: { "^/api": "" }, }));};
兄弟组件之间的通信,利用
pubsubjs
装置
pubsub-js
yarn add pubsub-js
引入
pubsubjs
并在传递数据的组件中进行音讯公布,在须要获取数据的组件中进行音讯订阅componentDidMount() { this.id=Pubsub.subscribe('getData', (name, stateObj) => { this.setState(stateObj) }) }componentWillUnmount(){ pubsub.undescribe(this.id)}request=()=>{ axios.get( 'http://localhost:3000/xxx' ) .then((res) => { Pubsub.publish('getData',{ loading: false, users: res.data.items, err:false }) }) .catch((err) => { Pubsub.publish('getData',{ loading: false, err:err.message }) })}
react
路由1.装置
react-router-dom
yarn add react-router-dom
引入必要组件
import React, { Component } from 'react'import { Link, Route } from 'react-router-dom'import About from './components/About'import Home from './components/Home'export default class App extends Component { render() { return ( <div> <div className="row"> <div className="col-xs-offset-2 col-xs-8"> <div className="page-header"><h2>React Router Demo</h2></div> </div> </div> <div className="row"> <div className="col-xs-2 col-xs-offset-2"> <div className="list-group"> {/* <a className="list-group-item active" href="./about.html">About</a> <a className="list-group-item" href="./home.html">Home</a> */} <Link to="/about" className="list-group-item">About</Link> <Link to="/home" className="list-group-item">Home</Link> </div> </div> <div className="col-xs-6"> <div className="panel"> <div className="panel-body"> {/* <h3>我是About的内容</h3> */} <Route path='/about' component={About}/> <Route path='/Home' component={ Home}/> </div> </div> </div> </div> </div> ) }}
import React from 'react';import ReactDOM from 'react-dom';import { BrowserRouter } from 'react-router-dom'import './index.css';import App from './App';ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, document.getElementById('root'));
- 通过
this.props.children
能够获取标签体内容 switch
组件包裹路由只会匹配第一个匹配到 的路由进行渲染对应组件react
多级路由导致款式失落问题public
文件下的index.html
文件引入文件门路批改为/
绝对路径的这种模式,或者用%PUBLIC_URL%
这种模式进行引入。- 或者将
BrowserRouter
组件换成HashRouter
组件
`Router
组件中的exact`属性用于精准匹配路由<Route exact path='/home' component={Home} />
Redirect
组件用于没有匹配到门路的时候,调转到默认路由,个别放到注册组件最初Switch
组件用于匹配到第一个路由就不往后面进行匹配NavLink
用于路由高亮显示,能够自定义className
Link
用于路由跳转<Switch> <Route path='/about/about' component={About} /> <Route exact path='/home' component={Home} /> <Redirect to="/home"></Redirect> </Switch>
嵌套路由
1.子组件注册组件须要带上父组件的
path
- 父组件
import React, { Component } from 'react'import { Switch, Route ,Redirect} from 'react-router-dom'import About from './pages/About'import Home from './pages/Home'import MyNavLink from './components/MyNavLink'import './App.css'export default class App extends Component { render() { return ( <div> <div className="row"> <div className="col-xs-offset-2 col-xs-8"> <div className="page-header"><h2>React Router Demo</h2></div> </div> </div> <div className="row"> <div className="col-xs-2 col-xs-offset-2"> <div className="list-group"> <MyNavLink to="/about" >About</MyNavLink> <MyNavLink to="/home" >Home</MyNavLink> </div> </div> <div className="col-xs-6"> <div className="panel"> <div className="panel-body"> <Switch> <Route path='/about' component={About} /> <Route path='/home' component={Home} /> <Redirect to="/home"></Redirect> </Switch> </div> </div> </div> </div> </div> ) }}
- 子组件
import React from "react";import Message from "./Message";import News from "./News";import MyNavLink from "../../components/MyNavLink";import { Switch, Route,Redirect } from 'react-router-dom'export default class Home extends React.Component { render() { console.log(this.props); return ( <div> <h2>Home组件内容</h2> <div> <ul className="nav nav-tabs"> <li> <MyNavLink to="/home/news">News</MyNavLink> </li> <li> <MyNavLink to="/home/message">message</MyNavLink> </li> </ul> <Switch> <Route path="/home/news" component={News}></Route> <Route path="/home/message" component={Message}></Route> <Redirect to="/home/message"></Redirect> </Switch> </div> </div> ) }}
路由组件传参
params
传参1.跳转的中央须要进行参数按程序传递
2.注册的中央须要进行按程序进行接管
3.子组件通过
this.props.match.params
获取import React, { Component } from 'react'import { Route } from 'react-router';import { Link } from 'react-router-dom';import MsgDetail from './MsgDetail';export default class Message extends Component { state = { students: [{ id: 1, name: '张三', age: 12 }, { id: 2, name: '李四', age: 13 }, { id: 3, name: '王二', age: 14 }] } render() { const { students } = this.state; return ( <div> <ul> { students.map((item) => { return ( <li> <Link to={`/home/message/msgdetail/${item.name}/${item.age}`} key={item.id}>{item.name}</Link> </li> ) }) } </ul> <hr /> <Route path='/home/message/msgdetail/:name/:age' component={MsgDetail}/> </div> ) }}
4.子组件进行获取
import React, { Component } from 'react';class MsgDetail extends Component { render() { console.log(this.props); const { name, age } = this.props.match.params; return ( <div> {name}----{ age} </div> ); }}export default MsgDetail;
search
传参(相似vue
外面的query
)1.在跳转的中央进行传递
2.在子组件的
this.props.location.search
进行取值3.须要将
search
参数进行转换成对象的模式import React, { Component } from 'react'import { Route } from 'react-router';import { Link } from 'react-router-dom';import MsgDetail from './MsgDetail';export default class Message extends Component { state = { students: [{ id: 1, name: '张三', age: 12 }, { id: 2, name: '李四', age: 13 }, { id: 3, name: '王二', age: 14 }] } render() { const { students } = this.state; return ( <div> <ul> { students.map((item) => { return ( <li> <Link to={`/home/message/msgdetai?name=${item.name}&age=${age}`} key={item.id}>{item.name}</Link> </li> ) }) } </ul> <hr /> <Route path='/home/message/msgdetail' component={MsgDetail} /> </div> ) }}
4.子组件进行获取
import React, { Component } from 'react';import qs from 'querystring'class MsgDetail extends Component { render() { console.log(this.props); const { search } = this.props.location.search const { name,age}=qs.parse(search.slice(1)) return ( <div> {name}----{ age} </div> ); }}export default MsgDetail;
state
传参1.路由跳转的中央须要通过对象的形式进行传递,须要蕴含
path
以及state
属性。state
属性是一个对象2.子组件通过
this.props.locaiton.state
进行获取3.
state
传递的参数在地址栏下面是看不到的,下面的两种都是在地址栏下面看的到的。import React, { Component } from 'react'import { Route } from 'react-router';import { Link } from 'react-router-dom';import MsgDetail from './MsgDetail';export default class Message extends Component { state = { students: [{ id: '00122', name: '张三', age: 12 }, { id: '00233', name: '李四', age: 13 }, { id: '003432423', name: '王二', age: 14 }] } render() { const { students } = this.state; return ( <div> <ul> { students.map((item) => { return ( <li key={item.id}> <Link to={{ path: '/home/message/msgdetail', state: { name: item.name, age: item.age } }}>{item.name}</Link> </li> ) }) } </ul> <hr /> <Route path='/home/message/msgdetail' component={MsgDetail} /> </div> ) }}
4.子组件进行接管
import React, { Component } from 'react';import qs from 'querystring'class MsgDetail extends Component { render() { console.log(this.props); const { name,age}=this.props.location.state return ( <div> {name}----{ age} </div> ); }}export default MsgDetail;
编程式组件导航
通过
this.props.history
的api
进行跳转jump = (name,age) => { this.props.history.push('/home/message/msgdetail', { name, age } ) }
withRouter
若想在个别组件中应用路由跳转的api
能够引入withRouter
办法import React, { Component } from 'react'import { withRouter } from 'react-router-dom'class Header extends Component { goBack = () => { this.props.history.goBack() } goFowrd = () => { this.props.history.goForward() } render() { return ( <div className="page-header"> <h2>React Router Demo</h2> <button onClick={this.goBack}>回退</button> <button onClick={this.goFowrd}>后退</button> </div> ) }}export default withRouter(Header)
antd
按需引入,可参考地址https://3x.ant.design/docs/react/use-with-create-react-app-cn
中的高级配置redux
1.装置
redux
yarn add redux
2.创立
redux
文件夹,在该文件下创立store
文件,action
文件,reducer
文件,constent
文件
3.store.js
import { createStore } from "redux";import countRedux from './count_redux'export default createStore(countRedux)
4.count_action.js
import {ADD,DESC } from './constent'export const add = (data) => ({ type: ADD, data})export const desc = (data) => ({ type: DESC, data})
5.count_redux.js
import { ADD,DESC} from './constent'export default function (preState=0, action) { const { type,data}=action switch (type) { case ADD: return preState + data case DESC: return preState - data default: return preState } }
6.constent.js
export const ADD='add'export const DESC='desc'
7.index.js
import React from "react";import ReactDOM from "react-dom";import App from "./App.js";import store from './redux/store'ReactDOM.render(<App></App>, document.getElementById('root'))store.subscribe(() => { ReactDOM.render(<App></App>, document.getElementById('root'))})
异步
action
1.引入并装置
redux-thunk
2.利用中间件传入
thunk
3.
action
返回的是一个函数,该函数会带有dispatch
函数参数代码如下:
store.js
import { createStore, applyMiddleware } from "redux";import countRedux from './count_redux'import thunk from 'redux-thunk'export default createStore(countRedux, applyMiddleware(thunk))
action.js
export const addAsync = (data, time) => { //返回一个带有dispatch的参数的函数 return (dispatch) => { setTimeout(() => { dispatch(add(data))//调用同步action },time) }}
react-redux
1.引入并装置
yarn add react-redux
2.创立容器组件,用于操作状态以及包裹ui
组件(链接ui
组件以及redux
)
// 引入要展现的UI组件import countUi from '../../components/Count'// 用于连贯UI组件以及reduximport { connect } from 'react-redux'// 引入actionimport { add, desc, addAsync } from '../../redux/count_action'// 将store外面的状态映射到props,能够用过UI组件进行操作(ui组件通过this.props.xxx获取)function mapStateToProps(state) { return { count: state }}// 将store外面的操作状态的办法映射到props,能够用过UI组件进行操作(ui组件通过this.props.xxx获取)function mapDispatchToProps(dispatch) { return { add: (num) => { dispatch(add(num)) }, desc: (num) => { dispatch(desc(num)) }, addasync: (num, time) => { dispatch(addAsync(num,time)) } }}export default connect(mapStateToProps, mapDispatchToProps)(countUi)
- 通过
props
传递给子组件store
UI
组件的优化写法// 引入要展现的UI组件import countUi from '../../components/Count'// 用于连贯UI组件以及reduximport { connect } from 'react-redux'// 引入actionimport { add, desc, addAsync } from '../../redux/count_action'// 将store外面的状态映射到props,能够用过UI组件进行操作(ui组件通过this.props.xxx获取)/* function mapStateToProps(state) { return { count: state}} */// 将store外面的操作状态的办法映射到props,能够用过UI组件进行操作(ui组件通过this.props.xxx获取)/* function mapDispatchToProps(dispatch) {return { add: (num) => { dispatch(add(num)) }, desc: (num) => { dispatch(desc(num)) }, addasync: (num, time) => { dispatch(addAsync(num,time)) }}} */// export default connect(mapStateToProps, mapDispatchToProps)(countUi)// 优化写法export default connect(state => ({ count: state }),//这里能够返回一个简略对象,外部能够主动散发action{ add: add, desc: desc, addasync: addAsync})(countUi)
5.引入
react-redux
能够不必手动监听转态变动import React from "react";import ReactDOM from "react-dom";import App from "./App.js";// import store from './redux/store'ReactDOM.render(<App></App>, document.getElementById('root'))// 引入react-redux后能够不必手动监听状态变动// // 监测redux转态扭转,redux状态扭转会从新渲染页面// store.subscribe(() => {// ReactDOM.render(<App></App>, document.getElementById('root'))// })
6.利用
react-redux
的provider
传递store
import React from "react";import ReactDOM from "react-dom";import App from "./App.js";import store from './redux/store'import { Provider } from 'react-redux'ReactDOM.render(<Provider store={store}> <App /></Provider >, document.getElementById('root'))
多个
reducer
利用combineReducers
函数合并import { createStore, applyMiddleware ,combineReducers } from "redux";import countRedux from './reducers/count_redux'import person from "./reducers/person";import thunk from 'redux-thunk'export default createStore( // 多个reducer用combineReducers合并 combineReducers({ count: countRedux, person: person, }), applyMiddleware(thunk));
reducer
必须是一个纯函数,即传入的什么参数,就返回改参数,且传入的参数不能被改写。如果传入的是对象或者是数组。返回的值也应该是一个对象或数组,不能够在原有的对象或数组中进行操作再返回import { ADD_PERSON } from "../constent";export default function (prestate=[],action) { const { type, data } = action; switch (type) { case ADD_PERSON: return [data,...prestate] default: return [] }}
redux
配置的开发者工具- 谷歌浏览器装置
redux-devtools
- 在我的项目中装置
redux-devtools-extension
在
store.js
中进行如下配置import { createStore, applyMiddleware } from "redux";import thunk from 'redux-thunk'import { composeWithDevTools } from "redux-devtools-extension";import reducers from "./reducers";export default createStore( // 多个reducer用combineReducers合并 reducers, composeWithDevTools(applyMiddleware(thunk)));
- 谷歌浏览器装置
打包后的文件如何在本地启动
1.全局装置
serve
插件npm install -g serve
进入打包的文件目录运行
serve
命令