這篇文章主要介紹了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,快速升職加薪,走上人生巔峯。