深刻解析React数据传递之组件内部通讯

这篇文章主要介绍了React数据传递之组件内部通讯的方法,写的十分的全面细致,具备必定的参考价值,对此有须要的朋友能够参考学习下。若有不足之处,欢迎批评指正。css

1. 概述html

脱离初级前端一段时间后会发现,写样式的时间愈来愈少,处理数据的时间愈来愈多。处理数据的过程也就是实现业务逻辑的过程,这在项目中无疑是最重要的。 因此学习前端框架,了解完基本语法后,接下来就要学习其如何进行数据传递。 Angular 设计之初的一大亮点就是实现了数据的双向绑定,使用 Vue 一段时间后发现,所谓数据的双向绑定,组件内部惟一的应用场景就是 form 表单(input,textarea,select, radio),而这种场景下的数据双向绑定,即使框架内部没有实现,本身实现起来也很是简单。明白这一点后感受以前认为 React 没有实现数据双向绑定很 low 的想法很幼稚。 对于 React 的数据传递,涉及两方面的内容: 组件内部的数据传递,典型的应用场景包括如何实现 form 表单双向数据绑定、如何绑定事件; 组件间的数据传递。 包括父组件往子组件传递数据、子组件往父组件传递数据以及兄弟组件之间传递数据。 本文先讨论组件内部的数据传递。前端

2. 组件内部数据传递vue

React 组件内部通讯主要分为两部分:数据展现与事件处理。 2.1 数据展现 组件内部数据的展现和更新都是经过 state 来实现的,若是要使用 state 必须使用 ES6 的 class 定义组件。数据更新在双向数据绑定部分探讨,这部分仅讨论展现初始化数据。 若是你熟悉 Vue,React 的 state 对象至关于 Vue 的 data 对象 下面是一个纯展现数据的示例:node

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> ); } }//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920 复制代码

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

2.2 事件webpack

2.2.1 与 DOM 中事件的异同web

在 React 中处理事件和在 DOM 中处理事件相似,有两点不一样: React 中经过驼峰命名法命名事件,而不是全是小写字母; 在 JSX 中直接传递函数做为事件处理程序,而不是字符串。 第 2 点不一样有坑,后面细说 举个例子,HTML中的事件:面试

<button onclick="activateLasers()">
 Activate Lasers
</button>
复制代码

React 中的事件:bash

// 由于 jsx 中'{}'里面表明函数表达式,
// 因此传递给 onClick 的实际是函数 activateLasers 的函数体部分,
// 所以须要指定 this 指向,否则会报错
<button onClick={activateLasers}>
 Activate Lasers
</button>
//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920
复制代码

2.2.2 存在的坑

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

class App extends Component {
 constructor(props) {
 super(props);
 this.state = {
  isToggleOn: true,
 };
 //欢迎加入前端全栈开发交流圈一块儿学习交流:619586920
 // 手动绑定 this
 this.handleClick = this.handleClick.bind(this);
 }
 
 handleClick() {
 // 若是不在 constructor() 方法中手动绑定 this,直接将其做为事件处理程序 this 为 undefined
 console.log(this);
 
 this.setState(prevState => ({
  isToggleOn: !prevState.isToggleOn
 }));
 }
 //欢迎加入前端全栈开发交流圈一块儿学习交流:619586920
 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;
//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920 
fn(); // window
a(); // window
this 指向发生改变的例子:
 
var fn = function () {
 console.log(this);
};
 
// 将函数体赋值给一个对象的属性,函数执行时 this 和定义时指向不一样
var o = {
 a: fn,
};
//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920 
fn(); // window
o.a(); // o,即{a:f}
复制代码

若是想要在将函数体赋值另外一个变量的同时把原函数的 this 指向也一块赋值过去,就须要在赋值的过程当中进行绑定 this 的操做,以下:

var fn = function () {
 console.log(this);
};
 
// fn 在赋值的同时将内部的 this 打包一块赋值给了 a
var o = {
 a: fn.bind(this),
};
//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920 
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>
);//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920
复制代码

等同于

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);
 }
 //欢迎加入前端全栈开发交流圈一块儿学习交流:619586920
 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>
  );
 }
}//欢迎加入前端全栈开发交流圈一块儿学习交流:619586920
复制代码

结语

感谢您的观看,若有不足之处,欢迎批评指正。

本次给你们推荐一个免费的学习群,里面归纳移动应用网站开发,css,html,webpack,vue node angular以及面试资源等。 对web开发技术感兴趣的同窗,欢迎加入Q群:864305860,无论你是小白仍是大牛我都欢迎,还有大牛整理的一套高效率学习路线和教程与您免费分享,同时天天更新视频资料。 最后,祝你们早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。

相关文章
相关标签/搜索