React中父子组件间的通信问题
2023-09-27 14:28:55 时间
一 组合而不是继承
React组件是无法继承的,即不存在 React.extend 之类的方法可以定义一个子类。
React推崇通过组合的方式来组织大规模的应用。
所以所谓父子组件,就和DOM中的父子元素一样,他们是有从属关系,但没有继承关系。
比如:
我们有一个父组件 Team,里面有一个子组件 People。
Team和People并不存在谁继承谁,只是 People 组成了 Team 而已。
大家都知道面向对象三个特性:封装、继承和多态。其中继承当然不是错的,但是确是争议最大的一个。可以参见这篇文章:
http://blog.berniesumption.com/software/inheritance-is-evil-and-must-be-destroyed/
很多时候,继承是可以通过interface之类的方式来完成的。
二 父子组件通信
组合起来很简单,那么父子组件怎么通信呢。
你可能会想通过事件来通信。React 竟然没有提供一个自定义事件,它的事件仅仅用来处理DOM事件,并没有组件的自定义事件。
比如一个子组件是无法通过 trigger(“hungry”) 之类的事件来通知父组件的。当然,你可以通过mixin之类的方式来给组件提供事件能力。
那么这样,就只有一种方式可以让子组件向父组件发送消息,就是 this.props 属性。
比如 父组件需要知道子组件的 hungry 事件,那么他向子组件传递一个 props.onHungry 方法。这样子组件通过调用 this.props.onHungry 就可以通知父组件。
而父组件怎么通知子组件呢?
也是通过 props,直接 setProps 来修改子组件的 props就行了。
这样,实际上 props 是父子组件通信的最重要的甚至是唯一的标准渠道。
看一个例子,还是上面的例子,稍作改动:
点一下 Lucy 就会alert一下。
Team 组件通过 props.onHungry 传给了 People 组件一个回调,这样 People 组件就通过调用这个方法来通知Team。
这是子组件向父组件发送消息的方式。
那么父组件怎么向子组件发送消息呢。更简单了,直接修改 props 就行了
team.setProps({name: “Lily”})
因为 props 是父子组件的通信渠道,为了避免状态不一致,所以严格杜绝组件修改自己的状态。
可以通过 team.setProps 方式修改,这属于组件外修改,但是不能在组件中 通过 this.setProps 方式来修改。
那么现在有一个问题,React是如何知道一个组件的 props 被他的父组件修改了?
我们把上面的代码改一下:
这样,Team把 this.state.name 作为 props 传给了 People 。
Team每次通过 this.setState 来修改state.name 的时候,People都会进行更新。
猜测是 setState 和 setProps 这两个方法会触发组件的更新。并且会触发每一个子组件检查更新。
子组件调用父组件:
1)在父组件设置对应的属性和方法;
2)将父组件的属性,方法设置在子组件的标签属性上;
3)子组件中利用this.props来调用父组件的成员;
eg:
父:
var p=React.cleateClass({
getDefaultProps:function(){
return{
a:1
}
},
render:function(){
return <Ch a={this.props.a}></Ch>
}
})
子:
var Ch=React.createClass({
render:fucntion(){
return <div>{this.props.a}</div>
}
})
父组件调用子组件:
1)在父组件中的子组件利用ref对子组件标注引用;
2)在父组件中利用this,refs获取子组件的引用,从而调用子组件的成员;
eg:
父:
var p=React.cleateClass({
hand:function(){
this.refs.one.hands();
},
render:function(){
return <Ch ref="one"></Ch>
}
})
子:
var Ch=React.createClass({
hands:function(){}
render:fucntion(){
return <div></div>
}
})
【react】父组件向子组件传值
父向子是用props,然后再子那边有一个监听函数
父类调用子类的函数
【react】子组件向父组件传值
reactjs是一枚新进小鲜肉,跟gulp搭配流行一段时间了。工作或者面试中经常遇到这样的问题,“子组件如何向父组件传值?”。其实很简单,概括起来就是:React中state改变了,组件才会update。父写好state和处理该state的函数,同时将函数名通过props属性值的形式传入子,子调用父的函数,同时引起state变化。子组件要写在父组件之前。具体写法看下面3个例子。
例子1.这里如下图,用户邮箱为父,绿色框为子。 父组件为用户输入的邮箱设好state,即“{email: ''}”,同时写好处理state的函数,即“handleEmail”,这两个名称随意起;再将函数以props的形式传到子组件,子组件只需在事件发生时,调用父组件传过来的函数即可。
//以下所有例子对应的html <body> <div id="test"></div> </body>
//子组件 var Child = React.createClass({ render: function(){ return ( <div> 请输入邮箱:<input onChange={this.props.handleEmail}/> </div> ) } }); //父组件,此处通过event.target.value获取子组件的值 var Parent = React.createClass({ getInitialState: function(){ return { email: '' } }, handleEmail: function(event){ this.setState({email: event.target.value}); }, render: function(){ return ( <div> <div>用户邮箱:{this.state.email}</div> <Child name="email" handleEmail={this.handleEmail}/> </div> ) } }); React.render( <Parent />, document.getElementById('test') );
例子2.有时候往往需要对数据做处理,再传给父组件,比如过滤或者自动补全等等,下面的例子对用户输入的邮箱做简单验证,自动过滤非数字、字母和"@."以外的字符。
//子组件,handleVal函数处理用户输入的字符,再传给父组件的handelEmail函数 var Child = React.createClass({ handleVal: function() { var val = this.refs.emailDom.value; val = val.replace(/[^0-9|a-z|\@|\.]/ig,""); this.props.handleEmail(val); }, render: function(){ return ( <div> 请输入邮箱:<input ref="emailDom" onChange={this.handleVal}/> </div> ) } }); //父组件,通过handleEmail接受到的参数,即子组件的值 var Parent = React.createClass({ getInitialState: function(){ return { email: '' } }, handleEmail: function(val){ this.setState({email: val}); }, render: function(){ return ( <div> <div>用户邮箱:{this.state.email}</div> <Child name="email" handleEmail={this.handleEmail}/> </div> ) } }); React.render( <Parent />, document.getElementById('test') );
例子3.如果还存在孙子组件的情况呢?如下图,黑框为父,绿框为子,红框为孙,要求子孙的数据都传给爷爷。原理一样的,只是父要将爷爷对孙子的处理函数直接传下去。
//孙子,将下拉选项的值传给爷爷 var Grandson = React.createClass({ render: function(){ return ( <div>性别: <select onChange={this.props.handleSelect}> <option value="男">男</option> <option value="女">女</option> </select> </div> ) } }); //子,将用户输入的姓名传给爹 //对于孙子的处理函数,父只需用props传下去即可 var Child = React.createClass({ render: function(){ return ( <div> 姓名:<input onChange={this.props.handleVal}/> <Grandson handleSelect={this.props.handleSelect}/> </div> ) } }); //父组件,准备了两个state,username和sex用来接收子孙传过来的值,对应两个函数handleVal和handleSelect var Parent = React.createClass({ getInitialState: function(){ return { username: '', sex: '' } }, handleVal: function(event){ this.setState({username: event.target.value}); }, handleSelect: function(event) { this.setState({sex: event.target.value}); }, render: function(){ return ( <div> <div>用户姓名:{this.state.username}</div> <div>用户性别:{this.state.sex}</div> <Child handleVal={this.handleVal} handleSelect={this.handleSelect}/> </div> ) } }); React.render( <Parent />, document.getElementById('test') );
相关文章
- React Native 图表组件Echarts
- React Native调用原生组件
- 微信小程序基本组件概述
- 分页组件化思想
- react-native 安卓手机Text组件文字显示不全问题
- FrozenJS 针对移动端开发的 js 组件库
- React组件通信(入门)
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(一)
- JS组件系列——Bootstrap Table 表格行拖拽(二:多行拖拽)
- 【Java AWT 图形界面编程】事件处理机制 ③ ( AWT 中常见的事件和事件监听器 | 低级事件 | 组件事件 | 窗口事件 | 鼠标事件 | 高级事件 | 动作事件 | 事件监听器 )
- React组件通信技巧
- Vue.js之父子组件
- 编写高性能React组件-传值篇
- React.js 中的组件通信问题
- React 各种组件关系通信
- React.js组件通信所有方法
- ReactJS组件间沟通的一些方法
- React组件通信技巧
- 详解Vue组件系统
- React 和 ReactNative 的渲染机制/ ReactNative 与原生之间的通信 / 如何自定义封装原生组件/RN中的多线程
- React Native手势密码组件
- react-native新导航组件react-navigation详解
- React-native设置全局函数globle【适用于有组件嵌套时】
- React Native 的 Navigator 组件使用方式
- 《React-Native系列》19、 ListView组件之上拉刷新(iOS和Android通用)
- 11 款 React Native 开源移动 UI 组件
- [Unity UGUI]点击和长按组件