详解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的一些注意
Dec 06 Javascript
javascript 函数调用规则
Aug 26 Javascript
js 多浏览器分别判断代码
Apr 01 Javascript
js获取系统的根路径实现介绍
Sep 08 Javascript
window.open打开页面居中显示的示例代码
Dec 27 Javascript
一个CSS+jQuery实现的放大缩小动画效果
Feb 19 Javascript
基于JavaScript如何制作遮罩层对话框
Jan 26 Javascript
JS实现浏览上传文件的代码
Aug 23 Javascript
React Native自定义控件底部抽屉菜单的示例
Feb 08 Javascript
Node.js Express安装与使用教程
May 11 Javascript
微信小程序语音同步智能识别的实现案例代码解析
May 29 Javascript
jQuery实现简单全选框
Sep 13 jQuery
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
php 正则表达式小结
2009/08/31 PHP
生成ubuntu自动切换壁纸xml文件的php代码
2010/07/17 PHP
JS和JQUERY获取页面大小,滚动条位置,元素位置(示例代码)
2013/12/14 Javascript
JavaScript中textRange对象使用方法小结
2015/03/24 Javascript
jQuery插件MixItUp实现动画过滤和排序
2015/04/12 Javascript
javascript解三阶幻方(九宫格)
2015/04/22 Javascript
10条建议帮助你创建更好的jQuery插件
2015/05/18 Javascript
jQuery的实例及必知重要的jQuery选择器详解
2016/05/20 Javascript
浅谈JavaScript 浏览器对象
2016/06/03 Javascript
JS使用cookie实现只出现一次的广告代码效果
2017/04/22 Javascript
详解用webpack2搭建angular2的项目
2017/06/22 Javascript
JavaScript简介_动力节点Java学院整理
2017/06/26 Javascript
深入解析Vue 组件命名那些事
2017/07/18 Javascript
无限循环轮播图之运动框架(原生JS实现)
2017/10/01 Javascript
vue2.0 兄弟组件(平级)通讯的实现代码
2018/01/15 Javascript
vue2.0+vuex+localStorage代办事项应用实现详解
2018/05/31 Javascript
vue router带参数页面刷新或回退参数消失的解决方法
2019/02/27 Javascript
微信小程序实现一张或多张图片上传(云开发)
2019/09/25 Javascript
Nodejs技巧之Exceljs表格操作用法示例
2019/11/06 NodeJs
vue中的双向数据绑定原理与常见操作技巧详解
2020/03/16 Javascript
微信小程序点击item使之滚动到屏幕中间位置
2020/03/25 Javascript
Python Socket实现简单TCP Server/client功能示例
2017/08/05 Python
python3 http提交json参数并获取返回值的方法
2018/12/19 Python
python中seaborn包常用图形使用详解
2019/11/25 Python
python 画3维轨迹图并进行比较的实例
2019/12/06 Python
Python使用Pandas库常见操作详解
2020/01/16 Python
Python运行提示缺少模块问题解决方案
2020/04/02 Python
电气工程及其自动化学生实习自我鉴定
2013/09/19 职场文书
外语系大学生自荐信范文
2014/03/01 职场文书
会展策划与管理专业求职信
2014/06/09 职场文书
晋江市人民政府党组群众路线教育实践活动整改方案
2014/10/25 职场文书
同学聚会邀请函
2015/01/30 职场文书
ObjectMapper 如何忽略字段大小写
2021/06/29 Java/Android
Redis的字符串是如何实现的
2021/10/24 Redis
Oracle中update和select 关联操作
2022/01/18 Oracle
Win11软件图标固定到任务栏
2022/04/19 数码科技