摘要:給賦值也是構造函數的工作之一。在的構造函數中,還給兩個成員函數綁定了當前的執行環境,因為方式創建的組件并不自動給我們綁定到當前實例對象。我們可以利用的功能,避免判斷邏輯這種充斥在構造函數之中,讓代碼更優。
React系列---React(一)初識React
React系列---React(二)組件的prop和state
React系列---React(三)組件的生命周期
組件是React的基石,所有的React應用程序都是基于組件的。基于組件的應用開發是廣泛使用的軟件開發模式,用分而治之的方法,把一個大的應用分解成若干小的組件,每個組件只關注某個特定功能,但是把組件組合起來,就能構成一個功能龐大的應用。
React組件的數據分為兩種,prop和state,無論prop或者state的改變,都可能引發組件的重新渲染。prop是組件對外接口,state是組件內部狀態。
第一個組件用create-react-app工具,初始化一個React項目:
npm create-react-app react-component-demo
創建一個可以計算點擊數的組件:
/src/ClickCounter.js:
import React from "react"; class ClickCounter extends React.Component { constructor(props) { super(props); this.onClickButton = this.onClickButton.bind(this); this.state = {count: 0}; } onClickButton() { this.setState({count: this.state.count + 1}); } render() { return (); }; } export default ClickCounter;Click Count: {this.state.count}
修改/src/index.js:
import React from "react"; import ReactDOM from "react-dom"; import ClickCounter from "./ClickCounter"; ReactDOM.render(, document.getElementById("root"));
運行React項目
npm run start
點擊按鈕,數字會隨之增加。恭喜你,已經構建了一個有交互的組件!
我們還可以在React組件中定義樣式。修改ClickCounter組件的render函數:
render() { const counterStyle = { margin: "16px" }; return (組件的prop); };Click Count: {this.state.count}
React組件通過定義自己能夠接受的prop就定義了自己對外公共接口。外部世界通過prop和組件對話。
給prop賦值從外部世界看prop的使用:
上面的例子使用了名為SampleButton的組件實例。React組件的prop所能支持的類型除了字符串,還可以是任何一種JavaScript語言支持的數據類型。當prop的類型不是字符串時,再JSX中必須用花括號{}把值包裹,所以style的值有兩層花括號,外層代表是JSX的語法,內層代表這是個對象常量。
React組件要反饋數據給外部世界,也是用prop,因為prop類型也可以是函數,函數類型的prop等于讓父組件交給子組件一個回調函數,子組件在恰當的時機調用函數的prop,就可以把信息傳遞給外部世界。
為了演示,我們構造一個應用包含兩種組件,ControlPanel父組件,然后若干個Counter子組件。對于Counter組件,父組件ControlPanel就是外部世界:
class ControlPanel extends React.Component { render() { return (); } }
React要求render只能返回一個元素,所以我們用div包裹了3個子組件。
每個Counter組件使用了caption和initValue兩個prop。ControlPanel通過caption的prop傳遞給Counter組件實例說明文字,通過initValue的prop傳遞給Count組件一個初始的計數值。
讀取prop值看下Counter組件內部是如何接收prop的:
class Counter extends React.Component { constructor(props) { super(props); this.onClickIncrementButton = this.onClickIncrementButton.bind(this); this.onClickDecrementButton = this.onClickDecrementButton.bind(this); this.state = { count: props.initValue || 0 }; } }
如果組件需要定義自己的構造函數,構造函數第一行一定要通過super調用父類React.Component的構造函數。給this.props賦值也是React.Component構造函數的工作之一。
在Counter的構造函數中,還給兩個成員函數綁定了當前this的執行環境,因為ES6方式創建的組件并不自動給我們綁定this到當前實例對象。
在其他函數中則可以通過this.props訪問傳入的值,看一下render函數:
render() { const {caption} = this.props; // ES6的解構賦值 return (propTypes檢查{caption} count: {this.state.count}); };
在ES6方法定義的組件中,可以通過增加類的propTypes屬性來定義prop規格。在運行和靜態代碼檢查時,都可以根據propTypes判斷外部世界是否正確地使用了組件的屬性。
增加Counter組件的propTypes定義:
Counter.propTypes = { caption: PropTypes.string.isRequired, initValue: PropTypes.number };
開發過程中,定義propTypes代碼可以避免犯錯,但是在發布產品時,可以用babel-react-optimize工具自動去除propTypes,這樣部署到產品環境的代碼就會更優。
組件的state驅動組件渲染的除了prop,還有state,state代表組件內部狀態。由于React組件禁止修改傳入的prop,所以當組件需要記錄自身的數據變化時,就要使用state。
在Counter組件中,初始計數可以通過initValue這個prop指定。當用戶點擊“+”和“-”改變計數時,就要Counter組件自己通過state來存儲了。
通常在構造函數的結尾處初始化state,就如上面的Counter:
constructor(props) { ... this.state = { count: props.initValue || 0 }; }
由于在PropType聲明中沒有用isRequired,我們需要在代碼中判斷給定的prop值是否存在,不存在則給一個默認值。我們可以利用React的defaultProps功能,避免判斷邏輯這種充斥在構造函數之中,讓代碼更優。
給Counter組件添加defaultProps代碼:
Counter.defaultProps = { initValue: 0 };
構造函數就可以簡化了:
constructor(props) { ... this.state = { count: props.initValue }; }讀取和更新state
通過給button的onClick屬性掛載點擊事件處理函數,我們可以改變組件的state,以點擊“+”按鈕的響應函數為例:
onClickIncrementButton() { this.setState({count: this.state.count + 1}); }
通過this.state可以讀取到組件的當前state。注意的是,改變state必須使用this.setState函數,而不能直接修改this.state。如果你違反這個操作,瀏覽器Console會告警。
直接修改this.state的值,只是野蠻的修改了state,卻沒有驅動組件重新渲染,新的值當然也不會反應在界面上。而this.setState()函數所做的事情,就是改變this.state的值后再驅動組件重新渲染。
無狀態函數式組件沒有內部state,不需要組件生命周期函數。可以用純函數的形式來表達。它做的事情只是根據輸入來展示組件,沒有其他副作用。可以把這種組件稱為無狀態函數式組件(stateless functional component)。
import React from "react"; // 用一個純函數表示 const Hobby = (props) =>
創建盡量多的無狀態組件,這些組件唯一關心的就是渲染數據。而在最外層,應該有一個包含state的父級別組件,用于處理各種事件、交流邏輯、修改state。對應的子組件要關心的只是傳入的屬性而已。
state應該包含組件的事件回調函數可能引發UI更新的這類數據。在實際的項目中,應該是輕量化的JSON數據,盡量把數據的表現設計到最小,更多的數據可以在render中通過各種計算得到。
prop和state對比prop用于定義外部接口,state用于記錄內部狀態;
prop的賦值在外部世界使用組件時,state的賦值在組件內部;
組件不應該改變prop的值,而state的存在的目的就是讓組件來改變的。
DOM操作大多數情況下,不需要操作DOM去更新UI,應使用setState。但是有些情況確實需要訪問一些DOM(如表單的值),那么可采用refs方式來獲得DOM節點。只需要加個ref屬性,然后通過this.refs.name來獲得對應的DOM結構。
示例Profile組件:
render() { return (...) }
在button上添加事件,取得input的值,添加到state的值里面:
addHobbyCallback() { // 用this.refs.name來取得DOM節點 let hobbyInput = this.refs.hobby; let val = hobbyInput.value; if (val) { let hobbies = this.state.hobbies; // 添加值到數組 hobbies = [...hobbies, val]; // 更新state, 刷新UI this.setState({ hobbies }, () => { hobbyInput.value = ""; }); } }
React系列---React(一)初識React
React系列---React(二)組件的prop和state
React系列---React(三)組件的生命周期
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/83674.html
摘要:用于規范的類型與必需的狀態。表示由組件更改的數據,通常是通過與用戶的交互來更改的。為了實現的修改,需要注冊事件處理程序到相應的元素上。當事件發生時,將更新后的值是從中檢索,并通知組件。通常情況下,該函數初始化狀態使用,,或其他數據存儲。 前言 上一篇文章中,我們講到了JSX的一些用法和注意事項,這次我們來講react中最基礎也是特別重要的內容:組件。這篇文章包含組件的以下內容:狀態、屬...
摘要:組件裝載過程裝載過程依次調用的生命周期函數中每個類的構造函數,創造一個組件實例,當然會調用對應的構造函數。組件需要構造函數,是為了以下目的初始化,因為生命周期中任何函數都有可能訪問,構造函數是初始化的理想場所綁定成員函數的環境。 React系列---React(一)初識ReactReact系列---React(二)組件的prop和stateReact系列---之React(三)組件的生...
摘要:當真正執行狀態修改時,依賴的并不能保證是最新的,因為會把多次的修改合并成一次,這時,還是等于這幾次修改發生前的。下篇預告深入系列組件的生命周期新書推薦進階之路作者徐超畢業于浙江大學,碩士,資深前端工程師,長期就職于能源物聯網公司遠景智能。 文:徐超,《React進階之路》作者授權發布,轉載請注明作者及出處 React 深入系列3:Props 和 State React 深入系列,深...
摘要:深入系列,深入講解了中的重點概念特性和模式等,旨在幫助大家加深對的理解,以及在項目中更加靈活地使用。下篇預告深入系列組件的生命周期我的新書進階之路已上市,請大家多多支持鏈接京東當當 React 深入系列,深入講解了React中的重點概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項目中更加靈活地使用React。 React 的核心思想是組件化的思想,而React 組件的定...
摘要:在這篇文章中,我們就要實現的組件功能。這篇文章的代碼從零開始實現系列是前端最受歡迎的框架之一,解讀其源碼的文章非常多,但是我想從另一個角度去解讀從零開始實現一個,從層面實現的大部分功能,在這個過程中去探索為什么有虛擬為什么這樣設計等問題。 前言 在上一篇文章JSX和虛擬DOM中,我們實現了基礎的JSX渲染功能,但是React的意義在于組件化。在這篇文章中,我們就要實現React的組件功...
閱讀 3207·2021-09-22 15:05
閱讀 2763·2019-08-30 15:56
閱讀 1071·2019-08-29 17:09
閱讀 805·2019-08-29 15:12
閱讀 2088·2019-08-26 11:55
閱讀 3074·2019-08-26 11:52
閱讀 3382·2019-08-26 10:29
閱讀 1386·2019-08-23 17:19