1.react介绍
- React 是Facebook内部的一个JavaScript类库。
- React 可用于创建Web用户交互界面。
- React不是一个完整的MVC框架,最多可以认为是MVC中的V(View),甚至React并不非常认可 MVC开发模式。
- React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。
- React 引入了虚拟DOM(Virtual DOM)的机制。
- React 引入了组件化的思想。
- React 使用Facebook专门为其开发的一套语法糖–JSX。
2.特点
虚拟DOM 组件化 JSX语法
3.优缺点
优点:
- 组件化开发
- 引入虚拟DOM,性能好,响应速度快
- JSX语法
- 单向数据绑定 Data Flow
- 跨浏览器兼容
- 完善的生态圈和活跃的社区
缺点:
- 不是完整MVC框架
- 不适用于复杂的大型应用
4.脚手架安装
npm i create-react-app -g //安装react脚手架
create-react-app demo //创建项目
cd demo //进入项目
npm start //启动项目 http://localhost:3000
目录结构:
-demo
-src
index.js 入口文件
App.js 根组件
index.css 样式
App.css App组件的样式
注意:
-
如果你保存就报错,删掉js-css-html formate插件
-
如何在vscode直接写标签
首先在 设置->emmet ->setting.json
"emmet.includeLanguages": {
"javascript":"javascriptreact"
},
5.JSX介绍
非表单元素绑定数据 属性绑定:{}
1.JSX语法遇到 < 就按HTML语法解析,遇到{ 就按JavaScript语法解析
2.使用三元表达式
3.使用函数表达式
4.JSX 标签可以相互嵌套
5.注意换行和缩进,增强代码的可读性,建议使用小括号括上 JSX 代码,防止分号自动插入的bug
6.属性绑定
7.style属性的值必须是一个对象
8.绑定class类名,必须使用className,不能使用class
9.注释 {/注释/}
6.列表渲染
Key可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。
因此你应当给数组中的每一个元素赋予一个确定的标识。
一个元素的key最好是这个元素在列表中拥有的一个独一无二的字符串。
通常,我们使用来自数据的id作为元素的key。
7.事件绑定
import React, { Component } from 'react';
import './App.css';
// 事件怎么绑定->参数传递—>event—>阻止默认事件 阻止事件传播—>当前这个框架有没有自己的事件小知识
class App extends Component {
a = 10;//属性
fn() {//方法
alert(this.a)
}
alertN(m,n){
alert(m+n);
}
getEvent(e){
console.log(e)
console.log(e.clientX)
}
getEvent2(e,n){
console.log(e.clientX)
console.log(n)
}
cancelRightKeyDown(e){
e.preventDefault();
console.log("右键了")
// return false;
}
outerClick(){
console.log("outer click")
}
innerClick(e){
e.stopPropagation();
console.log("inner click")
}
outerClick2(e){
e.stopPropagation()
console.log("outer2 click")
}
innerClick2(e){
console.log("inner2 click")
}
render() {//渲染
var b = 20;
return (
<div>
<h1>this is app</h1>
<p>{this.a}</p>
<p>{b}</p>
{/* 1.事件绑定方式 ①箭头函数 ②bind */}
<button onClick={()=>this.fn()}>点击就执行fn--1</button>
<button onClick={this.fn.bind(this)}>点击就执行fn--2</button>
{/* 2.事件传参 */}
{/* ①箭头函数 直接书写你的参数 */}
{/* ②bind 第一个参数是调用该函数的对象,从第二个参数开始,才是你要传递的参数 */}
<button onClick={()=>this.alertN(3,5)}>3+5</button>
<button onClick={this.alertN.bind(this,10,20)}>10+20</button>
{/* 3.event */}
{/* ①箭头函数 显示传参 在箭头函数的形参就是event ,event 可以在任何位置*/}
{/* ②bind 隐式传参 最后一个参数就是event */}
<button onClick={(ev)=>this.getEvent(ev)}>event1</button>
<button onClick={this.getEvent.bind(this)}>event2</button>
<button onClick={(e)=>this.getEvent2(e,10)}>e,10</button>
<button onClick={this.getEvent2.bind(this,20)}>e,20</button>
{/* 4.阻止默认事件 */}
{/* 注意:只能通过e.preventDefault阻止,在react中,return false不行 */}
<div className="box" onContextMenu={(e)=>this.cancelRightKeyDown(e)}>box1</div>
<div className="box" onContextMenu={this.cancelRightKeyDown.bind(this)}>222</div>
{/* 5.阻止事件传播 */}
{/* e.stopPropagation() */}
<div className="outer" onClick={()=>this.outerClick()}>
<div className="inner" onClick={(e)=>this.innerClick(e)}></div>
</div>
{/* <div className="outer" onClick={this.outerClick.bind(this)}>
<div className="inner" onClick={this.innerClick.bind(this)}></div>
</div> */}
{/* 6.如果想要绑定是捕获,那么就在你的事件后面加Capture */}
<div className="outer" onClickCapture={this.outerClick2.bind(this)}>
<div className="inner" onClickCapture={this.innerClick2.bind(this)}></div>
</div>
</div>
)
}
}
export default App;
7.组件注册
1.函数定义
//函数定义组件
import React from "react"
function Hello(){
return (
<div>
<h1>this is hello</h1>
</div>
)
}
export default Hello;
2.类定义
//类组件
import React,{Component} from "react"
class First extends Component {
render(){
return (
<div>
<h1>this is First</h1>
</div>
)
}
}
export default First
注意:
1.组件名称 首字母必须大写
2.组件的模板必须只能有 一个根节点
对比两种定义方式
1.函数定义没有生命周期 类定义的组件有生命周期,比如render constructor;
2.函数定义接收父组件传递的数据用props,类定义接收父组件传递的数据使用的是this.props;
3.类定义有state状态机,当调用setState,会重新执行render,函数定义是没有state.
8.父传子
{/* 父传子:父组件通过自定义属性传递,子组件通过props接收。
如果子组件是函数定义,就使用props;
如果子组件是类定义,就使用this.props */}
<Hello d={appData} a={10}></Hello>
<First d={appData}></First>
9.React解决了什么问题?
组件化:这是react的核心
开发效率:react代码基本就是组件的组合,只用关心一个render函数,不用关心视图局部的修改
运行效率:react实现了虚拟dom,相比于其他框架具有更优的效率
可维护性:react基于flux或者redux的架构设计,确定的store很容易定位问题
10.React、vue、angular有什么区别?
答案:
开发者 数据绑定 依赖标准 渲染页面 模式
vue 尤雨溪 双向数据绑定 ES5/es6 模板+脚本+样式 MVVM
react FaceBook 单向数据绑定 es6 JSX 不是MVVM
angular 谷歌 双向数据绑定 typescript 模板 MVC(1)/MVVM(2…)
11.react diff 原理?
当你使用react的时候,在某个时间点render函数创建了一颗react元素树,在下一个state或者props更新的时候,react函数将创建一颗新的react树,react将对比两棵树的不同之处,计算出如何高效的更新UI(值更新变化的地方)
12.JSX是什么?浏览器怎么解析JSX?
JSX 将 HTML 语法直接加入到 JavaScript 代码中,再通过翻译器转换到纯 JavaScript 后由浏览器执行。
浏览器中通过给script标签添加type="text/bable"属性来解析jsx
13.props
1.函数定义的组件接收props用props. 如果该组件接收的props发生了发生了改变,会重新渲染。
2.类定义组件接收props用this.props。如果该组件props或者state发生了改变,会重新渲染。
3.在构造函数里面调用super(props)?
super() 目的是为了在constructor里面使用this
super(props) 目的是为了在constructor里面使用this.props
constructor(props){
//super() 目的是为了在constructor里面使用this
//super(props) 目的是为了在constructor里面使用this.props
super(props)
console.log(this.props)
}
14.state
1.只有类定义的组件才有state
2.setState()会触发render执行
3.取值
const {num,a}=this.state;
4.操作state里面的arr或者json,需要先取出,然后做你的逻辑操作,再通过setState赋值回去
changeName(name) {
var { json } = this.state;
json.name = name;
this.setState({
json
})
}
5.setState()是异步的,如果你想要操作后的值再进行操作,那么需要写到回调函数里面
6…render里面调用setState会陷入死循环,所以千万不要这样做。
7.setState会造成页面不必要的渲染,所以state里面的状态应该是页面使用的数据最小集合。
15.组件交互
注意:子组件接收父组件的值,子组件不能修改。
父传子
父组件通过自定义属性传递,子组件通过props接收.如果子组件是函数定义,就通过props,如果子组件是类定义,就通过this.props.
parent.js
<Child d={data}></Child>
Child.js (函数定义)
<div>{props.d}</div>
子传父
父组件通过自定义属性传递,子组件通过props接收。如果子组件是函数定义,就通过props,如果子组件是类定义,就通过this.props.
parent.js
<Child data={d} onChildClick={this.changeD.bind(this)}></Child>
<Child2 data={d} child2Click={(e)=>this.changeD(e)}></Child2>
Child.js 类定义
import React, { Component } from 'react'
export default class Child extends Component {
render() {
const { data,onChildClick } = this.props;
return (
<div className="box">
<h3>this is child</h3>
<p>父组件传递的数据:{this.props.data}</p>
<p>data:{data}</p>
<button onClick={this.props.onChildClick.bind(this,'child change')}>点击就修改父组件的d,改为”child change"</button>
<button onClick={()=>this.props.onChildClick('111')}>点击修改父组件d:'1111'</button>
<button onClick={()=>onChildClick('222')}>222</button>
</div>
)
}
}
Child2.js 函数定义
import React from 'react';
function Child2(props) {
const { data, child2Click } = props;
return (
<div className="box">
<h3>this is child 2</h3>
<p>data:{props.data}</p>
<p>data:{data}</p>
<button onClick={props.child2Click.bind(null, '333')}>333</button>
<button onClick={() => child2Click("444")}>444</button>
</div>
)
}
export default Child2;
注意:在子传父的自定义属性传参,父组件接收通过event.react中没有全局组件。
16.(组件的)状态(state)和属性(props)之间有何不同?
答案:state是一种数据结构,用于组件挂载时定义数据的默认值。修改state使用setState,会触发render函数执行,渲染页面。
props是由父组件传递给子组件的。对于子组件而言,props是不可变的。
17.类组件(Class component)和函数式组件(Functional component)之间有何不同?
答案:函数组件无state和生命周期,传值需要用props
类组件有state和生命周期,传值需要this.props
18.为什么建议传递给 setState 的参数是一个 callback 而不是一个对象?
答案:因为this.setState的更新是异步的。
19.(在构造函数中)调用 super(props) 的目的是什么?
答案:在super被调用之前,子类是不能使用this的,在ES5中,子类必须在constructor中调用super().
传递props给super()的原因则是便于子类能在constructor中访问this.props
20.ref
1.字符串
<div ref="box">123</div>
this.refs.box.offsetLeft
2.React.createRef()
constructor(){
super()
this.el=React.createRef()
}
<div ref={this.el}>45654</div>
aa(){
this.el.current.offsetLeft; //..
}
3.ref回调函数
//此回调函数回自动执行,currentNode参数为当前节点,每次更新(初始化不算)执行两次,第一次参数为null,第二次参数为当前节点,但这不影响任何
<input ref={(currentNode)=>{this.input1=currentNode}}/>
//获取值
this.input1.value
vue:
<div ref="div">
123
</div>
this.$refs.div.offsetLeft
//parent.vue
<Child ref="child"></Child>
this.$refs.child.aa()
//child.vue
export default{
methods:{
aa(){
}
}
}
场景:
1.处理焦点、文本选择或媒体控制
2.触发强制动画
3.集成第三方 DOM 库
注意,当组件挂载完毕,即componentDidMount,我们才能通过this.refs调用到以上元素.
21. 音频
audio.play();//播放
audio.pause();//暂停
audio.οntimeupdate=()=>{
audio.currentTime //当前播放时间 单位是s
audio.duration //歌曲总时长 单位是 s
}
audio.currentTime=100;//音频调到100s
audio.currentTime+=10;//快进10s
audio.muted=true|false;
audio.volume=0.5;//改变声音 [0,1]
22.react中使用stylus
1.安装依赖包
npm i stylus stylus-loader --save
2.npm run eject
如果成功了,那就恭喜你!
如果失败了,怎么解决?
1.先安装一个git,然后安装。官网 傻瓜式安装
2.如果你的电脑是mac,那么打开终端就可以了,进入你的项目文件夹;
如果你的电脑是windows,那么就在你的项目文件夹里面 右键->git hash here,点击它。
3.git add . //添加所有文件
如果问了你一句话:who you are?
git config --global user.name "hlt"
git config --global user.email '11@qq.com'
git add .
4.git commit -m "13243" //提交
5.再次执行 npm run eject
找到你的webpack配置文件(config/webpack.config.js),搜索"oneOf",
{
test: /\.styl$/,
use: [
require.resolve('style-loader'),
require.resolve('css-loader'),
require.resolve('stylus-loader')
]
},
23.react 生命周期函数?
1.类定义组件才有生命周期
3个阶段
初始期 :只执行一次
1.constructor 创建 初始化数据,也是初始化state的生命周期
2.componentWillMount 挂载之前 渲染之前可以修改你的数据
3.render 渲染 渲染dom节点,在更新的时候,做的是:进行diff算法,更新dom元素
4.componentDidMount 挂载完成 ajax 开启计时器 操作DOM节点
更新期: props或者state变了,都会进行更新 ,可以执行很多次
componentWillReceiveProps(nextProps)
接收的props发生了改变
shouldComponentUpdate (nextProps,nextState)
1.不书写这个生命周期,那么你的生命周期执行顺序:componentWillUpdate->render->componentDidUpdate
2.书写了这个生命周期
没有return ,那么就报错
return true,那么你的生命周期顺序:shouldComponentUpdate->componentWillUpdate- >render->componentDidUpdate
return false,那么你的生命周期执行顺序:shouldComponentUpdate
componentWillUpdate 将要更新
render 渲染 进行diff算法,更新dom元素
componentDidUpdate 更新完成
销毁期
componentWillUnmount 销毁之前 做善后工作
如果开启过计时器,订阅,异步请求 都要取消,否则就会报错。
24.shouldComponentUpdate 是做什么的?
第一个 不存在 数据正常更新 。
第二个 存在 数据被拦截
按照你自己的需求去返回true 或者false,这个函数存在必须要返回相关的布尔值, 否则报错 。
①如果是true的时候
生命周期的顺序是
shouldComponentUpdate是否要更新-》componentWillUpdate将要更新=》 render渲染-》componentDidUpdate更新
②如果是false 就结束了
只走了shouldComponentUpdate-----是否要更新
25.为什么虚拟 dom 会提高性能?
虚拟DOM其实就是一个JavaScript对象。通过这个JavaScript对象来描述真实DOM。
为什么用虚拟dom?真实DOM的操作,一般都会对某块元素的整体重新渲染。
采用虚拟DOM的话,当数据变化的时候,只需要局部刷新变化的位置就好了。
26.应该在 React 组件的何处发起 Ajax 请求?
componentDidMount
27.在 React 中,refs 的作用是什么?
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。
我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,
该值会作为回调函数的第一个参数返回。
用于对 render() 返回的特定元素或组件的引用。
当需要进行 DOM 测量或向组件添加方法时,它们会派上用场。
28.使用箭头函数(arrow functions)的优点是什么?
作用域安全:在箭头函数之前,每一个新创建的函数都有定义自身的 this 值,但箭头函数不会,它会使用封闭执行上下文的 this 值。
简单:箭头函数易于阅读和书写
清晰:当一切都是一个箭头函数,任何常规函数都可以立即用于定义作用域。
29.路由
1.基础路由
npm i react-router-dom --save
引入 index.js
// 1. 引入路由模式 BrowserRouter |HashRouter
import {BrowserRouter} from "react-router-dom"
//2.嵌套根组件
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
路由出口 (router-view)
import React, { Component } from 'react'
import {Switch,Route} from "react-router-dom"
import Login from "./pages/Login/Login"
import Index from "./pages/Index/index"
export default class App extends Component {
render() {
return (
<div>
<Switch>
<Route path="/login" component={Login}></Route>
<Route path="/index" component={Index}></Route>
</Switch>
</div>
)
}
}
路由跳转(router-link [active-class])
import {Link,NavLink} from "react-router-dom"
<Link to="/index">首页</Link>
<NavLink to="/index">首页2</NavLink>
<NavLink activeClassName="select" to="/index/man">男装</NavLink>
<NavLink activeClassName="select" to="/index/women">女装</NavLink>
<NavLink activeClassName="select" to="/index/child">童装</NavLink>
路由基本配置规则 ({path:"/login",component:login})
<Route path="/login" component={Login}></Route>
路由重定向 (redirect)
import {Switch,Route,Redirect} from "react-router-dom"
<Switch>
<Route path="/login" component={Login}></Route>
<Route path="/index" component={Index}></Route>
<Redirect to="/login"></Redirect>
</Switch>
如果你使用路由的时候,报了Redirect的错误,建议你把node_modules删掉,在cmd里面安装 npm i
2.嵌套路由
<Switch>
<Route path="/index/man" component={Man}></Route>
<Route path="/index/women" component={Women}></Route>
<Route path="/index/child" component={Child}></Route>
</Switch>
3.编程式导航
vue
this.$router.push()
this.$router.replace()
this.$router.go(-1)
react
this.props.history.push("/movie") //添加一条新的历史记录
this.props.history.replace("/food")//替换当前历史记录
this.props.history.go(-1)//返回
使用前提是:该组件是参与路由的组件,就可以直接使用上面的编程式导航。
如果某个组件不是参与路由的组件,那么你需要引入withRouter方法解决。
import React, { Component } from 'react'
import {withRouter} from "react-router-dom"
class Back extends Component {
goBack(){
this.props.history.go(-1)
}
render() {
return (
<button onClick={this.goBack.bind(this)}>封装的返回组件</button>
)
}
}
export default withRouter(Back)
4.传参
vue
? this.$route.query
: this.$route.params
react
如果是通过? 传参 ,参数在 this.props.location.search ,需要自己手动解析为键值对
第一种方式:
var str=this.props.location.search.slice(1);//'foodId=22&a=10&b=20'
var arr=str.split("&");//["foodId=22", "a=10", "b=20"]
var json={};
arr.forEach(item=>{
var tempArr=item.split("=");//["foodId","22"]
json[tempArr[0]]=tempArr[1]
})
console.log(json)//做你的逻辑操作
第二种方式:
import querystring from "querystring"
var json=querystring.parse(this.props.location.search.slice(1))
如果通过 动态路由 传参 ,那么参数在this.props.match.params
30.路由拦截
在登录成功的时候,做一个标识。
//存一个标识,用来做登录拦截判断
localStorage.setItem("name",user.name)
定义了一个组件,MyRoute ,哪些组件需要做登录拦截,就用MyRoute定义他的路由规则
<MyRoute path="/movie" component={Movie}></MyRoute>
<MyRoute path="/movie-detail/:id" component={MovieDetail}></MyRoute>
<MyRoute path="/food" component={Food}></MyRoute>
<MyRoute path="/food-detail" component={FoodDetail}></MyRoute>
MyRoute组件内容
import React, { Component } from 'react'
import Login from "../Login/Login"
import {Route} from "react-router-dom"
export default class MyRoute extends Component {
componentWillMount(){
this.name=localStorage.getItem("name");//如果没有登录,name-null 如果登陆了,name-admin
}
render() {
return (
<div>
{
this.name?<Route {...this.props}></Route>:<Login></Login>
}
</div>
)
}
}
Login.js 用withRouter调用。
31.懒加载
Util/asyncComponent.js
import React,{Component} from "react"
function asyncComponent(fn){
class AsyncComponent extends Component {
constructor(){
super();
this.state={
c:null
}
}
componentDidMount(){
fn().then(mod=>{
this.setState({
c:mod.default
})
})
}
render(){
var C=this.state.c;
return (
<div>
{
this.state.c?<C></C>:null
}
</div>
)
}
}
return AsyncComponent;
}
export default asyncComponent;
注意:带有参数组件 不要用
32.为什么需要react中的路由
答案:Router 用于定义多个路由,当用户定义特定的 URL 时,
如果此 URL 与 Router 内定义的任何 “路由” 的路径匹配,
则用户将重定向到该特定路由。所以基本上我们需要在自己的应用中添加一个 Router 库,
允许创建多个路由,每个路由都会向我们提供一个独特的视图
33.react router和常规路由有何不同?
答案:
参与的页面:
reactRouter:只涉及单个HTML页面;
常规路由:每个视图对应一个新文件。
URL更改:
reactRouter:仅更改历史记录属性
常规路由:http请求被发送到服务器并且接收相应的html页面
体验:
reactRouter:用户认为自己正在不同的页面间切换
常规路由:用户实际在每个视图的不同页面切换
34.axios
安装
npm i axios --save
配置代理(记得重启)
//package.json
{
"proxy":"http://localhost:3000"
}
发起数据请求
//get
axios({
url:'url',
method:"get",
params:{}
}).then(res=>{})
//post
axios({
url:"url",
method:"post",
data:{}
}).then(res=>{})
如果上班post传参,后端收不到,那么就使用qs模块。
npm i qs --save
import qs from "qs"
axios({
url:"url",
method:"post",
data:qs.stringify({})
}).then(res=>{})
拦截
//请求拦截
axios.interceptors.request.use(config=>{
console.log(config);
config.token="12244353545645643545756"
return config;
})
//响应拦截
axios.interceptors.response.use(res=>{
console.log(res);
return res;
})
35.antd?是什么?如何安装和使用?
antd是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。
安装:npm install antd --save
使用:import { DatePicker } from ‘antd’;
36.当你调用setState的时候,发生了什么事?
当调用 setState 时,React会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态。这将启动一个称为和解的过程。和解的最终目标是以最有效的方式,根据这个新的状态来更新UI。 为此,React将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)。
一旦有了这个树,为了弄清 UI 如何响应新的状态而改变,React 会将这个新树与上一个元素树相比较( diff )。
通过这样做, React 将会知道发生的确切变化,并且通过了解发生什么变化,只需在绝对必要的情况下进行更新即可最小化 UI 的占用空间。
37.在 React 当中 Element 和 Component 有何区别?
一个 React element 描述了你想在屏幕上看到什么。换个说法就是,一个 React element 是一些 UI 的对象表示。
一个 React Component 是一个函数或一个类,它可以接受输入并返回一个 React element
38.React中路由有哪些常用组件?说明它们的作用?
BrowserRouter,在需要使用路由的页面中引入;
Switch,路由选择器
Route,路由配置规则
Redirect,路由重定向
Link,路由导航
NavLink,带activeClass的路由导航
39.redux(一部分,需详细学习)
Redux 是 JavaScript 状态容器,提供可预测化的状态管理.
.1.单一数据源
整个应用状态,都应该被存储在单一store的对象树中。
2.只读状态
唯一可以修改状态的方式,就是发送(dispatch)一个动作(Action),通俗来讲,就是说只有getter,没有setter。
3.使用纯函数去修改状态,
组件 ————》react-redux《——————redux---- ———》Redux-thunk《—————————后台
Redux state 状态
reducer(action) 修改状态 (约定 注册任务)
dispatch(action) 派发任务 同步
Redux-thunk 中间件 异步操作
1.安装redux react-redux
npm i redux react-redux --save
2.创建仓库 store/index.js
//1.安装 npm i redux --save
import {createStore} from "redux"
//2.初始化数据 state
const initialState = {
name: "妲己",
age: 20,
num:1,//数字
}
//action creator
//修改name的action
export const changeNameAction=(name)=>({
type:"changeName",
username:name
})
//num++ action
export const addAction=()=>({
type:"add"
})
//num-- action
export const subAction=()=>({
type:"sub"
})
//3.reducer 注册任务 action={type:"动作名称",}
//注意:reducer return的内容是下一次的状态。
function reducer(state = initialState, action) {
switch (action.type) {
case "changeName":
//{type:"changeName",name:"王昭君"}
return {
...state,
name: action.username
}
case "add":
//{type:"add"}
return {
...state,
num:state.num+1
}
case "sub":
//{type:"sub"}
return {
...state,
num:state.num-1
}
default:
return state;
}
}
//4.创建仓库
const store=createStore(reducer);
//5.reselect---getters
//导出name
export var getName=()=>store.getState().name;
//导出age
export var getAge=()=>store.getState().age;
//导出num
export var getNum=()=>store.getState().num;
//6.导出
export default store;
3.使用react-redux 关联react 和redux
入口文件 index.js
import {Provider} from "react-redux"
import store from "./store"
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
4.将需要状态管理层数据的组件改写为容器型组件
import {connect} from "react-redux"
class A extends Component{
render(){
const {name,changeName}=this.props;
return (
<div></div>
)
}
}
const mapStateToProps=()=>{
return {
name:getName(),
//...
}
}
const mapDispatchToProps=(dispatch)=>{
return {
changeName:(name)=>dispatch(changeNameAction(name)),
//...
}
}
export default connect(mapStateToProps,mapDispatchToProps)(A)