摘要:所以還是印證那句話是組件渲染的唯一依據(jù)。所以對組件的進行約束是創(chuàng)建一個健康組件的必要條件。這里我們約束屬性類型為。使用方式運行結(jié)果沒有錯誤假如我們再加入一個子組件控制臺如預(yù)期報錯自定義約束萬物皆有其局限性。
日常扯淡前的廢話
上一篇我們介紹了React中State對象,說到它是組件渲染的唯一依據(jù);當(dāng)然我們也可以認(rèn)為State是組件中的數(shù)據(jù)源之一,它保存著組件渲染的所有數(shù)據(jù)并且可以直接作用于組件的渲染。這里有兩個地方我們畫了所謂的重點,因為要考啊。666...
PropsProps是Facebook為React組件提供的另一個神級API。顧名思義,prop(property)就是屬性的意思;props呢就是properties,當(dāng)然是很多個屬性啦。因為大千世界中每個事物不可能只有一個屬性,所以
處于人道主義考慮(扯淡...頭伸過來),React設(shè)計師就允許我們給組件設(shè)置很多很多的屬性,究竟有多多?當(dāng)然是看我們開發(fā)者自己的心情咯。組件的Props類似于DOM的attributes,隨便從某個網(wǎng)頁上inspect某個節(jié)點都能看到除了tag以外這個節(jié)點還掛載了很多別的東西,比如我們常用的class或者id都是節(jié)點的屬性。當(dāng)然React組件中Props的表現(xiàn)也相似。不過相對于普通DOM的屬性操作,React的屬性操作可以說是優(yōu)雅萬分,至于優(yōu)雅到什么程度,下面會有例子呈上。我們一步一步來!
首先看個例子:
創(chuàng)建組件。一個很簡單的組件,用來顯示從props傳來的文字
import React, {Component} from "react"; class Show extends Component { render() { return ({this.props.content}
) } } export default Show;
使用組件
從例子中可以看到向組件Show添加一個屬性很便捷,寫一個屬性名再賦值就行了(而如果DOM需要添加一個屬性的話則需要調(diào)用setAttribute方法,異常繁瑣)。其次,當(dāng)我們給組件添加了屬性之后,那么這些屬性就被掛載到組件的this.props中。因此這就是為什么我們可以在組件中通過this.props.content來獲取通過Props傳入的文字(而如果DOM需要獲取一個屬性的話則需要調(diào)用getAttribute方法)。我們看下實際效果:
當(dāng)然我們也可以在添加屬性的同時進行簡單的邏輯處理,我們改下Show組件使用方式:
看下實際效果:
簡直神器...不過筆者在這里想強調(diào)下
不建議寫復(fù)雜的邏輯。過于復(fù)雜的邏輯會降低代碼的可閱讀性,所以如果某個屬性值被添加前需要做很多的處理,請把邏輯封裝在一個方法里最后用處理結(jié)果進行賦值即可,比如醬紫:
class App extends Component { createContent = () => { let result = 0; for (let i = 0; i <= 100; i++) { result += i; } return result; }; render() { return (); } } export default App;Welcome to React
這樣可以將節(jié)點和邏輯分離,增加可閱讀性而且代碼會顯得很優(yōu)雅。
Props與State有什么不同?開頭有說過State并不是組件的唯一數(shù)據(jù)源,當(dāng)然上面的例子也證明了這一點。然而,它們又有什么不同?
1,Props被保存在this.props中,State被保存在this.state中;獲取也如此。Props給我們帶來了什么?
2,State可以在組件中更新,而Props不可以。至于為什么,我們接下來會有解釋;
3,State的更新會引發(fā)組件的重新渲染;Props的更新(從組件外)并不會引發(fā)該組件的重新渲染。因此如果想在Props被更新的同時引發(fā)渲染,那么就需要在componentwillreceiveprops中或者getDerivedStateFromProps中將更新后的Props同步給State,這樣可以觸發(fā)組件的重新渲染,其本質(zhì)還是借用State的力量。所以還是印證那句話:State是組件渲染的唯一依據(jù)。
從上面的例子中我們可以看出我們可以將組件之外的數(shù)據(jù)通過Props傳遞給組件,這一特性也同樣解決了父子組件之間通信的問題:如果父組件想傳遞數(shù)據(jù)給子組件,那么就可以將所需要傳遞的數(shù)據(jù)通過Props傳遞給子組件,上面的例子寫得很詳細(xì)。同樣,正是因為組件的Props大多都是父組件向子組件傳遞數(shù)據(jù)的通道,那么也就解釋了為什么在子組件中不能修改Props中數(shù)據(jù)的原因,因為別人傳給你的東西你改啥?出問題誰背鍋?所以筆者在這里強調(diào)一個:不要在組件中更改Props!。因為我們直接修改Props中基本類型的時候React會自動報錯,但是如果修改引用類型的話比如向數(shù)組添加一個元素,React并不會報錯因為地址沒變進而導(dǎo)致組件運行異常。
Props約束我們都知道JavaScript是一門弱類型的語言,與強類型語言比如Java不同,我們在定義一個變量的時候不會去聲明這個對象到底是整型還是浮點還是字符串等等...因此當(dāng)我們給組件添加屬性的時候很可能會引發(fā)組件運行出錯,比如組件有個屬性叫l(wèi)ist,我們希望它是一個數(shù)組并且在組件中對其使用了forEach。但是另一個開發(fā)人員引用這個組件的時候由于不清楚所以傳了一個數(shù)字,那么組件就掛了。所以對組件的Props進行約束是創(chuàng)建一個健康組件的必要條件。
約束工具本來React庫中包含了屬性監(jiān)測的包,但是在某個版本被移除了(筆者記不清從哪個版本開始)。不過我們?nèi)钥赏ㄟ^第三方包做同樣的事情 prop-types
類型約束其實Props約束最需要解決的是類型的約束,由于篇幅有限因此下面通過一個例子介紹下具體使用方法,詳情請點開鏈接自行查閱文檔
1,首先安裝第三方包是必須的 npm install prop-types --save
2,在文件中引入 import PropTypes from "prop-types"
3,修改之前的例子
import React, {Component} from "react"; import PropTypes from "prop-types"; class Show extends Component { render() { return () } } Show.propTypes = { content: PropTypes.string }; export default Show;{this.props.content}
我們創(chuàng)建完組件后并且在export之前,使用字面量對象對組件的propTypes進行賦值以確定該組件的Props類型。這里我們約束content屬性類型為string。假如我們傳入的數(shù)據(jù)是一個數(shù)組的話
那么運行的結(jié)果就出錯了:
index.js:2178 Warning: Failed prop type: Invalid prop `content` of type `array` supplied to `Show`, expected `string`."必需"約束
所謂的"必需"約束是指定組件必須要某個屬性,寫法如下:
Show.propTypes = { content: PropTypes.string.isRequired };
這里表示Show組件必須要有content這個屬性。假如沒有呢?
index.js:2178 Warning: Failed prop type: The prop `content` is marked as required in `Show`, but its value is `undefined`.
自然在控制臺就有報錯信息了。
子組件約束子組件約束主要是約束該組件的子組件有幾個,假如我們規(guī)定該組件只能有一個子組件就可以這么寫:
import React, {Component} from "react"; import PropTypes from "prop-types"; class Show extends Component { render() { return ({this.props.children}) } } Show.propTypes = { children: PropTypes.element }; export default Show;
此時我們是對該組件的children進行了約束,筆者認(rèn)為children是React的保留字所以我們在定義Props的時候不要使用children。
使用方式:
Hello World
運行結(jié)果沒有錯誤;
假如我們再加入一個子組件
Hello
World
控制臺如預(yù)期報錯:
Warning: Failed prop type: Invalid prop `children` of type `array` supplied to `Show`, expected a single ReactElement.自定義約束
萬物皆有其局限性。假如包提供的所有約束條件中沒有我們所期望怎么辦?那就自己寫一個自定義約束即可;寫法如下:
import React, {Component} from "react"; class Show extends Component { render() { return ({this.props.custom}
) } } Show.propTypes = { custom: function (props, propName, componentName) { if (typeof(props[propName]) === "string") { if (!props[propName].startsWith("React")) { return new Error(`The prop ${propName} of Component ${componentName} is not start with "React"`) } } else { return new Error(`The prop ${propName} of Component ${componentName} is not a string object`) } } }; export default Show;
此時我們并不需要引入第三方庫了,不過寫法和前面的用法一樣,只是字面量對象的值不是特定的類型而是一個校驗函數(shù),函數(shù)的第一個參數(shù)是該組件的props集;第二個參數(shù)是被該校驗函數(shù)監(jiān)測的prop名字(此時是custom;第三個參數(shù)是該組件的名字);從代碼可以看出我們這個自定義約束的目的是監(jiān)測該組件的custom屬性值是否為字符串并且以React開頭。首先我們添加正確的屬性值:
運行正常;然后添加錯誤的屬性值看看:
控制臺打印出了我們預(yù)設(shè)的提示信息:
Warning: Failed prop type: The prop custom of Component Show is not start with "React"
再者如果我們添加錯誤的類型值看看:
錯誤信息正常打?。?/p>
Warning: Failed prop type: The prop custom of Component Show is not a string object
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97690.html
摘要:首先賣個關(guān)子,下面我們一起來復(fù)習(xí)下小學(xué)還是初中的一枚數(shù)學(xué)知識。一旦更改了,會觸發(fā)組件的重新渲染。為了頁面渲染性能的考慮,有助于在中進行比較并確定是否重新渲染。 概念引入 對于React來說, 沒有State就沒有頁面的渲染, 我們也將什么都看不到 咋一聽怎么那么唬人?不過的確是這樣,正如標(biāo)題所言State是UI的靈魂。我們都知道React的核心思想之一是組件化,將頁面所展示的東西按一定...
摘要:官方對的介紹是意思就是提供了一種通過組件樹傳遞數(shù)據(jù)的方法,而無需在每個級別手動傳遞。這也是基于重要物證哈哈實例使用學(xué)習(xí)技術(shù)最終是要有產(chǎn)出的。依然被視作一個組件,不過不同的是它的子組件必須是一個方法并且該方法接收當(dāng)前對象并最終返回一個節(jié)點。 拋轉(zhuǎn)引玉 通過上一篇的科普我們知道如果父節(jié)點需要向子節(jié)點傳遞數(shù)據(jù),那么就得通過Props來實現(xiàn);那么擺在我們眼前的就有一個問題了:現(xiàn)有N個節(jié)點并且它...
摘要:深入系列,深入講解了中的重點概念特性和模式等,旨在幫助大家加深對的理解,以及在項目中更加靈活地使用。下篇預(yù)告深入系列組件的生命周期我的新書進階之路已上市,請大家多多支持鏈接京東當(dāng)當(dāng) React 深入系列,深入講解了React中的重點概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項目中更加靈活地使用React。 React 的核心思想是組件化的思想,而React 組件的定...
閱讀 3721·2021-10-18 13:34
閱讀 2415·2021-08-11 11:15
閱讀 1209·2019-08-30 15:44
閱讀 702·2019-08-26 10:32
閱讀 998·2019-08-26 10:13
閱讀 2072·2019-08-23 18:36
閱讀 1784·2019-08-23 18:35
閱讀 532·2019-08-23 17:10