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

react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度。下面对一些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的形式传到子组件,子组件只需在事件发生时,调用父组件传过来的函数即可。

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

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

//孙子,将下拉选项的值传给爷爷
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方法。

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

(0)

相关推荐

  • react.js 父子组件数据绑定实时通讯的示例代码

    react.js我自己还在摸索学习中,碰到父子组件数据绑定实时通讯的问题,研究了一下,分享给大家,也给自己留个笔记: import React,{Component} from 'react' import ReactDOM from 'react-dom' class ChildCounter extends Component{ render(){ return( <div style={{border:'1px solid red'}}> {this.props.count} </

  • React父子组件间的传值的方法

    父组件向子组件传值: 父组件: import React, { Component } from 'react'; import Child from './chlid'; class parent extends Component{ constructor(props) { super(props); this.state = { txt0:"默认值0", txt1:"默认值1" } } componentDidMount(){ } parToson(){ th

  • react 父子组件之间通讯props

    实现父子组件双向数据流整体的思路是: 1,父组件可以向子组件传递props,props中带有初始化子组件的数据,还有回调函数 2,子组件的state发生变化时,在子组件的事件处理函数中,手动触发父函数传递进来的回调函数,同时时将子组件的数据传递回去(有时间研究) 父组件 父组件中定义一个函数,包含一个props的参数,函数内利用super(props)传递给子组件,this.state中用于定义本页面中要用到的以及要传递给子组件的变量. 父组件的render函数中利用<Table list={t

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

    react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度.下面对一些react日常开发中的注意事项进行罗列. React的组件生命周期 react主要思想是构建可复用组件来构建用户界面.在react里面一切皆组件.每个组件里面都是有自己的生命周期,这个生命周期规定了组件的状态和方法,分别在哪个阶段执行.下面附上一张React的生命周期图: 组件第一阶段:初始化.渲染以及装载完成: 组件第二阶段:组件运行时候的状态 ①:状态变化引发组件

  • 详解React中共享组件逻辑的三种方式

    废话少说,这三种方式分别是:render props.高阶组件和自定义Hook.下面依次演示 假设有一个TimeOnPage组件专门用来记录用户在当前页面停留时间,像这样: const TimeOnPage = () => { const [second, setSecond] = useState(0); useEffect(() => { setTimeout(() => { setSecond(second + 1); }, 1000); }, [second]); return

  • 详解Vue之父子组件传值

    一.简要介绍 父子组件之间的传值主要有三种:传递数值.传递方法.传递对象,主要是靠子组件的 props 属性来接收传值,下面分别介绍: (一)传递数值 1.子组件:Header.vue <template> <div> <!-- data对象里并没有 msg 属性,这里调用的是父类传递过来的 msg 属性 --> <h2>{{msg}}</h2> </div> </template> <script> expo

  • 详解React中的组件通信问题

    引入 本来我是没想过总结这些东西的,会感觉比较入门.但是之前同学去腾讯面试问到了这个问题(react或vue的组件通信),我帮他整理,顺便写demo的过程中,会有一些新的体会,多总结还是有利于进步的呀. 父子组件 父 → 子 parent组件传给child组件,符合react的单向数据流理念,自上到下传递props. // 父组件 class Parent extends Component { constructor() { super(); this.state = { value: '',

  • 详解Vue 非父子组件通信方法(非Vuex)

    一提到两个非父子组件通信方法,有经验的 coder 肯定会说用 Vuex 啊,我个人建议不要为了用 Vuex 而用 Vuex,除非你的项目很大,耦合度很高,需要大量的储存一些 data,组件之间通信频繁.当然还是要根据自己的业务场景的来决定,总之还是那句话,不要为了用 Vuex 而用 Vuex! Vue 官网介绍了非父子组件通信方法: 不过官网说的太简单了,新手看完估计还是一脸懵逼.还有这个空的 Vue 实例放到哪里合适也值得商榷. 这篇文章的目的就是用一个简单的例子让你明白如何用 Bus

  • 详解react如何在组件中获取路由参数

    路由参数 假如我们有很多 list 页面,这些页面除了动态内容不同,其他的页面部分都相同,这个时候需要怎么配置路由和组件呢? 这种场景就需要用到路由的参数功能,增加一条包含参数的路由配置. import List from './component/list'; <Route path="list/:id" component={List} /> 注意 path 属性中的 :id 就是该路由的参数( param ).再来看看 List 页面的组件. /list 对应了 li

  • 详解React中传入组件的props改变时更新组件的几种实现方法

    我们使用react的时候常常需要在一个组件传入的props更新时重新渲染该组件,常用的方法是在componentWillReceiveProps中将新的props更新到组件的state中(这种state被成为派生状态(Derived State)),从而实现重新渲染.React 16.3中还引入了一个新的钩子函数getDerivedStateFromProps来专门实现这一需求.但无论是用componentWillReceiveProps还是getDerivedStateFromProps都不是

  • 详解react native页面间传递数据的几种方式

    1. 利用react-native 事件DeviceEventEmitter 监听广播 应用场景: - 表单提交页面, A页面跳转到B页面选人, 然后返回A页面, 需要将B页面选择的数据传回A页面. - 多个多媒体来回切换播放,暂停后二次继续播放等问题. 代码如下: A页面 componentDidMount() { // 利用DeviceEventEmitter 监听 concactAdd事件 this.subscription = DeviceEventEmitter.addListener

  • React中父子组件通信详解

    目录 父组件向子组件通信 存在期 父组件向子组件通信 在父组件中,为子组件添加属性数据,即可实现父组件向子组件通信.传递的数据可以分成两类 子组件是作为属性来接收这些数据的 第一类就是数据:变量,对象,属性数据,状态数据等等 这些数据发生改变,子组件接收的属性数据就发生了改变. 第二类就是方法:父组件可以向子组件传递属性方法,子组件接收方法,并可以在组件内执行,有两种执行方式 注意:父组件传给子组件的方法是不能执行的,执行了相当于将方法的返回值传递给子组件. 第一种 作为事件回调函数执行 参数默

  • 详解React 父组件和子组件的数据传输

    在学习 React 框架组件间数据传输知识点前,我们需要先明确几点使用原则. React的组件间通讯是单向的.数据必须是由父级传到子级或者子级传递给父级层层传递. 如果要给兄弟级的组件传递数据,那么就要先传递给公共的父级而后在传递给你要传递到的组件位置. 这种非父子关系的组件间传递数据,不推荐使用这种层层传递的方式:而是选择使用维护全局状态功能模块(Redux) 一.父组件向子组件传递数据 父组件向子组件传递数据是通过在父组件中引用子组件时,在子组件标签设置传输数据的属性:而子组件中通过 thi

随机推荐