React数据传递之组件内部通信的方法

1. 概述

脱离初级前端一段时间后会发现,写样式的时间越来越少,处理数据的时间越来越多。处理数据的过程也就是实现业务逻辑的过程,这在项目中无疑是最重要的。

所以学习前端框架,了解完基本语法后,接下来就要学习其如何进行数据传递。

Angular 设计之初的一大亮点就是实现了数据的双向绑定,使用 Vue 一段时间后发现,所谓数据的双向绑定,组件内部唯一的应用场景就是 form 表单(input,textarea,select, radio),而这种场景下的数据双向绑定,即便框架内部没有实现,自己实现起来也非常简单。明白这一点后感觉之前认为 React 没有实现数据双向绑定很 low 的想法很幼稚。

对于 React 的数据传递,涉及两方面的内容:

  1. 组件内部的数据传递,典型的应用场景包括如何实现 form 表单双向数据绑定、如何绑定事件;
  2. 组件间的数据传递。 包括父组件往子组件传递数据、子组件往父组件传递数据以及兄弟组件之间传递数据。

本文先讨论组件内部的数据传递。

2. 组件内部数据传递

React 组件内部通信主要分为两部分:数据展示与事件处理。

2.1 数据展示

组件内部数据的展示和更新都是通过 state 来实现的,如果要使用 state 必须使用 ES6 的 class 定义组件。数据更新在双向数据绑定部分探讨,这部分仅讨论展示初始化数据。

如果你熟悉 Vue,React 的 state 对象相当于 Vue 的 data 对象

下面是一个纯展示数据的示例:

class App extends Component {
 constructor(props) {
 super(props);

 // 初始化 state
 this.state = {
  inputValue: "test",
 };
 }

 render() {
 // 注意,在 react 中,DOM 元素是对象,所以使用‘()'包住
 return (
  <div className="App">
  <p>{this.state.inputValue}</p>
  </div>
 );
 }
}

在通过 class 定义的 React 组件中,除了生命周期钩子函数, constructor() 和 render() 着两个方法也是自动执行的,先执行 constructor() ,执行 constructor() 的同时也是再为 render() 渲染 DOM 做数据准备。

实际上 constructor() 函数是组件生命周期中调用的第一个函数。

2.2 事件

2.2.1 与 DOM 中事件的异同

在 React 中处理事件和在 DOM 中处理事件类似,有两点不同:

  1. React 中通过驼峰命名法命名事件,而不是全是小写字母;
  2. 在 JSX 中直接传递函数作为事件处理程序,而不是字符串。

第 2 点不同有坑,后面细说

举个例子,HTML中的事件:

<button onclick="activateLasers()">
 Activate Lasers
</button>

React 中的事件:

// 因为 jsx 中'{}'里面代表函数表达式,
// 所以传递给 onClick 的实际是函数 activateLasers 的函数体部分,
// 因此需要指定 this 指向,不然会报错
<button onClick={activateLasers}>
 Activate Lasers
</button>

2.2.2 存在的坑

直接传递 function 作为 event handler 需要指定函数的执行环境,即需要手动绑定 this ,不然会报 this 为 undefined 的错。见下面的例子:

class App extends Component {
 constructor(props) {
 super(props);
 this.state = {
  isToggleOn: true,
 };

 // 手动绑定 this
 this.handleClick = this.handleClick.bind(this);
 }

 handleClick() {
 // 如果不在 constructor() 方法中手动绑定 this,直接将其作为事件处理程序 this 为 undefined
 console.log(this);

 this.setState(prevState => ({
  isToggleOn: !prevState.isToggleOn
 }));
 }

 render() {
 return (
  <div className="App">
  <button onClick={this.handleClick}>
   {this.state.isToggleOn ? "on" : "off"}
  </button>
  </div>
 );
 }
}

2.2.3 为什么会有坑

React 官网说这个锅要 JS 原生语法来背,其实不尽然,React 实在 JS 语法早已确定的情况下设计了这样的事件系统,如果一定要有人站出来背锅,他们五五分吧。

1, JS原生语法存在的问题

JS语法中有这样的规则:如果将一个函数的函数体(没有 () )赋值给另一个变量,函数体内部的 this 指向可能会发生变化。会不会变化取决于函数和被赋值的变量是否处于同一个作用域(相同的执行环境)中,但实际使用中,将一个函数赋值给相同作用域的变量没有意义,那样的话直接使用那个函数就好,没必要在赋值给另一个变量。

this 指向不发生改变的没有意义的例子(为了方便说明,直接使用 var 操作符):

var fn = function () {
 console.log(this);
};

var a = fn;

fn(); // window
a(); // window
this 指向发生改变的例子:

var fn = function () {
 console.log(this);
};

// 将函数体赋值给一个对象的属性,函数执行时 this 和定义时指向不同
var o = {
 a: fn,
};

fn(); // window
o.a(); // o,即{a:f}

如果想要在将函数体赋值另一个变量的同时把原函数的 this 指向也一块赋值过去,就需要在赋值的过程中进行绑定 this 的操作,如下:

var fn = function () {
 console.log(this);
};

// fn 在赋值的同时将内部的 this 打包一块赋值给了 a
var o = {
 a: fn.bind(this),
};

fn(); // window
o.a(); // window

通常在将函数体赋值给变量的时候为了避免 this 出错,都会进行 绑定执行环境的操作 ,典型的例子是 var bindId = document.getElementById.bind(document)

2, JSX 存在的问题

因为 JSX 中 DOM 元素也是对象,给元素的属性赋值实际是给 DOM 元素对象的属性赋值,见下:

const element = (
 <button onClick={this.handleClick}>click me</button>
);

等同于

const element = {
 type: 'button',
 props: {
 onClick: this.handleClick,
 children: 'click me',
 },
};

这实际就是 将函数体赋值给一个对象的属性,函数执行时 this 和定义时指向不同 的场景,和原生语法相同的是 this 指向发生了改变,不同的是原生 JS 中不管怎样, this 总归是有个指向的,而 JSX 直接 undefined 。

所以说不绑定 this 报 undefined 的错不能全怪 JS 原生语法。

3. 双向数据绑定

通过 state 传递数据加上事件处理程序便能实现数据的双向绑定,其背后的思想是(以 input 为例):初始化时将 state 中预定义的 state a 赋值给 input,当 input 的 value 发生改变时,触发事件处理程序,将改变后的 value 赋值给状态 a ,React 监测到 state 改变时重新调用 render() 方法,即重新渲染组件,达到双向绑定的目的。

class App extends Component {
 constructor(props) {
  super(props);
  this.state = {
   inputValue: "test",
  };
  this.changeInput = this.changeInput.bind(this);
 }

 changeInput(e) {
  // 将改变后的 input 值赋值给 inputValue,通过事件对象 $event.target.value 实现
  this.setState({
   inputValue: e.target.value
  });
 }

 render() {
  // input 改变时触发 changeInput
  return (
   <div className="App">
    <input value={this.state.inputValue} onChange={this.changeInput} />
    <p>{this.state.inputValue}</p>
   </div>
  );
 }
}

这里用到了事件对象,React 的事件对象和 JS 原生事件对象保持一致。

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

(0)

相关推荐

  • React组件之间的通信的实例代码

    最近学习浅尝则止的学习了一下react.js这个UI的框架,react这个库给我的最大的感觉就是它能够完全的接管UI层,在要改变视图的东西的时候只需要改变其this.state中的状态.只要操作数据层的东西视图层就会发生变化,这一点我还是很喜欢的.可以摆脱对DOM的直接操作,毕竟直接来会比较复杂,本来应该是逻辑层js中混杂着各种css的字符串,对于我来说有点不爽(JSX中也混杂这标签,但我觉的不应该把它看作标签,看作语句会习惯一点). 回到几天的重点,讲react组件之间的状态传递. 上代码:

  • react开发教程之React 组件之间的通信方式

    这两天学习了React感觉组件通信这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记. 父子组件通讯 通讯手段 这是最常见的通信方式,父组件只需要将子组件需要的props传给子组件,子组件直接通过this.props来使用. 通讯内容 更多要提的是如何合理的设置子组件的props,要想将子组件设计成一个复用性强的通用组件,需要将能够复用的部分抽象出来,抽象出来的props有两种形成,一种是简单的变量,另一种是抽象出来处理某种逻辑函数. 以Header 组件为例 //HeaderBar.j

  • 详解React native全局变量的使用(跨组件的通信)

    RN中有两种方式使用全局变量 1.通过导入导出文件的方式 新建constants.js文件 const object = { website:'http://www.hao123.com', name:'好123', }; export default object; 需要用到的时候导入文件 import constants from './constansts.js' <Text>{constants.name}</Text> 还可以有另外一种导入文件的写法 export def

  • 关于react中组件通信的几种方式详解

    前言 刚入门React可能会因为React的单向数据流的特性而遇到组件间沟通的麻烦,下面这篇文章就来给大家详细介绍下,在开始之前先来看一张图: react组件通信 需要组件之进行通信的几种情况 父组件向子组件通信 子组件向父组件通信 跨级组件通信 没有嵌套关系组件之间的通信 1. 父组件向子组件通信 React数据流动是单向的,父组件向子组件通信也是最常见的;父组件通过props向子组件传递需要的信息 Child.jsx import React from 'react'; import Pro

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

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

  • React数据传递之组件内部通信的方法

    1. 概述 脱离初级前端一段时间后会发现,写样式的时间越来越少,处理数据的时间越来越多.处理数据的过程也就是实现业务逻辑的过程,这在项目中无疑是最重要的. 所以学习前端框架,了解完基本语法后,接下来就要学习其如何进行数据传递. Angular 设计之初的一大亮点就是实现了数据的双向绑定,使用 Vue 一段时间后发现,所谓数据的双向绑定,组件内部唯一的应用场景就是 form 表单(input,textarea,select, radio),而这种场景下的数据双向绑定,即便框架内部没有实现,自己实现

  • Vue 父子组件的数据传递、修改和更新方法

    父子组件之间的数据关系,我这边将情况具体分成下面4种: 父组件修改子组件的data,并实时更新 子组件通过$emit传递子组件的数据,this.$data指当前组件的data(return{...})里的所有数据, this.$emit('data',this.$data); 之后通过父组件的getinputdata方法来接收数据 @data='getinputdata' 其中的data就是传过来的数据,通过修改这个数据就可以通过父组件实时更新子组件 getinputdata(data) { c

  • React Native自定义标题栏组件的实现方法

    大家好,今天讲一下如何实现自定义标题栏组件,我们都知道RN有一个优点就是可以组件化,在需要使用该组件的地方直接引用并传递一些参数就可以了,这种方式确实提高了开发效率. 标题栏是大多数应用界面必不可少的一部分,将标题栏剥离出来做成一个组件很有必要.今天先讲一个不带返回按钮的标题栏.废话少说,直接上代码: /** * 封装公共的标题头,没有返回按钮 */ 'use strict'; import React, { Component } from 'react'; import { Text, Vi

  • iPhone与iWatch连接、控制、数据传递(Swift)的方法

    最近在做一个项目,涉及到iPhone设备和手表传输数据.控制彼此界面跳转,在网上找了很多资料,发现国内的网站这方面介绍的不多,而国外的网站写的也不是很全,所以在这写这篇文章,给大家参考一下,望大神指点一二. iPhone和iWatch配对这个不需要多说,百度搜索答案一大堆,这个是前提. iPhone与iWatch交互的代码有两种情况,取决于iWatch的系统.iWatch OS1与OS2.3的方法不同,在OS1的系统中,iWatch发送数据的代码如下 let userInfo:[String:S

  • 深入理解React中es6创建组件this的方法

    首发于:https://mingjiezhang.github.io/. 在JavaScript中,this对象是运行时基于函数的执行环境(也就是上下文)绑定的. 从react中的demo说起 Facebook最近一次更新react时,将es6中的class加入了组件的创建方式当中.Facebook也推荐组件创建使用通过定义一个继承自 React.Component 的class来定义一个组件类.官方的demo: class LikeButton extends React.Component

  • React实践之Tree组件的使用方法

    本文介绍了React实践之Tree组件,分享给大家,具体如下: 实现功能 渲染数据 展开合并 使用 数据结构: const node = { title: '00000', key: '0' , level:'level1', open: true, child:[ { title: '0-111111', key: '0-0', level:'level2', open: true, child:[ { title: '0-1-1111', key: '0-0-0', level:'level

  • JAVA POST与GET数据传递时中文乱码问题解决方法

    做了N年的java开发从没有自己写过一个网站,最近乱忙活弄了一个企业家宣传网站. 跟大家一样遇到了中文字符集乱码问题,为了大家能少走一些弯路,所以在此分享一下即简单又实用的解决方法. 1. POST 数据传递 接收页 复制代码 代码如下: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% request.setCharacterEnco

  • React日期时间显示组件的封装方法

    本文实例为大家分享了React日期时间显示组件的封装具体代码,供大家参考,具体内容如下 时间日期展示器 import ProtoType from 'prop-types'; import { useState, useEffect } from 'react'; import './index.css' /**时间选择器  * @luoronghao  * 参数说明  * timzone:时区(1-24)  * calendar:日期类型{solar(阳历),lunar(阴历)}  * dat

  • vue组件中的数据传递方法

    Vue 的组件作用域都是孤立的,不允许在子组件的模板内直接引用父组件的数据.必须使用特定的方法才能实现组件之间的数据传递.组件之间传递数据大致分为三种情况: 父组件向子组件传递数据,通过 props 传递数据. 子组件向父组件传递数据,通过 events 传递数据. 两个同级组件之间传递数据,通过 event bus 传递数据. 一.父组件向子组件传递数据 子组件部分: <template> <div class="child"> {{ msg }} </

  • Angular 2父子组件数据传递之@Input和@Output详解 (上)

    前言 为了让大家学习起来轻松.易懂,小编尽量做到篇幅短,语言通俗易懂,知识点分段来讲,以免太长了看起来很累,也很容易失去耐心阅读下去,希望大家理解和支持,同时希望大家点赞和分享出去,让更多的志同道合的朋友来学习 Angular 提供了@Input和@Output语法来处理组件数据的流入流出,接下来我们通过@Input和@Output来演示父子组建之间的数据传递 父组件向子组件传递数据 父组件传递数据到子组件通过@Input方式的现实方式 第一步:定义父组件 ParentComponent.ts

随机推荐