React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。
state
和 props
两个主要的属性我们可以通过 【JSX 表达式】处理数据和 DOM 之间的关系,而不需要操作 DOM
React 中采用虚拟 DOM 的机制;
1)在 React 中,我们会把定义好的JSX 标记最终转换为一个虚拟的 DOM,存在内存里
2)如果用户做了对DOM 可能产生影响的操作的时候,虚拟DOM 会把操作前后的数据进行对比,如果操作前后的数据有变化,就会把所有的变动然后统一操作一次 DOM ,如果发现操作前后的数据没有差异的话,就不会再去操作 DOM了;
3)虚拟DOM 有两大优势
1】一个是操作 DOM 前对数据进行对比,只有数据变化的时候才去操作DOM
2】它会整合 DOM 操作,可以减少 DOM 操作,提升性能
1).声明式设计:React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据变动时 React能高效更新并渲染合适的组件。
2)组件化: 构建管理自身状态的封装组件,然后对其组合以构成复杂的 UI。
3)高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。
4)灵活:无论你现在使用什么技术栈,在无需重写现有代码的前提下,通过引入React来开发新功能。
可以从以下三个方面理解 JSX:
1)JSX 是一种 JS 扩展的表达式
2)JSX 是带有逻辑的标记语法,有别于 HTML 模版
3)并且支持样式、逻辑表达式和事件
jsx语法规则:
1.定义虚拟DOM时,不要写引号。
2.标签中混入JS表达式时要用{}。
3.样式的类名指定不要用class,要用className。
4.内联样式,要用style={{key:value}}的形式去写。
5.只有一个根标签
6.标签必须闭合
7.标签首字母
(1).若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
(2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
const myId = 'aTgUiGu'
const myData = 'HeLlo,rEaCt'
//1.创建虚拟DOM
const VDOM = (
{myData.toLowerCase()}
{myData.toLowerCase()}
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
1.(1)面向过程 —— function式组件 —— rfc(函数组件又叫做 无状态组件
)
//1.创建函数式组件
function MyComponent(){
console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式
return 我是用函数定义的组件(适用于【简单组件】的定义)
}
//2.渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
/*
执行了ReactDOM.render( .......之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
*/
(2)面向对象 —— class式组件 —— rcc(类组件又叫做 有状态组件
)
class MyComponent extends React.Component {
render(){
//render是放在哪里的?—— MyComponent的原型对象上,供实例使用。
//render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。
console.log('render中的this:',this);
return 我是用类定义的组件(适用于【复杂组件】的定义)
}
}
//2.渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
/*
执行了ReactDOM.render( .......之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
*/
2、class组件中this指向undefined问题
情形:①class组件中 ②事件处理方法中的this指向undefined
原因:①按钮单击触发,this不指向class对象
②JSX被编译为虚拟DOM对象,没有“事件源”概念
③JSX被编译为“严格模式”下的执行代码,事件处理函数为全局函数——严格模式下全局对象不是window而是undefined
解决方案:
方案1:利用 箭头函数
形式的 class实例
方法
f1 = ()=>{ }
方案2:利用箭头函数自身不绑定 this
的特点
onClick={ ()=>this.f1( ) }
方案3:利用 ES5
中的 bind()
方法,将事件处理程序中的 this 与组件实例绑定到一起
onClick={ this.f1.bind( this ) }
state有两个基本功能:
1)能够存储一定的值,从而能被react使用;
2)能够再它改变的时候被React监听到并且重新渲染
类组件
class Weather extends React.Component{
//初始化状态
state = {
isHot:false,
wind:'微风'
}
render(){
const {isHot,wind} = this.state
return
今天天气很{isHot ? '炎热' : '凉爽'}{wind}
}
}
不要直接修改 state 中的值,这是错误的!!!
修改state
2. 更新UI
//1.创建组件
class Weather extends React.Component{
//初始化状态
state = {isHot:false,wind:'微风'}
render(){
const {isHot,wind} = this.state
return 今天天气很{isHot ? '炎热' : '凉爽'},{wind}
}
//自定义方法————要用赋值语句的形式+箭头函数
changeWeather = ()=>{
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
}
//2.渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
函数组件
这里的setData的作用跟setState类似,但是它只能用来改变data的状态,需要改变的时候传入一个回调函数。函数的参数是之前的值,返回一个要改变的值。这个方法本质是需要传入一个新的对象,来改变React之前对象的值。
import {useState} from "react"
function FunctionComponent(){
const [data,setData] = useState("你要传入的初始值")
return (
展示数据 {state}
)
}
props功能在于组件间通信(父子组件传参)
注意:所有 React 组件都必须像纯函数一样保护它们的 props 不被更改,是只读的
类组件(父传子)
//父组件传值
class Father extends React.PureComponent{
render(){
return (
)
}
}
class Son extends React.PureComponent{
render(){
return (
this data is {this.props.value}
)
}
}
类组件(子传父)
//子组件给父组件传值,此时往往需要父组件给子组件先传一个props函数,
//子组件通过调用传入的函数传值改变父组件的值
export default class Fa extends Component {
state = {faValue:'Fa1'}
changeFa = (value)=>{
this.setState(()=>{
return {faValue:value}
})
}
render() {
return (
<>
Fa's value is {this.state.faValue}
>
)
}
}
export default class Son extends React.PureComponent{
changeValue = ()=>{
this.props.changeFa(this.inputRef.value)
}
render() {
return (
<>
{this.inputRef = el}}/>
>
)
}
}
函数组件(父传子)
function Fa(){
return (
)
}
function Son(props){
return (
this data is {props.value}
)
}
函数组件(子传父)
function Fa(){
const [faValue,setFaValue] = useState("Fa1")
const changeFa = (value)=>{
setFaValue(value)
}
return (
Fa's value is {faValue}
)
}
function Son(props){
const inputValue = useRef("")
//定义改变fa组件的值的函数
const changeFaValue = ()=>{
props.changeFa(inputValue.current.value)
}
return (
<>
>
)
}
ref是一个对象,它有一个current属性,可以对这个属性进行操作,用于获取DOM元素和保存变化的值。比如setTimeout的返回的ID,就可以把这个值放到ref中。为什么要放到ref中,因为更改ref的值,不会引起组件的重新渲染,因为值与渲染无关,它也不应该引起组件渲染。
怎么获取ref对象呢?调用useRef()函数和createRef()函数,它们返回ref对象。在组件的整个生命周期中,ref对象一直存在。
字符串形式
class Demo extends React.Component{
//展示左侧输入框的数据
showData = ()=>{
const {input1} = this.refs
alert(input1.value)
}
//展示右侧输入框的数据
showData2 = ()=>{
const {input2} = this.refs
alert(input2.value)
}
render(){
return(
)
}
}
//渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
回调引用
//创建组件
class Demo extends React.Component{
//展示左侧输入框的数据
showData = ()=>{
const {input1} = this
alert(input1.value)
}
//展示右侧输入框的数据
showData2 = ()=>{
const {input2} = this
alert(input2.value)
}
render(){
return(
this.input1 = c } type="text" placeholder="点击按钮提示数据"/>
this.input2 = c } type="text" placeholder="失去焦点提示数据"/>
)
}
}
//渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
使用useRef()
//组件挂载后,ref对象的current属性,就自动指向DOM元素
import React, { useRef } from "react";
const CustomTextInput = () => {
const textInput = useRef();
const focusTextInput = () => textInput.current.focus();
return (
<>
>
);
}
useRef是一个React Hooks,在函数组件中使用,它还可以接受一个参数,用于初始化useRef返回的对象的current属性。(const ref = useRef(initialValue);)
import React, { useRef } from "react";
const RenderCounter = () => {
const counter = useRef(0);
useEffect(() => {
counter.current = counter.current + 1;
});
return (
{`The component has been re-rendered ${counter} times`}
);
};
使用React.createRef()【类组件写法】
//创建组件
class Demo extends React.Component{
/*
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的
*/
myRef = React.createRef()
myRef2 = React.createRef()
//展示左侧输入框的数据
showData = ()=>{
alert(this.myRef.current.value);
}
//展示右侧输入框的数据
showData2 = ()=>{
alert(this.myRef2.current.value);
}
render(){
return(
)
}
}
//渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
使用React.createRef()【函数组件写法】
function CustomTextInput(props) {
// textInput必须在此处声明,以便ref可以引用它
let textInput = React.createRef();
function handleClick() {
textInput.current.focus();
}
return (
);
}
//创建组件
class Demo extends React.Component{
/*
(1).通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件, 而不是使用的原生DOM事件 —————— 为了更好的兼容性
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) ————————为了的高效
(2).通过event.target得到发生事件的DOM元素对象 ——————————不要过度使用ref
*/
//创建ref容器
myRef = React.createRef()
myRef2 = React.createRef()
//展示左侧输入框的数据
showData = (event)=>{
console.log(event.target);
alert(this.myRef.current.value);
}
//展示右侧输入框的数据
showData2 = (event)=>{
alert(event.target.value);
}
render(){
return(
)
}
}
//渲染组件到页面
ReactDOM.render( ,document.getElementById('test'))
1.受控组件中输入框的值由其change事件接管,做对应的数据劫持操作,例如可以对输入框的值进行合法输入校验(匹配正则),此时表单数据由 React 组件来管理(“受开发者控制”)。
import axios from "axios";
import React, { useState, useEffect } from "react";
function ControlledComponent() {
//创建一个state值绑定在输入框的value上;
const [userName, setUsername] = useState("小明");
//数据组装提交到后台
function doSumbit() {
const data = {
name: userName,
};
console.log(data)
axios("xxx", data);
}
useEffect(() => {
console.log(userName);
}, [userName]);
return (
<>
//输入框绑定change事件传入事件e
//change事件中得到输入框的值然后赋值改变state值
{setUsername(e.target.value);} }>
>
);
}
export default ControlledComponent;
2.非受控组件则是同过ref直接获取输入框的值,只获取到最后状态的结果值,在输入过程中做不到对输入值的操作,此时表单数据将交由 DOM 节点来处理(“不受开发者控制”)。
import axios from "axios";
import React, { useRef } from "react";
function NotControlledComponent() {
const inputRef = useRef();
//通过ref.current.value获取输入框的值进行数据组装提交到后台
function doSumbit() {
const data = {
name: inputRef.current.value,
};
axios("xxx", data);
}
return (
<>
//创建一个ref实例绑定到输入框的ref上
>
);
}
export default NotControlledComponent;
1.先订阅,再发布(理解:隔空对话的感觉)
安装第三方库pubsub-jsnpm add pubsub-js
利用钩子函数componentDidMount在组件挂载subscribe()函数进行订阅消息。import PubSub from 'pubsub-js' //引入
//订阅 subscribe()
componentDidMount(){
this.token = PubSub.subscribe('usersData',(_,data) => {
console.log('订阅消息:',data)
this.setState({...data})
})
}
//发布消息 publish()
PubSub.publish('usersData',{isFirst:false,isLoading:true})
//发送网络请求
axios.get(`https://api.github.com/search/users?q=${keyWord}`).then(
response => {
// this.props.UpdateAppState({isLoading:false,users:response.data.items})
PubSub.publish('usersData',{isLoading:false,users:response.data.items})
},
error => {
//this.props.UpdateAppState({isLoading:false,err:error.message})}
PubSub.publish('usersData',{isLoading:false,err:error.message})
}
)
2.适用于任意组件间通信
3. 要在组件的componentWillUnMount中取消订阅
//取消订阅 unsubscribe()
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
注意:React中没有“指令”的概念,即无v-on、v-if、v-for、v-model.... |
①内容绑定:
{表达式} ②属性绑定:
属性名={表达式}/> ③样式绑定:
style={ {color:'red'} }/> ④事件绑定:
onClick={表达式}/> ⑤双向数据绑定:
value={表达式} onChange={e=>setXxx(e.target.value)}/>
⑥条件渲染:
{ 判定表达式 && (JSX) } 等价于 if( ){ return (JSX) }
{ 判定表达式 ? (JSX1) : (JSX2) } 等价于 if( ){ return (JSX1) }else {return (JSX2)}⑦列表渲染:
{ arr.map( (e,i)=>(JSX) ) }
v6 版本相比v5使用上发生了一些改变:
- v6版本移除了之前的
,引入了新的替代者
和
配合使用,且必须用
包裹
,当
url
发生变化时会查看其所有子
元素找到最佳匹配并呈现组件
属性用于指定:匹配时是否区分大小写(默认为
false
)
component 改为
element
- 路由重定向
Navigate
,代替之前的Redirect
}/>
与
类似,但增加了一个点击之后导航高亮的效果 ,它有一个默认的类名
active
,通过这个类名可以修改高亮的颜色
install i react-router-dom
标签进行跳转import { BrowserRouter,Link,Route, Routes} from "react-router-dom";
// link相当于 跳转标签,
// Route相当于容器
const Home=()=>{
return(
Home
)
}
const About=()=>About
const Main=()=>main
export default function Basic(){
return (
{/* // 如果项目需要路由,需要这个组件将项目包裹,只有在内部才能使用 */}
-
home
-
about
-
main
{/* 使用component组件渲染对应的组件 */}
{/* // react是包容性路由,满足条件都渲染,使用 exact精准匹配 */}
} exact>
}>
}>
)
}
Outlet
,useRoutes()
Route
可以嵌套使用,且可以配合useRoutes
配置路由表,通过
来渲染匹配到的子路由
//一般的嵌套写法
}>
} />
} />
//使用使用useRoutes()写法
const element = useRoutes([
{
path: '/',
element:
},
{
path: '/home',
element: ,
children: [
{
path: 'news',
element:
},
{
path: 'message',
element:
}
]
}
])
//Home文件
news
message
//渲染路由规则匹配到的组件
常见的组件路由传递参数的方式有三种,分别是通过params参数传递、利用search属性传递、利用state属性传递
一般来说,我们会使用类似于/${id}
的方式来传递值
xxx
虽然传递了多个参数,但是我们并不知道每个参数对应的key是什么,所以需要先规定好每个参数对应的key。
然后在目标组件中使用this.props.match
来获取传递的参数
export default class Details extends Component {
state = {
details: [
{id:'01',comment:'你好,我的祖国'}
...
]
}
render() {
const {details} = this.state;
const {params} = this.props.match;
const detailofMessage = details.find((detailObj)=>{
return detailObj.id === params.id
})
return (
- ID: {detailofMessage.id}
- Title: {params.title}
- Comment: {detailofMessage.comment}
)
}
}
上面是类组件方式,下面为函数组件
//在路由的path上配置:id
{
path: 'news/:id',
element:
},
//传递
news
//获取
function HomeNews() {
console.log(useParams());//{id: '1', title: '消息'}
const {id,title} = useParams()//获取url里携带的params参数
return (
{id}{title}
)
}
种方式基本上和我们常见的在url地址上进行参数拼接是一样的,这种方式写法较为简单,只需要在 Link 标签中定义好key=value形式参数拼接,然后在实际的组件中,直接从prop属性中获取,调用querystring(或者其他处理字符串转对象的函数库)处理参数,并封装成对象返回即可
xxx
这种方式下的传参并不需要额外对路由进行配置
然后在实际组件中获取传递的参数(props.location.search
属性中把我们步骤一的参数都封装了进去,但是这种方式封装的参数是字符串形式的,我们并不能直接使用,而是要借助queryString
库来帮助我们把字符串解析成对象。)
import React, { Component } from 'react'
// querystring 是脚手架初始化的时候自带的函数库,能帮助我们分解和生成key=value形式的对象
import qs from 'querystring'
export default class Details extends Component {
state = {
details: [
{id:'01',comment:'你好,我的祖国'}
...
]
}
render() {
console.log('this.props',this.props)
const {details} = this.state;
const {search} = this.props.location;
// parse能将字符串转为key:value形式的对象
const messageObj = qs.parse(search.slice(1));
const detailofMessage = details.find((detailObj)=>{
return detailObj.id === messageObj.id
})
return (
- ID: {detailofMessage.id}
- Title: {messageObj.title}
- Comment: {detailofMessage.comment}
)
}
}
上面是类组件方式,下面为函数组件
//传递search参数
news
//接受search参数
function HomeNews() {
const [search,setsearch] = useSearchParams()//返回search参数 和 更新search参数的函数
const id = search.get('id')//通过get方法获取
const title = search.get('title')
console.log(useSearchParams());//[URLSearchParams, ƒ]
return (
{id}{title}
)
}
这种方式传递的参数是不会在浏览器中显式的展示的,同时,即使刷新页面,路由子页面的数据还是不会消失。原因是react路由器帮我们对维护了history对象(history对象中又维护了location对象,所以也就有了state对象)
xxx
这种方式下的传参也不需要额外对路由进行配置
然后在具体组件中获取传递的参数
export default class Details extends Component {
state = {
details: [
{id:'01',comment:'你好,我的祖国'}
...
]
}
render() {
const {details} = this.state;
const {id,title} = this.props.location.state;
const detailofMessage = details.find((detailObj)=>{
return detailObj.id === id
})
return (
- ID: {detailofMessage.id}
- Title: {title}
- Comment: {detailofMessage.comment}
)
}
}
上面是类组件方式,下面为函数组件
//传递state参数
news
//接受state参数
function HomeNews() {
const { state:{id,title}} = useLocation()//连续解构赋值
return (
{id}{title}
)
}
useNavigate
代替v5中的this.props.history
默认是push
模式
export default function HomeNews() {
const navigate = useNavigate();
const jump = ()=>{
navigate('/home')
}
return (
)
}
使用{replace:true}
就会变为replace
模式
navigate('/home', { replace: true });
也可以使用 navigate(-1)
传入一个数字来进行跳转
navigate(1)//传入数字
1.底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。
2.path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
HashRouter的路径包含#,例如:localhost:3000/#/demo/test
3.刷新后对路由state参数的影响
(1).BrowserRouter没有任何影响,因为state保存在history对象中。
(2).HashRouter刷新后会导致路由state参数的丢失!!!
4.备注:HashRouter可以用于解决一些路径错误相关的问题。
Hook 不能在 class 组件中使用 !!!只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。只能在React 的函数组件或自定义的 Hook中调用 Hook
用于定义变量和相关的更新变量的函数(将state按照相关性进行划分,这样有利于独立出自定义hook)
1: import React, { useState } from 'react';
2:
3: function Example() {
4: const [count, setCount] = useState(初始值);
5:
6: return (
7:
8: You clicked {count} times
9:
12:
13: );
14: }
相当于 componentDidMount 和 componentDidUpdate、componentWillUnmount
a.如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([]
)作为第二个参数。这就告诉 React 你的 effect 不依赖于 props 或 state 中的任何值。
useEffect(() => {
getList(current)
}, [])
b.采用传递第二个参数,判断是否需要重新执行
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新
c.组件即将挂载
useEffect( ()=>{
return ()=>{
//生命周期方法4 = 任意状态数据发生改变 + 组件即将卸载
}
} )
useRef
const refContainer = useRef(initialValue);
useRef
返回一个可变的 ref 对象,其 .current
属性被初始化为传入的参数(initialValue
)。返回的 ref 对象在组件的整个生命周期内保持不变。一个常见的用例便是命令式地访问子组件:
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
>
);
}
useRef
会在每次渲染时返回同一个 ref 对象,类似于class组件的this,可用于保存变量
function Timer() {
const intervalRef = useRef();
useEffect(() => {
const id = setInterval(() => {
// ...
});
intervalRef.current = id;
return () => {
clearInterval(intervalRef.current);
};
});
// ...
}
React小知识:在JSX里如何创建一个不生成任何HTML元素的父元素? Vue.js中: 方法① 、 方法② React中: 方法① <>> 方法② |
安装
npm install -save redux
1. Action 的作用就是告诉状态管理器需要做什么样的操作
const add =()=>{
return {
type:"add",
data:id,
}
}
2.Reducer
这是一个确定状态将如何变化,以及更新状态的地方。
Reducer 是一个纯函数,接受 旧 state 和 action,根据不同的 Action 做出不同的操作,并返回新的 state 。即:(state, action) => state
/*
1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
const initState = 0 //初始化状态
export default function countReducer(preState=initState,action){
// console.log(preState);
//从action对象中获取:type、data
const {type,data} = action
//根据type决定如何加工数据
switch (type) {
case INCREMENT: //如果是加
return preState + data
case DECREMENT: //若果是减
return preState - data
default:
return preState
}
}
3.Store
– 整个程序的状态state保存在Store中。
//import { createStore } from 'redux';
//const store = createStore(reducer);
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore} from 'redux'
//引入为Count组件服务的reducer
import countReducer from './count_reducer'
//暴露store
export default createStore(countReducer)
这就是 store, 用来管理 state 的单一对象,其中有三个方法:
1、store.getState(): 获取state ,如上,经过 reducer 返回了一个新的 state,可以用该函数获取。
2、store.dispatch(action) :发出 action,用于触发 reducer,更新 state,import { createStore } from 'redux'; const store = createStore(fn); const action = { type: 'change_input', value: 'Learn Redux', }; store.dispatch(action);
3、store.subscribe(listener):监听变化,当 state 发生变化时,就可以在这个函数的回调中监听。import { Component} from 'react'; import store from './store/index'; class List extends Component { constructor(props) { super(props); store.subscribe(this.storeChange.bind(this)); // store发生改变时,自动触发storeChange方法 } render() { return ( // .... ); } storeChange() { // store发生改变时,将自动触发 let newState = store.getState(); // 得到当前state状态,包含所有store属性 this.setState(newState); // 重新渲染 View } } export default List;
store.subscribe
方法返回一个函数,调用这个函数就可以解除监听。let unsubscribe = store.subscribe(() => console.log(store.getState()) ); unsubscribe(); // 解除监听
redux-thunk中间件的使用方法:
链接地址
connect用法(
连接 React 组件与 Redux Store)
导入:
import { connect } from 'react-redux'
使用:
connect( mapStateToProps , mapDispatchToProps )()
mapStateToProps
/*定义该参数后,组件就可以监听 Redux Store 的变化,任何时候只要store发生变化,
该函数就会被调用;
该函数必须返回一个纯对象,它会与组件的 props 结合,
而第二个参数 ownProps 被指定时,它代表传递到该组件的props,
且只要组件收到新的 props ,mapStateToProps 就被调用*/
const mapStateToProps = (state, ownProps) => {
return {
value: state.count //UI组件中需要什么参数,对象中就写哪些参数
}
}
mapDispatchToProps
/*如果mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数。作为函数,应该返回一个对象,该对象的每个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action*/
const mapDispatchToProps = (dispatch, ownProps) => {
return {
onIncreaseClick: () => dispatch({type: 'increase'}),
onReduceClick: () => dispatch({type: 'reduce'})
}
}