首頁  >  文章  >  web前端  >  在React中如何實現組件內部通信

在React中如何實現組件內部通信

亚连
亚连原創
2018-06-14 15:24:481587瀏覽

這篇文章主要介紹了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 (
  <p className="App">
  <p>{this.state.inputValue}</p>
  </p>
 );
 }
}

在透過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 中&#39;{}&#39;里面代表函数表达式,
// 所以传递给 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 (
  <p className="App">
  <button onClick={this.handleClick}>
   {this.state.isToggleOn ? "on" : "off"}
  </button>
  </p>
 );
 }
}

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: &#39;button&#39;,
 props: {
 onClick: this.handleClick,
 children: &#39;click me&#39;,
 },
};


這實際上就是將函數體賦值給一個對象的屬性,函數執行時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 (
   <p className="App">
    <input value={this.state.inputValue} onChange={this.changeInput} />
    <p>{this.state.inputValue}</p>
   </p>
  );
 }
}

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

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

使用Node.js爬虫如何实现网页请求

使用VueAwesomeSwiper容易出现的问题?

在angular2中有关Http请求原理(详细教程)

在node中如何实现http小爬虫

以上是在React中如何實現組件內部通信的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn