React 页面间传值的个人总结
react 组件之间传值的方案有很多,下面是我个人经验的总结
github 地址
props 来传递值
传值方式:
- 通过props 获取值
- 通过props 提供的func去修改值
优点:
- 不需要任何第三方的组件,纯react,非常纯哦
缺点:
- 代码调试有些麻烦,但是可以react 插件辅助查看到当前react 对象的props
注意事项:
一般在表单页面中用到组件时候会用到props 传递值,需要注意下,最好页面的状态控制都在该页面的顶级节点的state 的,不要尝试获取或控制子节点的state,所以组件内部state是父级节点不关心的
Demo 代码如下:
import React,{Component} from 'react';
import PropTypes from 'prop-types'
class ChildNode extends Component{
static PropTypes={
value:PropTypes.string.isRequired,
onChange:PropTypes.func.isRequired
}
render(){
const {value,onChange} = this.props;
return (
<div>
<span>这里是子节点值:{value}</span><br/>
<input type="text" value={value} onChange={(e)=>{
console.log('开始更改值')
onChange(e.target.value)
}}/>
</div>
)
}
}
class Parent extends Component{
state={
childValue:'this is the value of the child node'
}
onChildValueChange=(val)=>{//注意这里用ES6 的array function 来绑定当前的this
this.setState({childValue:val})
}
render(){
const {childValue} = this.state;
return (
<div>
<span>这里是父节点</span>
<div>
<span>父节点控制子节点的内容</span>
<button onClick={()=>{
let childValue = this.state.childValue||""
this.setState({
childValue:childValue+'我最帅!'
})
}}>内容直接加上我最帅</button>
</div>
<br/>
<br/>
<ChildNode value={childValue} onChange={this.onChildValueChange}/>
</div>
)
}
}
export default Parent;
Redux
这里使用redux-react 来连接 react 和 redux。
传递方式:
获取值:通过redux-react connect()
传递值:通过dispatch 具体的action
优点:
- 可以通过redux-logger 组件来查看数据的变化过程,可以容易的调试复杂的业务逻辑
- 全局的数据都可以获取到以及修改
缺点:
- 因为业务独立逻辑代码独立到action、reducer里面,需要增加code的代码量以及单独action、reducer文件的分割。
可以借助文件夹名称的约定和第三方组件来弥补上面的缺点
注意事项
通过connect 传递过来的props 值不能修改哦。只读的!
Demo 代码如下:
import React,{Component} from 'react'
import {createStore,combineReducers} from 'redux'
import { Provider,connect } from 'react-redux'
/**
* reducer 用来描述state 是怎样改变的
* @param state
* @param action
* @returns {number}
*/
function reducerOne(state=0,action){
switch (action.type) {
case 'reducerOne/INCREMENT':
return state + 1
case 'reducerOne/DECREMENT':
return state - 1
default:
return state
}
}
const store = createStore(combineReducers({reducerOne}))
class ReduxNodeOne extends Component{
render(){
return (
<div>
<h6>节点一</h6>
<button onClick={()=>{
this.props.increment()
}}>加1</button>
<button onClick={()=>{
this.props.decrement()
}}>减1</button>
</div>
)
}
}
class ReduxNodeTwo extends Component {
render(){
return (
<div>
<h6>节点二</h6>
<span>Counter:{this.props.counter}</span>
</div>
)
}
}
const ConnectedReduxNodeTwo = connect(({reducerOne})=>{
return {
counter:reducerOne
}
})(ReduxNodeTwo)
const ConnectedReduxNodeOne= connect(null,{
increment:function(){
return {
type:'reducerOne/INCREMENT'
}
},
decrement:function(){
return {
type:'reducerOne/DECREMENT'
}
}
})(ReduxNodeOne)
export default function(){
return (
<Provider store={store}>
<div>
<h1>Redux Simple Demo</h1>
<ConnectedReduxNodeOne />
<ConnectedReduxNodeTwo/>
</div>
</Provider>
)
};
context
纯react 页面的时候,如果数据的传递要通过多层react 对象的时候,你可以考虑context 传递值哦。
传递方法:
获取值:子组件内定义static contextTypes={ name:PropTypes.string.isRequired, } 在通过this.context 去获取
传递值:父组件定义static childContextTypes={ name:PropTypes.string }和getChildContext(){ return { name:'爷爷' } }
优点:
- 可以透过多层react 传值
缺点:
- 有点打乱数据传递的流向,不好理解数据
注意事项:
- 一般在写通用性组件的时候才会用到,其他时候尽量用props 或者 redux 去实现
Demo 如下:
import React,{Component} from 'react'
import PropTypes from 'prop-types'
class ContextParent extends Component{
static childContextTypes={
name:PropTypes.string
}
render(){
return (
<div>
Node Parent
{this.props.children}
</div>
)
}
getChildContext(){
return {
name:'爷爷'
}
}
}
class Context extends Component{
render(){
return <div>
Current Node
{this.props.children}
</div>
}
}
class ContextChild extends Component{
static contextTypes={
name:PropTypes.string.isRequired,
}
render(){
return (
<div>
Node Children
<span>Parent:{this.context.name}</span>
</div>
)
}
}
export default function(){
return (
<ContextParent>
<Context>
<ContextChild/>
</Context>
</ContextParent>
)
}
event 传值
通过 eventemitter3 library 实现,也可以用其他的event 库
该传值方案一般作为react state 存储数据时候需要联动触发的业务逻辑以及专业填上线前出现的业务逻辑的代码坑。
传值方式:
获取值:通过在constructor 里面监听event 事件,再setState到内部state
传递值: 触发 emit 事件
优点:
- 事件驱动,可以和其他框架做数据交换
缺点
- 数据流向不明确,不好理解和后续维护
注意事项
- event 的 事件名称 最好是全局的constants 对象,同时也是有规律的
Demo 如下:
import React,{Component} from 'react'
import EventEmitter from 'eventemitter3';
const EVENT = new EventEmitter();
class NodeOne extends Component{
constructor(props){
super(props)
this.state={
counter:0
};
EVENT.on('NodeOne:increment',(num)=>{
this.setState({
counter:this.state.counter+num
})
})
}
render(){
return (
<div>
<h4>Node One 当前counter:{this.state.counter}</h4>
<button onClick={()=>{
EVENT.emit('NodeTwo:increment',20)
}}>Node Two 加 20</button>
</div>
)
}
}
class NodeTwo extends Component{
constructor(props){
super(props)
this.state={
counter:0
};
EVENT.on('NodeTwo:increment',(num)=>{
this.setState({
counter:this.state.counter+num
})
})
}
render(){
return (
<div>
<h4>Node Two当前counter:{this.state.counter}</h4>
<button onClick={()=>{
EVENT.emit('NodeOne:increment',5)
}}>Node One 加 5</button>
</div>
)
}
}
export default function(){
return (
<div>
<NodeOne/>
<NodeTwo/>
</div>
)
}
React 页面间传值的个人总结的更多相关文章
- iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)
iOS页面间传值实现方法:1.通过设置属性,实现页面间传值:2.委托delegate方式:3.通知notification方式:4.block方式:5.UserDefault或者文件方式:6.单例模式 ...
- iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例)
iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notific ...
- 【转】iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)-- 不错
原文网址:http://www.cnblogs.com/JuneWang/p/3850859.html iOS页面间传值的方式(NSUserDefault/Delegate/NSNotificatio ...
- iOS 页面间传值 之 单例传值 , block 传值
ios 页面间传值有许多,前边已经分享过属性传值和代理传值,今天主要说一下单例传值和 block 传值 单例传值:单例模式一种常用的开发的模式,单例因为在整个程序中无论在何时初始化对象,获取到的都是同 ...
- iOS 页面间传值 之 属性传值,代理传值
手机 APP 运行,不同页面间传值是必不可少,传值的方式有很多(方法传值,属性传值,代理传值,单例传值) ,这里主要总结下属性传值和代理传值. 属性传值:属性传值是最简单,也是最常见的一种传值方式,但 ...
- iOS页面间传值的方式 (Delegate/NSNotification/Block/NSUserDefault/单例)
iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例) iOS页面间传值的方式(NSUserDefault/Delegate/NSN ...
- iOS页面间传值的五种方式总结(Delegate/NSNotification/Block/NSUserDefault/单例)
iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例) iOS页面间传值的方式(NSUserDefault/Delegate/NSNot ...
- mui框架如何实现页面间传值
mui框架如何实现页面间传值 我的传值 listDetail = '<li class="mui-table-view-cell mui-media>">< ...
- MUI框架-02-注意事项-适用场景-实现页面间传值
MUI框架-02-注意事项-适用场景-实现页面间传值 关于开发,我拷贝太多也没什么意义,就请查阅:官方文档:http://dev.dcloud.net.cn/mui/ui/ 快速入门 - 注意事项 有 ...
随机推荐
- 01-从零玩转JavaWeb-面向过程与面向对象
配套视频讲解:面向过程面向对象 一.面向过程 所有事情都按顺序一件一件来执行. 二.面向对象 面向对象是将功能通过对象也实现,将功能封装进对象之中 让对象去实现具体的细节 三.面向对象的目的 ...
- 2017 多校训练 1002 Balala Power!
Balala Power! Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- Peaceful Commission
Peaceful Commission Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 判断回文数字 9. Palindrome Number
Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could negativ ...
- (11.06)Java小知识
最近由于课程变化,学习计划也跟着改动,留给我写博客的时间也越来越少.今天晚上没有课,抽空过来图书馆写一写,许久不写感觉都有点陌生了! 今天要和大季家分享的衔接了上一篇博客,是关于方法的嵌套调用与递归调 ...
- VMware驱动程序"vmci.sys"的版本不正确 怎么解决
解决办法: 1.创建好虚拟机之后,别打开电源,然后到建好的虚拟机文件夹里: 2.找到后缀vmx的文件,记事本打开: 3.找到vmci0.present='TRUE',把true改为false: 4.保 ...
- 百度Echarts导入
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- HTML 3秒一换轮播(鼠标选中旋转停止定时) 动画案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【LuaJIT版】从零开始在 macOS 上配置 Lua 开发环境
前言 这篇文章针对的是基于 LuaJIT 的环境配置.借助于 LuaJIT,Lua 的执行效率可以进一步提升几十倍.如果你不是很清楚自己是需要 Lua 还是 LuaJIT,那么建议你从 LuaJIT ...
- Hadoop 2.2.0单节点的伪分布集成环境搭建
Hadoop版本发展历史 第一代Hadoop被称为Hadoop 1.0 1)0.20.x 2)0.21.x 3)0.22.x 第二代Hadoop被称为Hadoop 2.0(HDFS Federatio ...