ReactJs小書筆記(二)
ReactJs小書官方文檔:傳送門
17 前端應(yīng)用狀態(tài)管理——狀態(tài)提升
- 概念:當(dāng)平級的組件之間的需要進行數(shù)據(jù)傳遞的時候肉拓,需要將組件之間的共享的狀態(tài)交給組件附近最近的父節(jié)點保管后频,然后通過
props
把狀態(tài)傳遞給子組件,實現(xiàn)組件之間的數(shù)據(jù)共享暖途; - 總結(jié):當(dāng)某個狀態(tài)被多個組件依賴或者影響的時候卑惜,就把該狀態(tài)提升到這些組件的最近公共父組件中去管理,用 props 傳遞數(shù)據(jù)或者函數(shù)來管理這種依賴或著影響的行為驻售;
- 問題:一旦發(fā)生狀態(tài)提升露久,就需要修改原來保存這個狀態(tài)的組件的代碼,也要把整個數(shù)據(jù)傳遞路徑經(jīng)過的組件都修改一遍芋浮,好讓數(shù)據(jù)能夠一層層地傳遞下去;這樣對代碼的組織管理維護帶來很大的問題壳快。
18 掛載階段的組件生命周期(1)
- 組件初始化階段
- constructor():(構(gòu)造器)初始化組件纸巷;
- componentWillMount():組件掛載開始之前,也就是在組件調(diào)用 render 方法之前調(diào)用眶痰;
- render(): 將構(gòu)造好的 DOM 元素掛載到頁面;
- componentDidMount():組件掛載完成以后,也就是 DOM 元素已經(jīng)插入頁面后調(diào)用蜓耻;
- 組件的刪除階段
- 即將從頁面中刪除
- componentWillUnmount():組件對應(yīng)的 DOM 元素從頁面中刪除之前調(diào)用母蛛;
- 從頁面中刪除
19 掛載階段的組件生命周期(2)
利用生命周期函數(shù)實現(xiàn)一個時鐘的應(yīng)用:
import React, { Component } from 'react';
class Clock extends Component {
constructor () {
super()
this.state = {
date: new Date()
}
}
componentWillMount () {
this.timer = setInterval(() => {
this.setState({ date: new Date() })
}, 1000)
}
render () {
return (
<div>
<p>現(xiàn)在的時間是:</p>
<h3>
{this.state.date.toLocaleTimeString()}
</h3>
</div>
)
}
}
class App extends Component {
constructor () {
super()
this.state = { isShowClock: true }
}
handleShowOrHide () {
this.setState({
isShowClock: !this.state.isShowClock
})
}
render () {
return (
<div>
{this.state.isShowClock ? <Clock /> : null }
<button onClick={this.handleShowOrHide.bind(this)}>
顯示或隱藏時鐘
</button>
</div>
)
}
componentWillUnmount () {
clearInterval(this.timer)
}
}
export default App;
20 更新階段的組件生命周期
- shouldComponentUpdate(nextProps, nextState):你可以通過這個方法控制組件是否重新渲染;如果返回
false
組件就不會重新渲染七婴。這個生命周期在 React.js 性能優(yōu)化上非常有用祟偷; - componentWillReceiveProps(nextProps):組件從父組件接收到新的 props 之前調(diào)用;
- componentWillUpdate():組件開始重新渲染之前調(diào)用打厘;
- render() :將構(gòu)造好的 DOM 元素掛載到頁面修肠;
- componentDidUpdate():組件重新渲染并且把更改變更到真實的 DOM 以后調(diào)用;
21 ref 和 React.js中的DOM操作
-
React.js
中基本不會和DOM直接打交道户盯;React.js
提供了一系列的on*
方法幫助我們進行事件監(jiān)聽嵌施,所以 React.js 當(dāng)中不需要直接調(diào)用addEventListener
的 DOM API饲化;并且React.js
重新渲染的機制幫助我們免除了絕大部分的 DOM 更新操作; -
React.js
當(dāng)中提供了ref
屬性來幫助我們獲取已經(jīng)掛載的元素的DOM
節(jié)點吗伤,可以給某個 JSX 元素加上ref
屬性吃靠,如 進入頁面實現(xiàn)自動focus
到輸入框:
class AutoFocusInput extends Component {
componentDidMount () {
this.input.focus()
}
render () {
return (
<input ref={(input) => this.input = input} />
)
}
}
ReactDOM.render(
<AutoFocusInput />,
document.getElementById('root')
)
- 組件標(biāo)簽也可以使用
ref
屬性,獲取該組件的DOM節(jié)點足淆;
注意: ReactJs
中能不用 ref
就不用巢块;特別是要避免用 ref
來做 React.js 本來就可以幫助你做到的頁面自動更新的操作和事件監(jiān)聽,多余的 DOM 操作其實是代碼里面的“噪音”缸浦,不利于我們理解和維護夕冲。
22 props.children 和容器類組件
- 容器類的組件中可以填充任意的內(nèi)容,其定義了一種外層的結(jié)構(gòu)裂逐,如下:
import React, { Component } from 'react';
class Card extend Component {
constructor () {
super()
this.state= {}
}
render(
<div className='card'>
<div className='card-content'>
{this.props.content}
</div>
</div>
)
}
ReactDOM.render(
{/*通過給 Card 組件傳入一個 content 屬性歹鱼,這個屬性可以傳入任意的 JSX 結(jié)構(gòu)。然后在 Card 內(nèi)部會通過 {this.props.content} 把內(nèi)容渲染到頁面上*/}
<Card content={
<div>
<h2>React.js 小書</h2>
<div>開源卜高、免費弥姻、專業(yè)、簡單</div>
訂閱:<input />
</div>
} />,
document.getElementById('root')
)
- 使用
props.children
掺涛,能夠使得組件獲取所有嵌套在組件中的 JSX 結(jié)構(gòu)庭敦,如下:
import React, { Component } from 'react';
class Card extends Component {
render () {
return (
<div className='card'>
<div className='card-content'>
{this.props.children}
</div>
</div>
)
}
}
ReactDOM.render(
<Card>
<h2>React.js 小書</h2>
<div>開源、免費薪缆、專業(yè)秧廉、簡單</div>
訂閱:<input />
</Card>,
document.getElementById('root')
)
- 將
props.children
值打印出來,可以知道其本質(zhì)是一個數(shù)組拣帽,因而甚至可以在組件內(nèi)部把數(shù)組中的JSX
元素安置在不同的地方:
class Layout extends Component {
render () {
return (
<div className='two-cols-layout'>
<div className='sidebar'>
{this.props.children[0]}
</div>
<div className='main'>
{this.props.children[1]}
</div>
</div>
)
}
}
23 dangerouslySetHTML 和 style 屬性
23.1 dangerouslySetHTML 屬性
- 出于安全考慮的原因(XSS 攻擊)疼电,在
React.js
當(dāng)中所有的表達式插入的內(nèi)容都會被自動轉(zhuǎn)義,就相當(dāng)于 jQuery 里面的text(…)
函數(shù)一樣减拭,任何的 HTML 格式都會被轉(zhuǎn)義掉蔽豺,而React.js
提供了一個屬性dangerouslySetInnerHTML
,可以讓我們設(shè)置動態(tài)設(shè)置元素的innerHTML
:
class Editor extends Component {
constructor() {
super()
this.state = {
content: '<h1>React.js 小書</h1>'
}
}
// content中的內(nèi)容會完全展示拧粪,其中 h1 標(biāo)簽被轉(zhuǎn)義了修陡,顯示為字符串
render () {
return (
<div className='editor-wrapper'>
{this.state.content}
</div>
)
}
// 使用 `dangerouslySetInnerHTML` 屬性能夠設(shè)置動態(tài)設(shè)置元素的 `innerHTML`
render () {
return (
<div
className='editor-wrapper'
dangerouslySetInnerHTML={{__html: this.state.content}} />
)
}
}
23.2 style 屬性
在 React.js
中使用 style
屬性時,需要把 CSS 屬性變成一個對象再傳給元素:
<h1 style={{fontSize: '12px', color: 'red'}}>React.js 小書</h1>
其中 style
接受一個對象可霎,這個對象里面是這個元素的 CSS 屬性鍵值對魄鸦,原來 CSS 屬性中帶 -
的元素都必須要去掉 -
換成駝峰命名
;
24 PropTypes 和組件參數(shù)驗證
- 原由:JavaScript 的靈活性體現(xiàn)在弱類型癣朗、高階函數(shù)等語言特性上号杏,然而語言的弱類型很容易出 bug,所以在
React.js
中給組件的配置參數(shù)加上類型驗證; - 安裝使用
React
提供的第三方庫prop-types
進行類型驗證:npm install --save prop-types
盾致;
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Comment extends Component {
static propTypes = {
comment: PropTypes.object
}
render () {
const { comment } = this.props
return (
<div className='comment'>
<div className='comment-user'>
<span>{comment.username} </span>:
</div>
<p>{comment.content}</p>
</div>
)
}
-
prop-types
類型驗證參數(shù):
PropTypes.array
PropTypes.bool
PropTypes.func
PropTypes.number
PropTypes.object
PropTypes.string
PropTypes.node
PropTypes.element
-
prop-types
中通過isRequired
關(guān)鍵字來強制組件某個參數(shù)必須傳入:
...
static propTypes = {
comment: PropTypes.object.isRequired
}
...