共计 20255 个字符,预计需要花费 51 分钟才能阅读完成。
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 组件以及 redux
import {connect} from 'react-redux'
// 引入 action
import {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 组件以及 redux import {connect} from 'react-redux' // 引入 action import {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
命令