欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-10-24 15:47:05
react是r系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度。下面对一些react日常开发中的注意事项进行罗列。...

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方法。

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