我們來(lái)寫(xiě)上次提到的組件猜煮,計(jì)數(shù)器次员。
組件
/src
下新建一個(gè)文件 Counter.js
import React, {Component} from 'react'
import './Counter.css'
class Counter extends Component{
render(){
return(
<div>
<div className="counter">
<input type="button" className="counterLeftButton" value="-" />
<input type="text" value="0" />
<input type="button" className="counterRightButton" value="+" />
</div>
)
}
}
export default Counter
- 這里沒(méi)有用到元素渲染,就不用引入
ReactDOM
了王带。我們統(tǒng)一在index.js
中渲染淑蔚。這里還引入了一個(gè)對(duì)應(yīng)的 CSS 文件,稍微修飾一下愕撰。 - 注意
render
方法只能返回一個(gè)JSX元素刹衫,有多個(gè)并列元素時(shí),外層用<div>
包一下就好搞挣。 - 最后一行用于導(dǎo)出類(lèi)带迟,這樣在別的 js 文件中就可以引入了。如果不想寫(xiě)最后一行囱桨,可以在定義的時(shí)候直接這樣寫(xiě):
export default class Counter extends Component
嵌套
接下里仓犬,讓這個(gè) Counter
在頁(yè)面中顯示出來(lái),兩個(gè)辦法:
- 在
public/index.html
中加入一個(gè) HTML 元素舍肠,在src/index.js
中引入 Counter 并渲染到上面的 HTML元素中搀继。
<div id="counter"></div>
...
import Counter from './Counter'
...
ReactDOM.render(<Counter />, document.getElementById('counter'));
...
- 直接把
<Counter />
嵌套到之前 hello 所在的JSX
元素中:
...
import Counter from './Counter'
...
render(){
return(
<div>
hello
<Counter />
</div>
)
}
emmm...就這樣吧。當(dāng)然如果你愿意翠语,多放幾個(gè)也是沒(méi)問(wèn)題的叽躯。
...
render(){
const counters = []
for(var i = 0; i < 5; i++){
counters.push(<Counter/>)
}
return(
<div>
{counters}
</div>
)
}
...
事件
到現(xiàn)在為止,按鈕點(diǎn)了沒(méi)反應(yīng)啡专,也不能自己輸入數(shù)字险毁。是的制圈,React.js
中無(wú)法直接更改 input
元素的值们童。不過(guò)使用 React.js
提供的監(jiān)聽(tīng)事件機(jī)制,很容易就能做到鲸鹦,把 onChange
慧库,onClick
等等, 像是 onXxx
這種事件當(dāng)做屬性馋嗜,添加上對(duì)應(yīng)的處理方法齐板,設(shè)置到 JSX 元素上就可以了。
但是有一點(diǎn),React.js
會(huì)直接調(diào)用這個(gè)方法甘磨,并沒(méi)有通過(guò)對(duì)象調(diào)用橡羞,所以,如果要在方法中用 this
關(guān)鍵字济舆,需要自己綁定 bind
卿泽。
<input type="text" value="0" onChange={this.handleInputValueChange.bind(this)}/>
Counter
類(lèi)中加上 handleInputValueChange
方法
handleInputValueChange(event){
console.log(event.target.value)
}
然后,去修改 input 中
的值滋觉,你就能在控制臺(tái)看到了……
摔签夭,要直接在頁(yè)面上讓我看到啊混蛋,能不能給點(diǎn)力啊椎侠。
state
emmm...
看起來(lái)我們沒(méi)辦法直接在函數(shù)里訪問(wèn) JSX 元素啊第租,不過(guò),要是把 input
的 value
值設(shè)置為變量我纪,在函數(shù)里修改再體現(xiàn)在頁(yè)面上不就可以了慎宾。等同于,我們直接改了元素的 數(shù)據(jù)狀態(tài)浅悉。React.js
為組件提供了 state 機(jī)制璧诵,我們?cè)诶锩娲娣乓粋€(gè)變量 count
就好。
constructor () {
super()
this.state = { count: 0 }
}
handleInputValueChange(event){
this.state.count = event.target.value
}
...
<input type="text" value={this.state.count} ... />
...
你會(huì)發(fā)現(xiàn)仇冯,還是不行…… emmm ...
自己直接修改 this.state
中的數(shù)據(jù)之宿, React.js
不會(huì)給渲染的,這里需要調(diào)用 setState
:
this.setState({count: event.target.value});
同樣的苛坚,給兩個(gè) button 加上 onClick
事件:
<input type="button" value="-" onClick={this.handleCountDecrease.bind(this)}/>
...
<input type="button" value="+" onClick={this.handleCountIncrease.bind(this)}/>
實(shí)現(xiàn)這兩個(gè)方法比被,加上數(shù)據(jù)驗(yàn)證什么的,到現(xiàn)在為止泼舱,看起來(lái)似乎還不錯(cuò)等缀。
props
但是,這個(gè)組件除了在購(gòu)物車(chē)界面中使用娇昙,還有可能用在其他的地方尺迂,并且或許有另外的文本要求,這里使用了“-”冒掌,“+”噪裕,或許別的需求里需要其他字符,像是“<” 和 “>”股毫,so膳音,到此為止它的擴(kuò)展性還是不夠,如果可以在使用的時(shí)候直接在外部設(shè)置某些屬性铃诬,就更好了祭陷。比如這樣用:
<Counter leftButtonText="<" rightButtonText=">" />
我們?cè)诮M件 Counter
中提前設(shè)置好默認(rèn)值苍凛,通過(guò) this.props.參數(shù)名
使用:
static defaultProps = {
leftButtonText: "-",
rightButtonText: "+"
}
...
<input type="button" value={this.props.leftButtonText} .../>
<input type="text" .../>
<input type="button" value={this.props.rightButtonText} .../>
...
ta-da
不過(guò)傳進(jìn)來(lái)的
props
不能在組件內(nèi)部修改,需要改變的時(shí)候兵志,可以通過(guò)父組件重新渲染醇蝴。當(dāng)然,如果需要想罕,直接傳函數(shù)進(jìn)來(lái)也是可以的哑蔫。在 index.js
中定義函數(shù)并傳入:
handleCounterClick(event){
console.log("click handled by props")
}
render(){
return(
<Counter handleClick={this.handleCounterClick}/>
)
}
組件 Counter.js
中直接使用就好:
<div className="counter" onClick={this.props.handleClick}>...</div>
這下勉強(qiáng)算得上是一個(gè)組件吧。任何需要它出現(xiàn)的地方弧呐,直接使用 <Counter />
就OK了闸迷。
今天就到這里了。