详解React之父子组件传递和其它一些要点


Posted in Javascript onJune 25, 2018

react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度。下面对一些react日常开发中的注意事项进行罗列。

React的组件生命周期

react主要思想是构建可复用组件来构建用户界面。在react里面一切皆组件。每个组件里面都是有自己的生命周期,这个生命周期规定了组件的状态和方法,分别在哪个阶段执行。下面附上一张React的生命周期图:

详解React之父子组件传递和其它一些要点

组件第一阶段:初始化、渲染以及装载完成;

组件第二阶段:组件运行时候的状态 ①:状态变化引发组件的更新和重新渲染到更新完成

  ②:父组件属性变化引发组件的更新(是常见的组件之间传递数据和同步状态的手段):比如父组件登录了,子组件也需变成登录状态

组件第三阶段:卸载组件

JSX 语法

const names = ['Alice', 'Emily', 'Kate'];

ReactDOM.render(
 <div>
 {
  names.map((name) => {
   return <div>Hello, {name}!</div>
  })
 }
 </div>,
 document.getElementById('example')
);

JSX 的基本语法规则:遇到 HTML 标签(以<开头),就用 HTML 规则解析;遇到代码块(以{开头),就用 JavaScript 规则解析。

所以给jsx添加注释只要这样子:

{/* 。。。 */}

父组件传向子组件

子:
var HelloMessage = React.createClass({
 render: function() {
  return <h1>Hello {this.props.name}</h1>;
 }
});
---------------------------------------
父:
ReactDOM.render(
 <HelloMessage name="Muyy" />,
 document.getElementById('example')
);

变量HelloMessage就是相当于一个子组件类。通过this.props.name获取到了Muyy。

另外注意

  1. 所有组件类都必须有自己的render方法,用于输出组件。
  2. 组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage
  3. 组件类只能包含一个顶层标签
  4. class属性需要写成classNamefor属性需要写成htmlFor,这是因为classfor是 JavaScript 的保留字

子组件传向父(爷)组件

其实很简单,概括起来就是:react中state改变了,组件才会update。父组件写好state和处理该state的函数,同时将函数名通过props属性值的形式传入子,子调用父的函数,同时引起state变化。

例子1.这里如下图,用户邮箱为父,绿色框为子。 父组件为用户输入的邮箱设好state,即“{email: ''}”,同时写好处理state的函数,即“handleEmail”,这两个名称随意起;再将函数以props的形式传到子组件,子组件只需在事件发生时,调用父组件传过来的函数即可。

详解React之父子组件传递和其它一些要点

//子组件
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.bind(this)}/>
      </div>
    )
  }
});
React.render(
 <Parent />,
 document.getElementById('test')
);

例子2.有时候往往需要对数据做处理,再传给父组件,比如过滤或者自动补全等等,下面的例子对用户输入的邮箱做简单验证,自动过滤非数字、字母和"@."以外的字符。

详解React之父子组件传递和其它一些要点

//子组件,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.bind(this)}/>
      </div>
    )
  }
});
React.render(
 <Parent />,
 document.getElementById('test')
);

例子3.如果还存在孙子组件的情况呢?如下图,黑框为父,绿框为子,红框为孙,要求子孙的数据都传给爷爷。原理一样的,只是父要将爷爷对孙子的处理函数直接传下去。

详解React之父子组件传递和其它一些要点

//孙子,将下拉选项的值传给爷爷
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.bind(this)} handleSelect={this.handleSelect.bind(this)}/>
      </div>
    )
  }
});
React.render(
 <Parent />,
 document.getElementById('test')
);

getDefaultProps && getInitialState

getDefaultProps方法可以用来设置组件属性的默认值

var MyTitle = React.createClass({
 getDefaultProps : function () {
  return {
   title : 'Hello World'
  };
 },

 render: function() {
   return <h1> {this.props.title} </h1>;
  }
});

ReactDOM.render(
 <MyTitle />,
 document.body
);

getInitialState 方法可以用来设置初始状态

getInitialState: function() {
  return {liked: false};
 },

获取真实的DOM节点

从组件获取真实 DOM 的节点,这时就要用到ref属性

var MyComponent = React.createClass({
 handleClick: function() {
  this.refs.myTextInput.focus();
 },
 render: function() {
  return (
   <div>
    <input type="text" ref="myTextInput" />
    <input type="button" value="Focus the text input" onClick={this.handleClick} />
   </div>
  );
 }
});

ReactDOM.render(
 <MyComponent />,
 document.getElementById('example')
);

上面代码中,组件MyComponent的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个ref属性,然后this.refs.[refName]就会返回这个真实的 DOM 节点。

