react native组件传递组件上调用方法如何传递参数,除了匿名函数用更好的方法吗

React组件的三种写法总结
作者:Jean-Xu
字体:[ ] 类型:转载 时间:
本文主要总结了React组件的三种写法以及最佳实践,具有一定的参考价值,下面跟着小编一起来看下吧
React 专注于 view 层,组件化则是 React 的基础,也是其核心理念之一,一个完整的应用将由一个个独立的组件拼装而成。
截至目前 React 已经更新到 v15.4.2,由于 ES6 的普及和不同业务场景的影响,我们会发现目前主要有三种创建 React 组件的写法:1. ES5写法React.createClass,2. ES6写法ponent,3. 无状态的函数式写法(纯组件-SFC)。
你们最钟爱哪种写法呢?萝卜青菜各有所爱~ 每个团队都有自己的代码规范和开发模式,但书写 React 组件时 都会以提高代码阅读性、更优的组件性能、易于 bug 追踪为原则。下面我们就聊聊这三种写法的区别,以及各自所适用场景的最佳实践。
ES5-写法 React.createClass
React.createClass不用多说,我们最早使用这个方法来构建一个组件“类”,它接受一个对象为参数,对象中必须声明一个render方法,render返回一个组件实例,下面用一个 SwitchButton 组件的例子来看看React.createClass的具体用法:
var React = require('react');
var ReactDOM = require('react-dom');
var SwitchButton = React.createClass({
getDefaultProp:function() {
return { open: false }
getInitialState: function() {
return { open: this.props.open };
handleClick: function(event) {
this.setState({ open: !this.state.open });
render: function() {
var open = this.state.open,
className = open ? 'switch-button open' : 'btn-switch';
&label className={className} onClick={this.handleClick.bind(this)}&
&input type="checkbox" checked={open}/&
ReactDOM.render(
&SwitchButton /&,
document.getElementById('app')
ES6-写法 ponent
React 升级到 v0.13 后就支持了 ES6 的class语法,我们可以使用class App ponent{...}的方式创建组件,这也是目前官方推荐创建有状态组件的方式。用 ES6 重写上面 SwitchButton 组件的例子:
import React from 'react'
import { render } from 'react-dom'
class SwitchButton ponent {
constructor(props) {
super(props)
this.state = {
open: this.props.open
this.handleClick = this.handleClick.bind(this)
handleClick(event) {
this.setState({ open: !this.state.open })
render() {
let open = this.state.open,
className = open ? 'switch-button open' : 'btn-switch'
&label className={className} onClick={this.handleClick}&
&input type="checkbox" checked={open}/&
SwitchButton.defaultProps = {
open: false
&SwitchButton /&,
document.getElementById('app')
与React.createClass创建组件的不同之处:
与这里使用了 ES6 的import语句替代require()方法导入模块,其中import {render}可以直接从模块中导入变量名,这种写法更加简洁直观。
初始化 state
React 使用 ES6 的“类”继承实现时,去掉了getInitialState这个 hook 函数,state的初始化放在构造函数方法constructor中声明。
<ponent创建组件时,事件函数并不会自动绑定this,需要我们手动绑定,不然this将不会指向当前组件的实例对象。以下有三种绑定this的方法:
1. 在constructor中使用bind()进行硬绑定
constructor() {
this.handleClick = this.handleClick.bind(this);
2. 直接在元素上使用bind()绑定
&label className={className} onClick={this.handleClick.bind(this)}&
3. ES6 有个很有用的语法糖:Arrow Function(箭头函数)它可以很方便的使this直接指向class SwitchButton(它的作用等同于大家熟悉的var self = this,但后者会让代码变得混乱,Arrow Function 就很好的解决了这一问题)
&label className={className} onClick={()=&this.handleClick()}&
无状态的函数式写法(纯组件 SFC)
React.createClass和ponent都可以用来创建有状态的组件,而 无状态组件 - Stateless Component 是 React 在 v0.14 之后推出的。
它的出现 是因为随着应用复杂度不断提升和组件本数量的增加,组件按各自职责被分成不同的类型,于是有一种只负责展示的纯组件出现了,它的特点是不需要管理状态state,数据直接通过props传入,这也符合 React 单向数据流的思想。
对于这种无状态的组件,使用函数式的方式声明,会使得代码的可读性更好,并能大大减少代码量,Arrow Function 则是函数式写法的最佳搭档:
const Todo = (props) =& (
onClick={props.onClick}
style={{textDecoration: plete &#63; "line-through" : "none"}}
{props.text}
上面定义的 Todo 组件,输入输出数据完全由props决定,而且不会产生任何副作用。对于props为 Object 类型时,我们还可以使用 ES6 的解构赋值:
const Todo = ({ onClick, complete, text, ...props }) =& (
onClick={onClick}
style={{textDecoration: complete &#63; "line-through" : "none"}}
{...props}
{props.text}
无状态组件一般会搭配高阶组件(简称:OHC)一起使用,高阶组件用来托管state,Redux 框架就是通过 store 管理数据源和所有状态,其中所有负责展示的组件都使用无状态函数式的写法。
这种模式被鼓励在大型项目中尽可能以简单的写法 来分割原本庞大的组件,而未来 React 也会面向这种无状态的组件进行一些专门的优化,比如避免无意义的检查或内存分配。所以建议大家尽可能在项目中使用无状态组件。
当然,无状态组件也不是万金油,比如它不支持"ref",原因很简单,因为 React 调用它之前,组件不会被实例化,自然也就没有"ref",(ref和findDOMNode实际上打破了父子组件之间仅通过 props 来传递状态的约定,违背了 React 的原则,需要避免)。
以上三种写法的比较,以及最佳实践
Facebook 官方早就声明 ponent将取代React.createClass。随着 React 不断发展,React.createClass暴露出一些问题:
相比ponent可以有选择性的绑定需要的函数,React.createClass会自动绑定函数,这样会导致不必要的性能开销。
React.createClass亲生的 mixin,ponent不再支持,事实上 mixin 不够优雅直观,替代方案是使用更流行的高阶组件-HOC,如果你的项目还离不开 也可以使用 react-mixin
总的来说:无状态函数式写法 优于React.createClass,而React.createClass优于ponent。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具问题: (react.js)react 中 ,子组件的内部方法,父组件如何调用?
描述:比如父组件中有一个弹窗组件,该弹窗组件包含open/close两个方法用以显示/隐藏该弹窗。现在父组件在某些状态下,如ajax success回调中,想去操作这个弹窗。请问,有什么方法可以做到?解决方案1:可以给字组件加个ref属性然后在父组件内可以方问子组件的props/state/方法。。。&子组件 ref='test'/&this.refs.test.子方法
以上介绍了“ (react.js)react 中 ,子组件的内部方法,父组件如何调用?”的问题解答,希望对有需要的网友有所帮助。
本文网址链接:/itwd/3288592.html
上一篇: 下一篇:React 组件之间如何交流 - 推酷
React 组件之间如何交流
今天群里面有很多都在问关于 React 组件之间是如何通信的问题,之前自己写的时候也遇到过这类问题。下面是我看到的一篇不错英文版的翻译,看过我博客的人都知道,我翻译可能不会按部就班,会尽可能用中文的意思,来将作者要讲述的技术描述清楚。英文能力有限,如果有不对的地方请跟我留言,一定修改……^_^
处理 React 组件之间的交流方式,主要取决于组件之间的关系,然而这些关系的约定人就是你。
我不会讲太多关于 data-stores、data-adapters 或者 data-helpers 之类的话题。我下面只专注于 React 组件本身的交流方式的讲解。
React 组件之间交流的方式,可以分为以下 3 种:
【父组件】向【子组件】传值;
【子组件】向【父组件】传值;
没有任何嵌套关系的组件之间传值(PS:比如:兄弟组件之间传值)
一、【父组件】向【子组件】传值
这个是相当容易的,在使用 React 开发的过程中经常会使用到,主要是利用 props 来进行交流。例子如下:
var MyContainer = React.createClass({
getInitialState: function () {
checked: true
render: function() {
&ToggleButton text=&Toggle me& checked={this.state.checked} /&
var ToggleButton = React.createClass({
render: function () {
// 从【父组件】获取的值
var checked = this.props.checked,
text = this.props.
&label&{text}: &input type=&checkbox& checked={checked} /&&/label&
进一步讨论
如果组件嵌套层次太深,那么从外到内组件的交流成本就变得很高,通过 props 传递值的优势就不那么明显了。(PS:所以我建议尽可能的减少组件的层次,就像写 HTML 一样,简单清晰的结构更惹人爱)
var MyContainer = React.createClass({
render: function() {
&Intermediate text=&where is my son?& /&
// 子组件1:中间嵌套的组件
var Intermediate = React.createClass({
render: function () {
&Child text={this.props.text} /&
// 子组件2:子组件1的子组件
var Child = React.createClass({
render: function () {
&span&{this.props.text}&/span&
二、【子组件】向【父组件】传值
接下来,我们介绍【子组件】控制自己的 state 然后告诉【父组件】的点击状态,然后在【父组件】中展示出来。因此,我们添加一个 change 事件来做交互。
var MyContainer = React.createClass({
getInitialState: function () {
checked: false
onChildChanged: function (newState) {
this.setState({
checked: newState
render: function() {
var isChecked = this.state.checked ? 'yes' : 'no';
&div&Are you checked: {isChecked}&/div&
&ToggleButton text=&Toggle me&
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
var ToggleButton = React.createClass({
getInitialState: function () {
checked: this.props.initialChecked
onTextChange: function () {
var newState = !this.state.
this.setState({
checked: newState
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
render: function () {
// 从【父组件】获取的值
var text = this.props.
// 组件自身的状态数据
var checked = this.state.
&label&{text}: &input type=&checkbox& checked={checked}
onChange={this.onTextChange} /&&/label&
我觉得原文作者用代码不是很直观,接下来我话一个流程走向简图来直观描述一下这个过程:
这样做其实是依赖 props 来传递事件的引用,并通过回调的方式来实现的,这样实现不是特别好,但是在没有任何工具的情况下也是一种简单的实现方式
这里会出现一个我们在之前讨论的问题,就是组件有多层嵌套的情况下,你必须要一次传入回调函数给 props 来实现子组件向父组件传值或者操作。
Tiny-Tip: React Event System
在 onChange 事件或者其他 React 事件中,你能够获取以下东西:
【this】:指向你的组件
【一个参数】:这个参数是一个
,SyntheticEvent。
React 对所有事件的管理都是自己实现的,与我们之前使用的 onclick、onchange 事件不一样。从根本上来说,他们都是绑定到 body 上。
document.on('change', 'input[data-reactid=&.0.2&]', function () {...});
上面这份代码不是来自于 React,只是打一个比方而已。
如果我没有猜错的话,React 真正处理一个事件的代码如下:
var listenTo = ReactBrowserEventEmitter.listenTo;
function putListener(id, registrationName, listener, transaction) {
var container = ReactMount.findReactContainerForID(id);
if (container) {
var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument :
listenTo(registrationName, doc);
// 在监听事件的内部,我们能发现如下:
target.addEventListener(eventType, callback, false);
这里有所有 React 支持的事件:
多个子组件使用同一个回调的情况
var MyContainer = React.createClass({
getInitialState: function () {
totalChecked: 0
onChildChanged: function (newState) {
var newToral = this.state.totalChecked
+ (newState ? 1 : -1);
this.setState({
totalChecked: newToral
render: function() {
var totalChecked = this.state.totalC
&div&How many are checked: {totalChecked}&/div&
&ToggleButton text=&Toggle me&
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
&ToggleButton text=&Toggle me too&
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
&ToggleButton text=&And me&
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
var ToggleButton = React.createClass({
getInitialState: function () {
checked: this.props.initialChecked
onTextChange: function () {
var newState = !this.state.
this.setState({
checked: newState
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
render: function () {
// 从【父组件】获取的值
var text = this.props.
// 组件自身的状态数据
var checked = this.state.
&label&{text}: &input type=&checkbox& checked={checked} onChange={this.onTextChange} /&&/label&
这是非常容易理解的,在父组件中我们增加了一个【totalChecked】来替代之前例子中的【checked】,当子组件改变的时候,使用同一个子组件的回调函数给父组件返回值。
三、没有任何嵌套关系的组件之间传值
如果组件之间没有任何关系,组件嵌套层次比较深(个人认为 2 层以上已经算深了),或者你为了一些组件能够订阅、写入一些信号,不想让组件之间插入一个组件,让两个组件处于独立的关系。对于事件系统,这里有 2 个基本操作步骤:订阅(subscribe)/监听(listen)一个事件通知,并发送(send)/触发(trigger)/发布(publish)/发送(dispatch)一个事件通知那些想要的组件。
下面讲介绍 3 种模式来处理事件,你能
来比较一下它们。
简单总结一下:
(1) Event Emitter/Target/Dispatcher
特点:需要一个指定的订阅源
// to subscribe
otherObject.addEventListener(‘click’, function() { alert(‘click!’); });
// to dispatch
this.dispatchEvent(‘click’);
(2) Publish / Subscribe
特点:触发事件的时候,你不需要指定一个特定的源,因为它是使用一个全局对象来处理事件(其实就是一个全局广播的方式来处理事件)
// to subscribe
globalBroadcaster.subscribe(‘click’, function() { alert(‘click!’); });
// to dispatch
globalBroadcaster.publish(‘click’);
(3) Signals
特点:与Event Emitter/Target/Dispatcher相似,但是你不要使用随机的字符串作为事件触发的引用。触发事件的每一个对象都需要一个确切的名字(就是类似硬编码类的去写事件名字),并且在触发的时候,也必须要指定确切的事件。(看例子吧,很好理解)
// to subscribe
otherObject.clicked.add(function() { alert(‘click’); });
// to dispatch
this.clicked.dispatch();
如果你只想简单的使用一下,并不需要其他操作,可以用简单的方式来实现:
// 简单实现了一下 subscribe 和 dispatch
var EventEmitter = {
_events: {},
dispatch: function (event, data) {
if (!this._events[event]) { // 没有监听事件
for (var i = 0; i & this._events[event]. i++) {
this._events[event][i](data);
subscribe: function (event, callback) {
// 创建一个新事件数组
if (!this._events[event]) {
this._events[event] = [];
this._events[event].push(callback);
otherObject.subscribe('namechanged', function(data) { alert(data.name); });
this.dispatch('namechanged', { name: 'John' });
如果你想使用 Publish/Subscribe 模型,可以使用:
React 团队使用的是:
它基于 Signals 模式,用起来相当不错。
Events in React
使用 React 事件的时候,必须关注下面两个方法:
componentDidMount
componentWillUnmount
在处理事件的时候,需要注意:
在 componentDidMount 事件中,如果组件挂载(mounted)完成,再订阅事件;当组件卸载(unmounted)的时候,在 componentWillUnmount 事件中取消事件的订阅。
(如果不是很清楚可以查阅 React 对生命周期介绍的文档,里面也有描述。原文中介绍的是 componentWillMount 个人认为应该是挂载完成后订阅事件,比如Animation这个就必须挂载,并且不能动态的添加,谨慎点更好)
因为组件的渲染和销毁是由 React 来控制的,我们不知道怎么引用他们,所以EventEmitter 模式在处理组件的时候用处不大。
pub/sub 模式可以使用,你不需要知道引用。
下面来一个例子:实现有多个 product 组件,点击他们的时候,展示 product 的名字。
(我在例子中引入了之前推荐的 PubSubJS 库,如果你觉得引入代价太大,也可以手写一个简版,还是比较容易的,很好用哈,大家也可以体验,但是我还是不推荐全局广播的方式)
// 定义一个容器
var ProductList = React.createClass({
render: function () {
&ProductSelection /&
&Product name=&product 1& /&
&Product name=&product 2& /&
&Product name=&product 3& /&
// 用于展示点击的产品信息容器
var ProductSelection = React.createClass({
getInitialState: function() {
selection: 'none'
componentDidMount: function () {
this.pubsub_token = PubSub.subscribe('products', function (topic, product) {
this.setState({
selection: product
}.bind(this));
componentWillUnmount: function () {
PubSub.unsubscribe(this.pubsub_token);
render: function () {
&p&You have selected the product : {this.state.selection}&/p&
var Product = React.createClass({
onclick: function () {
PubSub.publish('products', this.props.name);
render: function() {
return &div onClick={this.onclick}&{this.props.name}&/div&;
ES6: yield and js-csp
ES6 中有一种传递信息的方式,使用生成函数(generators)和 yield 关键字。可以看一下
(这里我写一个简单的 DEMO 介绍一下这种新的传递方式,其实大同小异)
function* list() {
for(var i = 0; i & arguments. i++) {
yield arguments[i];
return &done.&;
var o = list(1, 2, 3);
var cur = o.
while(!cur.done) {
cur = o.next();
console.log(cur);
以上例子来自于屈屈的一篇博客:
屈屈是一个大牛,大家可以经常关注他的博客。
通常来说,你有一个队列,对象在里面都能找到一个引用,在定义的时候锁住,当发生的时候,立即打开锁执行。js-csp 是一种解决办法,也许以后还会有其他解决办法。
在实际应用中,按照实际要解决的需求选择解决办法。对于小应用程序,你可以使用 props 和回调的方法进行组件之间的数据交换。你可以通过 pub/sub 模式,以避免污染你的组件。在这里,我们不是在谈论数据,只是组件。对于数据的请求、数据的变化等场景,可以使用 Facebook 的 Flux、Relay、GraphQL 来处理,都非常的好用。
文中的每一个例子我都验证过了,主要使用最原始的引入文件方式,创建服务使用的 http-server 包,大家也可以尝试自己来一次。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致[译] React 组件中绑定回调_javascript_ThinkSAAS
[译] React 组件中绑定回调
[译] React 组件中绑定回调
内容来源: 网络
在组件中给事件绑定处理函数是很常见的,比如说每当用户点击一个button的时候使用console.log打印一些东西。
class DankButton ponent {
render() {
return &button onClick={this.handleClick}&Click me!&/button&
handleClick() {
console.log(`such knowledge`)
很好,这段代码会满足你的需求,那现在如果我想在handleClick()内调用另外一个方法,比如logPhrase()
class DankButton ponent {
render() {
return &button onClick={this.handleClick}&Click me!&/button&
handleClick() {
this.logPhrase()
logPhrase() {
console.log(&such gnawledge&)
这样竟然不行,会得到如下的错误提醒
TypeError: this.logPhrase is not a function at handleClick (file.js:36:12)
当我们把handleClick绑定到 onClick的时候我们传递的是一个函数的引用,真正调用handleClick的是事件处理系统。因此handleClick 的this上下文和我门想象的this.logPhrase()是不一样的。
这里有一些方法可以让this指向DankButton组件。
不好的方案 1:箭头函数
箭头函数是在ES6中引入的,是一个写匿名函数比较简洁的方式,它不仅仅是包装匿名函数的语法糖,箭头函数没有自己的上下问,它会使用被定义的时候的this作为上下文,我们可以利用这个特性,给onClick绑定一个箭头函数。
class DankButton ponent {
render() {
// Bad Solution: An arrow function!
return &button onClick={() =& this.handleClick()}&Click me!&/button&
handleClick() {
this.logPhrase()
logPhrase() {
console.log(&such gnawledge&)
然而,我并不推荐这种解决方式,因为箭头函数定义在render内部,组件每次重新渲染都会创建一个新的箭头函数,在React中渲染是很快捷的,所以重新渲染会经常发生,这就意味着前面渲染中产生的函数会堆在内存中,强制垃圾回收机制清空它们,这是很花费性能的。
不好的方案 2:this.handleClick.bind(this)
另外一个解决这个问题的方案是,把回调绑定到正确的上下问this
class DankButton ponent {
render() {
// Bad Solution: Bind that callback!
return &button onClick={this.handleClick.bind(this)}&Click me!&/button&
handleClick() {
this.logPhrase()
logPhrase() {
console.log(&such gnawledge&)
这个方案和箭头函数有同样的问题,在每次render的时候都会创建一个新的函数,但是为什么没有使用匿名函数也会这样呢,下面就是答案。
function test() {}
const testCopy = test
const boundTest = test.bind(this)
console.log(testCopy === test) // true
console.log(boundTest === test) // false
.bind并不修改原有函数,它只会返回一个指定执行上下文的新函数(boundTest和test并不相等),因此垃圾回收系统仍然需要回收你之前绑定的回调。
好的方案:在构造函数(constructor)中bind handleClick
仍然使用 .bind ,现在我们只要绕过每次渲染都要生成新的函数的问题就可以了。我们可以通过只在构造函数中绑定回调的上下问来解决这个问题,因为构造函数只会调用一次,而不是每次渲染都调用。这意味着我们没有生成一堆函数然后让垃圾回收系统清除它们。
class DankButton ponent {
constructor() {
// Good Solution: Bind it in here!
this.handleClick = this.handleClick.bind(this)
render() {
return &button onClick={this.handleClick}&Click me!&/button&
handleClick() {
this.logPhrase()
logPhrase() {
console.log(&such gnawledge&)
很好,现在我们的函数被绑定到正确的上下文,而且不会在每次渲染的时候创建新的函数。
如果你使用的是React.createClass而不是ES6的classes,你就不会碰到这个问题,createClass生成的组件会把它们的方法自动绑定到组件的this,甚至是你传递给事件回调的函数。内容来源:
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信}

我要回帖

更多关于 react 跨组件状态传递 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信