JavaScript中React面向組件編程(上)
前言:
- React組件中默認(rèn)封裝了很多屬性,有的是提供給開(kāi)發(fā)者操作的,其中有三個(gè)屬性非常重要:state、props、refs。通過(guò)這三大核心屬性的使用,我們能夠?qū)崿F(xiàn)對(duì)組件的狀態(tài)進(jìn)行更新。
一,組件的基本理解和使用
1. 函數(shù)組件
<script type="text/babel"> function MyComponent() { return <h2>我是函數(shù)定義的組件(適用于簡(jiǎn)單組件的定義)</h2> } ReactDOM.render(<MyComponent />, document.getElementById('test')) </script>
函數(shù)組件的渲染過(guò)程
1.React解析了組件標(biāo)簽,找到了對(duì)應(yīng)的組件 2.發(fā)現(xiàn)這個(gè)組件是一個(gè)函數(shù)定義的,隨后調(diào)用該函數(shù),生成一個(gè)虛擬dom 3.最后將虛擬dom轉(zhuǎn)化成為真實(shí)dom,呈現(xiàn)在頁(yè)面中
2. 類式組件
<script type="text/babel"> class MyComponent extends React.Component { render() { return <h2>我是類定義的組件適用于復(fù)雜數(shù)據(jù)類型</h2> } } ReactDOM.render(<MyComponent />, document.getElementById('test')) </script>
類式組件的渲染過(guò)程
1.React解析了組件標(biāo)簽,找到了對(duì)應(yīng)的組件 2.發(fā)現(xiàn)這個(gè)組件是一個(gè)類定義的,隨后new出來(lái)一個(gè)實(shí)例對(duì)象,并通過(guò)該實(shí)例調(diào)用原型上的render方法 3.將render()返回的內(nèi)容生成一個(gè)虛擬dom 4.最后將虛擬dom轉(zhuǎn)化成為真實(shí)dom,呈現(xiàn)在頁(yè)面中
3.組件的注意事項(xiàng)
組件名必須首字母大寫(xiě) 虛擬DOM元素只能有一個(gè)根元素 虛擬DOM元素必須有結(jié)束標(biāo)簽
二,組件的三大核心屬性
1.state
state
是一個(gè)對(duì)象,它包含組件的數(shù)據(jù)狀態(tài),當(dāng)狀態(tài)變化時(shí),會(huì)觸發(fā)視圖的更新。你可以理解它的作用跟Vue
中的data
對(duì)象類似。
<script type="text/babel"> class Weather extends React.Component { constructor() { super() this.state = { isHot: false, wind: '微風(fēng)' } this.chang = this.chang.bind(this) } render() { let { isHot, wind } = this.state return <h2 onClick={this.chang}>今天的天氣很 {isHot ? "炎熱" : "涼爽"},{wind}</h2> }hang() { console.log(this) this.setState({ isHot: !this.state.isHot }) } } ReactDOM.render(<Weather />, document.getElementById('test')) </script>
1. 注意事項(xiàng)
1.組件中render方法中的this為組件實(shí)例對(duì)象 2.組件自定義的方法中this為undefined,如何解決? 1.強(qiáng)制綁定this: 通過(guò)函數(shù)對(duì)象的bind() 2.箭頭函數(shù) 3.狀態(tài)數(shù)據(jù),不能直接修改或更
2.簡(jiǎn)寫(xiě)方式
<script type="text/babel"> class Weather extends React.Component { state = { isHot: false, wind: '微風(fēng)' } render() { let { isHot, wind } = this.state return <h2 onClick={this.chang}>今天的天氣很 {isHot ? "炎熱" : "涼爽"},{wind}</h2> } chang = ()=>{ this.setState({ isHot: !this.state.isHot//這里的修改是一種合并,對(duì)比屬性的變化,如果有賦新值,沒(méi)有則跳過(guò) }) } } ReactDOM.render(<Weather />, document.getElementById('test')) let a = new Weather() </script>
設(shè)置狀態(tài):setState
setState(object nextState[, function callback])
不能在組件內(nèi)部通過(guò)this.state
修改狀態(tài),因?yàn)樵摖顟B(tài)會(huì)在調(diào)用 setState() 后被替換。
setState()
并不會(huì)立即改變 this.state,而是創(chuàng)建一個(gè)即將處理的 state
。setState()
并不一定是同步的,為了提升性能 React
會(huì)批量執(zhí)行 state
和 DOM
渲染。
setState()
總是會(huì)觸發(fā)一次組件重繪,除非在 shouldComponentUpdate()
中實(shí)現(xiàn)了一些條件渲染邏輯。
2.props
React
中組件通過(guò) props 屬性接收外部傳入的數(shù)據(jù),這點(diǎn) Vue 跟 React 是一致的- react 中說(shuō)的單向數(shù)據(jù)流值說(shuō)的就是 props,根據(jù)這一特點(diǎn)它還有一個(gè)作用:
組件之間的通信
。 - props 本身是
不可變的
,但是有一種情形它貌似可變,即是將父組件的 state作為子組件的 props
,當(dāng)父組件的 state 改變,子組件的 props 也跟著改變,其實(shí)它仍舊遵循了這一定律:props 是不可更改的
。
<script type="text/babel"> class MyComponent extends React.Component { render() { return ( <ul> <li>{this.props.name}</li> <li>{this.props.age}</li> </ul> ); } } ReactDOM.render( <MyComponent name="Bob" age="18" />, document.getElementById("test") ); </script>
props的特點(diǎn):
- 每個(gè)組件對(duì)象都會(huì)有props(properties的簡(jiǎn)寫(xiě))屬性
- 組件標(biāo)簽的所有屬性都保存在props中
- 內(nèi)部讀取某個(gè)屬性值:this.props.propertyName
- 作用:通過(guò)標(biāo)簽屬性從組件外 向組件內(nèi)傳遞數(shù)據(jù)(只讀 read only)
- 對(duì)props中的屬性值進(jìn)行類型限制和必要性限制
對(duì)props進(jìn)行限制
- 引入 prop-type 庫(kù),這就是專門(mén)用于限制 props 屬性的一個(gè)庫(kù)
- 導(dǎo)入 prop-type 庫(kù),到當(dāng)前頁(yè)面
- 根據(jù) Person.propTypes = {} 進(jìn)行限制
class MyComponent extends React.Component { render() { return ( <ul> <li>{this.props.name}</li> <li>{this.props.age}</li> </ul> ); } } // 校驗(yàn)類型 MyComponent.propTypes = { name: PropTypes.string, // 這里的 PropTypes 變量是全局掛載的 age: PropTypes.number, }; ReactDOM.render( <MyComponent name="Bob" age={18} />, document.getElementById("test") );
props的簡(jiǎn)寫(xiě)
<script type="text/babel"> class Weather extends React.Component { constructor(props) {//是否接受,取決于是否使用外部數(shù)據(jù) super(props)//只能上面接受了props,super()就去傳遞,否則后續(xù)的使用,可能就會(huì)出現(xiàn)問(wèn)題 } static propTypes = { name: PropTypes.string.isRequired,//限制name為字符串類型,必填 // age: PropTypes.number, sex: PropTypes.string, speak: PropTypes.func } static defaultProps = { sex: '男', } render() { let { name, age, sex } = this.props return ( <ul> <li>姓名:{name}</li> <li>性別:{sex}</li> <li>年齡:{age + 1}</li> </ul> ) } } ReactDOM.render(<Weather name="tom" age={26} sex="女" />, document.getElementById('test')) </script>
函數(shù)組件使用props
<script type="text/babel"> // 函數(shù)組件 function MyComponent(props) { return ( <ul> <li>{props.name}</li> <li>{props.age}</li> </ul> ); } // 校驗(yàn)類型 MyComponent.propTypes = { name: PropTypes.string, age: PropTypes.number, }; ReactDOM.render( <MyComponent name="Bob" age={18} />,document.getElementById("test") ); </script>
3.ref
- React 中的 Refs 可以讓我們?cè)L問(wèn) DOM 節(jié)點(diǎn),它有三種使用方式:字符串方式,回調(diào)函數(shù)式,createRef。
- 在 React 中 Refs 提供了一種方式,允許用戶訪問(wèn)DOM 節(jié)點(diǎn)或者在render方法中創(chuàng)建的React元素。
- 在 React單項(xiàng)數(shù)據(jù)流中,props是父子組件交互的唯一方式。要修改一個(gè)子組件,需要通過(guò)的新的props來(lái)重新渲染。
但是在某些情況下,需要在數(shù)據(jù)流之外強(qiáng)制修改子組件。被修改的子組件可能是一個(gè)React組件實(shí)例,也可能是一個(gè)DOM元素。對(duì)于這兩種情況,React 都通過(guò) Refs的使用提供了具體的解決方案。
回調(diào)函數(shù)方式
<script type="text/babel"> class MyComponent extends React.Component { handleAlert = () => { // 直接從組件實(shí)例上獲取 myInput console.log(this.myInput); // <input type="text"> alert(this.myInput.value); }; render() { return ( <div> {/* ref 直接定義成一個(gè)回調(diào)函數(shù),參數(shù)就是節(jié)點(diǎn)本身,將它賦值給組件的一個(gè) myInput 屬性 */} <input ref={(ele) => (this.myInput = ele)} type="text" /> <button onClick={this.handleAlert}>alert</button> </div> ); } } ReactDOM.render(<MyComponent />, document.getElementById("test")); </script>
React官方提示:
如果 ref 回調(diào)函數(shù)是以內(nèi)聯(lián)函數(shù)的方式定義的,在更新過(guò)程中它會(huì)被執(zhí)行兩次,第一次傳入?yún)?shù) null,然后第二次會(huì)傳入?yún)?shù) DOM 元素。這是因?yàn)樵诿看武秩緯r(shí)會(huì)創(chuàng)建一個(gè)新的函數(shù)實(shí)例,所以 React 清空舊的 ref 并且設(shè)置新的。通過(guò)將 ref 的回調(diào)函數(shù)定義成 class 的綁定函數(shù)的方式可以避免上述問(wèn)題,但是大多數(shù)情況下它是無(wú)關(guān)緊要的。
createRef -官方推薦使用
<script type="text/babel"> class MyComponent extends React.Component { // 創(chuàng)建 ref myInput = React.createRef(); handleAlert = () => { console.log(this.myInput.current); // 這里需要注意,元素是在 current 屬性上 alert(this.myInput.current.value); }; render() { return ( <div> {/* 將創(chuàng)建好的 ref 附加到元素上 */} <input ref={this.myInput} type="text" /> <button onClick={this.handleAlert}>alert</button> </div> ); } } ReactDOM.render(<MyComponent />, document.getElementById("test")); </script>
上面就是使用 React.createRef() 方法創(chuàng)建 ref 的方式,特別需要注意的是,創(chuàng)建出來(lái)的 ref 的值是一個(gè)對(duì)象,我們需要的 DOM 元素是放在對(duì)象的 current 屬性上,如上面的 this.myInput.current。
總結(jié)
以上就是React面向組件編程中的一部分。希望本篇文章能夠幫助到你!
到此這篇關(guān)于JavaScript中React面向組件編程的文章就介紹到這了,更多相關(guān)React面向組件編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React?Fiber?樹(shù)思想解決業(yè)務(wù)實(shí)際場(chǎng)景詳解
這篇文章主要為大家介紹了React?Fiber?樹(shù)思想解決業(yè)務(wù)實(shí)際場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12JavaScript中rem布局在react中的應(yīng)用
這篇文章主要介紹了JavaScript中rem布局在react中的應(yīng)用 的相關(guān)資料,需要的朋友可以參考下2015-12-12Hello?React的組件化方式之React入門(mén)小案例演示
這篇文章主要介紹了Hello?React的組件化方式-React入門(mén)小案例,本文通過(guò)Hello?React的案例,?來(lái)體驗(yàn)一下React開(kāi)發(fā)模式,?以及jsx的語(yǔ)法,需要的朋友可以參考下2022-10-10react使用useState修改對(duì)象或者數(shù)組的值無(wú)法改變視圖的問(wèn)題
這篇文章主要介紹了react使用useState修改對(duì)象或者數(shù)組的值無(wú)法改變視圖的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法
本篇文章主要介紹了react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12React項(xiàng)目經(jīng)驗(yàn)總結(jié)及遇到的坑
這篇文章主要介紹了React項(xiàng)目經(jīng)驗(yàn)總結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07