需要注意的是,由于this.refs.[refName]属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定Click事件的回调函数,确保了只有等到真实 DOM 发生Click事件之后,才会读取this.refs.[refName]属性。

React 组件支持很多事件,除了Click事件以外,还有KeyDownCopyScroll等,完整的事件清单请查看官方文档。

子组件传向父组件的另一种思路

父组件调用子组件的state、function,除了上面介绍的方法之外,也可以通过ref属性实现。推荐使用这种方式进行子组件向父组件的传递。举个简单的示范:

export default class 父组件a extends React.Component {
  constructor(props) {
    super(props)  
  }

  render() {
    return (
     <子组件b
        ref={r => this.bbbb =r} // bbbb自定义名字
     />
    )
  }
}

经过这样处理后后,现在父组件a中可以通过this.bbbb.state.xxx获取子组件的xxx状态,也可以通过this.bbbb.xxx获取子组件的xxx方法。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery的Ajax时无响应数据的解决方法
May 25 Javascript
js控制滚动条缓慢滚动到顶部实现代码
Mar 20 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
Jul 18 Javascript
js控制文本框只输入数字和小数点的方法
Mar 10 Javascript
详解JavaScript函数对象
Nov 15 Javascript
通过网页查看JS源码中汉字显示乱码的解决方法
Oct 26 Javascript
使用snowfall.jquery.js实现爱心满屏飞的效果
Jan 05 Javascript
深入理解Node.js中的进程管理
Mar 13 Javascript
详解jQuery-each()方法
Mar 13 jQuery
jQuery提示框插件SweetAlert用法分析
Aug 05 jQuery
JavaScript实现班级抽签小程序
May 19 Javascript
vue实现同时设置多个倒计时
May 20 Vue.js
Vue EventBus自定义组件事件传递
Jun 25 #Javascript
一个Vue页面的内存泄露分析详解
Jun 25 #Javascript
Vue.js项目中管理每个页面的头部标签的两种方法
Jun 25 #Javascript
angularjs结合html5实现拖拽功能
Jun 25 #Javascript
vue中vee validate表单校验的几种基本使用
Jun 25 #Javascript
超出JavaScript安全整数限制的数字计算BigInt详解
Jun 24 #Javascript
JS的函数调用栈stack size的计算方法
Jun 24 #Javascript
You might like
mysql时区问题
2008/03/26 PHP
php学习 函数 课件
2008/06/15 PHP
php select,radio和checkbox默认选择的实现方法
2010/05/15 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
PHP中串行化用法示例
2016/11/16 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
Laravel 6 将新增为指定队列任务设置中间件的功能
2019/08/06 PHP
Laravel修改验证提示信息为中文的示例
2019/10/23 PHP
JS对象转换为Jquery对象示例
2014/01/26 Javascript
JavaScript中switch判断容易犯错的一个细节
2014/08/27 Javascript
Bootstrap按钮组件详解
2016/04/26 Javascript
iScroll.js 使用方法参考
2016/05/16 Javascript
jQuery DataTables插件自定义Ajax分页实例解析
2020/04/28 Javascript
jQuery使用zTree插件实现可拖拽的树示例
2017/09/23 jQuery
微信小程序-getUserInfo回调的实例详解
2017/10/27 Javascript
vue中当图片地址无效的时候,显示默认图片的方法
2018/09/18 Javascript
js实现按钮开关单机下拉菜单效果
2018/11/22 Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
2019/11/29 Javascript
基于vue3.0.1beta搭建仿京东的电商H5项目
2020/05/06 Javascript
原生js实现随机点名
2020/07/05 Javascript
详解vue 中 scoped 样式作用域的规则
2020/09/14 Javascript
django 实现编写控制登录和访问权限控制的中间件方法
2019/01/15 Python
python协程之动态添加任务的方法
2019/02/19 Python
python tkinter组件摆放方式详解
2019/09/16 Python
Pycharm debug调试时带参数过程解析
2020/02/03 Python
python GUI库图形界面开发之PyQt5开发环境配置与基础使用
2020/02/25 Python
PyQt5的相对布局管理的实现
2020/08/07 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
美国嘻哈文化生活方式品牌:GLD
2018/04/15 全球购物
专科毕业生自我鉴定
2013/12/01 职场文书
完整版商业计划书
2014/09/15 职场文书
2014年医务科工作总结
2014/12/18 职场文书
历史博物馆观后感
2015/06/05 职场文书
2016创先争优活动党员公开承诺书
2016/03/24 职场文书
django上传文件的三种方式
2021/04/29 Python
浅谈MySql整型索引和字符串索引失效或隐式转换问题
2021/11/20 MySQL