react構(gòu)建指南
1,使用react需要用到腳手架 create react -app
使用之前需要裝有node ,因?yàn)樾枰玫絥ode的npm
安裝的時(shí)候需要全局安裝一個(gè)包,然后找個(gè)地方安裝myapp
替換淘寶鏡像 $ npm install cnpm -g --registry=https://registry.npm.taobao.org
以后使用cnpm會(huì)更快一些。
2,需要react router 路由管理
安裝所必須要的包:
npm install --save-dev react-router
npm install --save-dev react-router-dom
1,props
1,props初始化的時(shí)候使用,state是交互的時(shí)候使用,僅用戶(hù)交互,會(huì)隨著事件改變
2,需要從父組件傳遞用props,隨著時(shí)間推移不會(huì)改變用props
3,props不給初始值的話(huà),會(huì)默認(rèn)為true,但是不建議不給初始值
4,Text.defaultProps={//defaultProps可以給Text組件添加props
name:"hello"
}
5,傳遞props值,可以用<Greeting {...props}/>但是謹(jǐn)慎使用
組件類(lèi) :
<Mytab name="abcd" age="aaa"/>,//是一個(gè)React組件類(lèi)大寫(xiě)
component:
<span>{this.props.name},{this.props,age}</span>//在組件的時(shí)候獲取的時(shí)候用
特點(diǎn):1,屬性不好改,定死的
2,props一般用來(lái)傳遞數(shù)據(jù),父組件向子組件傳遞數(shù)據(jù)。
2,state
1,constructor(props){super(props)}//組件應(yīng)該始終調(diào)用基礎(chǔ)構(gòu)造函數(shù),一般來(lái)說(shuō)是初始化組件的時(shí)候執(zhí)行的。
2,在constructor里面可以直接this.state={};給state賦值
3,在其他方法里面不允許這么寫(xiě)。需要this.setState({...})
4,this.props和this.state是隊(duì)列更新dom,所以有可能會(huì)有沒(méi)排隊(duì)跟上的情況,不應(yīng)該用他的上一次值來(lái)做操作。解決 的辦法是用setState()來(lái)接受一個(gè)函數(shù)而不是上述對(duì)象,
this.setState((prevState, props)=>({
counter:prevState.counter+props.increment
}))
3,事件
1,react建議直接把監(jiān)聽(tīng)事件寫(xiě)在dom中
2,on...事件監(jiān)聽(tīng)只能作用于普通的html標(biāo)簽上,不能適用于組件上面
2,onClick={this.click}//綁定事件駝峰命名,寫(xiě)法如此
3,需要在construtor(){ this.click=this.click.bind(this)}//進(jìn)行事件綁定
然后lick(){this.setState({name:"000"})//才可以設(shè)置state的值}//不然設(shè)置不了state的值
4,如果嫌麻煩不愿bind,可以直接寫(xiě)成
click=()=>this.setState({name:"000"})//綁定事件第二種方法,就不用bind綁定了,是ES6寫(xiě)法
或者onClick={()=>this.click()}; 然后click(){this.setState({name:"000"})}//這樣也不用綁定bind了
4,組件
1,如果一個(gè)新組件 retrun null或者retrun false,則這個(gè)新組件講不會(huì)顯示,但是會(huì)執(zhí)行生命周期方法。
2, {a&&<span>aa</span>},如果a有值或者是true,則顯示aa組件,否則不顯示
3,false,null,undefined,值為這些的條件都不渲染。
4,不受控組件的解決方案:
<input type="checkbox">和<input type="radio">支持defaultChecked,//不能直接使用checked因?yàn)槭褂昧司筒豢勺兞? <select>與<textarea>和<input/>支持defaultValue。//不能直接使用value因?yàn)槭褂昧司筒豢勺兞?5,forceUpdate就是手動(dòng)重新render。有些變量不在state上,但是你又想達(dá)到這個(gè)變量
更新的時(shí)候,刷新render;
或者state里的某個(gè)變量層次太深,更新的時(shí)候沒(méi)有自動(dòng)觸發(fā)render。
這些時(shí)候都可以手動(dòng)調(diào)用forceUpdate自動(dòng)觸發(fā)render。所以建議使用immutable來(lái)操
作state,redux等f(wàn)lux架構(gòu)來(lái)管理state。
6,如果shouldComponentUpdate返回false,則render()不會(huì)被調(diào)用,就不更新?tīng)顟B(tài)。
5,組件之間的通信
1,父組件可以通過(guò)props的方式向子組件傳值
2,父組件可以通過(guò){...this.props}的方式傳入更深層子孫組件如:
// 通過(guò) ... 運(yùn)算符 向 Child_1_1 傳遞 Parent 組件的信息
class Child_1 extends Component{
render() {
return <div>
<p>{this.props.msg}</p>
<Child_1_1 {...this.props}/>
</div>
}
}
class Child_1_1 extends Component{
render() {
return <p>{this.props.msg}</p>
}
}
3,子向父組件通信
//可以利用回調(diào)函數(shù)
class Parent extends Component{ //父組件
state = {// es7語(yǔ)法
msg: ''
};
val=(data)=> this.setState(mag:data); //父組件的props中val方法
render() {
return <div>
<p>child msg: {this.state.msg}</p>
<Child value = {this.val} />//父組件的props
</div>;
}
}
class Child extends Component{//子組件
click(){
this.props.valuel('可以可以是隨便的值,也可是是此子組件的state')
}
render(){
return <div><button onClick={this.click} >點(diǎn)擊通信</button></div>
}
}
3,兄弟之間的通信 就是借助父組件做為中間橋梁,進(jìn)行通信的。
4,兄弟之間的這種通信模式會(huì)觸發(fā)很多次生命周期,故需要一種觀(guān)察者模式import eventProxy from '../eventProxy。還有更好的解決方式,redux,后續(xù)跟進(jìn)。
5,列表和秘鑰
1,可以使用map()來(lái)渲染li列表
function NumberList(props) {
let number=props.numbers;
let numlist=number.map((n)=> <Listi key={n.toString()} value={n}/>);//一定要加key區(qū)別與其他列表。
return <ul>{numlist}</ul>
}
function Listi(props){
return <li>{props.value+1}</li> //key不應(yīng)寫(xiě)在這里,應(yīng)寫(xiě)在根元素,可以在這里做數(shù)據(jù)操作+1
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
6,froms表單
1,普通的表單提交如果用在react上,實(shí)現(xiàn)這一點(diǎn)的標(biāo)準(zhǔn)方法就是一種稱(chēng)為受控組件的技術(shù)
2,textarea,select,input checkbox同樣受用.
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
7,propsTypes
1,PropTypes導(dǎo)出一系列驗(yàn)證器,可用于確保您接收的數(shù)據(jù)有效
2,PropsTypeys提供了不同的驗(yàn)證器
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
8,ref和js中的DOM操作
1,react封裝了很多個(gè).on事件,幾乎不需要和dom直接打交道,react其實(shí)也建議過(guò)多的使用ref
1,ref就相當(dāng)于一個(gè)DOM掛鉤,在某個(gè)元素上設(shè)置ref,就可以取得這個(gè)DOM元素進(jìn)行操作。
onclick(){ //點(diǎn)擊獲取ref設(shè)置的this.in的掛鉤,進(jìn)行DOM操作
this.in.focus();
}
render(){
return (
<div>
測(cè)試: <input ref={(input)=>{this.in=input;}} type="text" />//設(shè)置ref,this.in就是此input
<button onClick={this.onclick}>點(diǎn)擊獲取input焦點(diǎn)</button>
</div>
)
}
**4,注意{{}}**
<span tyle={{display:none}}}> 我是span1</span>//style要放到{{}}里面
容器組件
1,只放容器的組件,注意有結(jié)束標(biāo)簽
<BlackBorderContainer>
<div className='name'>My Name:Lucy</div>
<p className='age'>
My Age:<span>12</span>
</p>
</BlackBorderContainer>
class BlackBorderContainer extends Component{
render(){
return (<div>
{this.props.children[1]}<hr/>{this.props.children[0]}
</div>)
}
}
組件的生命周期
-> constructor() //初始化一些狀態(tài)
-> componentWillMount() // 加載ajax
-> render()
// 然后構(gòu)造 DOM 元素插入頁(yè)面
-> componentDidMount()
// ...
// 即將從頁(yè)面中刪除
-> componentWillUnmount()//清除一些狀態(tài)機(jī)
// 從頁(yè)面中刪除
componentWillMount(),創(chuàng)建之前
componentDidMount(),創(chuàng)建之后
組件輸出已經(jīng)呈現(xiàn)給DOM后,
componentWillReceiveProps()//組件的參數(shù)更新時(shí),就是組件接受一個(gè)新的任務(wù)
componentWillUpdate(),更新之前
componentDidMount(),更新之后
componentWillUnmount() 組件對(duì)應(yīng)的 DOM 元素從頁(yè)面中刪除之前調(diào)用
5,組件里面可以有子組件
6,創(chuàng)建列表 Mocha 調(diào)試用的 react全家桶系列之一
里面的有一個(gè)key 值,用來(lái)識(shí)別dom的唯一性,react發(fā)現(xiàn)如何存在就不重新創(chuàng)建,如果無(wú)就新建
下午創(chuàng)建一個(gè)列表
7,組件內(nèi)的節(jié)點(diǎn)
node 標(biāo)簽
怎么操作需要渲染的標(biāo)簽
ref 類(lèi)似于id
ref=“f1”
取 this.refs["f1]
8,在constructor中其實(shí)組件并沒(méi)有完全準(zhǔn)備好,因?yàn)榻M件還沒(méi)有徹底渲染出來(lái)。所以使用refs的時(shí)候,一定要注意。
9,默認(rèn)值,可以用default Value Checked 這樣是可以改的
10,事件冒泡:
Origin
1、React并不會(huì)通過(guò)String類(lèi)型的Html片段生成DOM
2、在componentWillReceiveProps中調(diào)用setState()不會(huì)觸發(fā)re-render
3、componentWillUpdate中不能調(diào)用this.setState()
4、在通過(guò)Ajax獲取到數(shù)據(jù),調(diào)用this.setState()之前,應(yīng)該通過(guò)this.isMounted()確定當(dāng)前的component已經(jīng)處在渲染完成的階段
5、父組件到子組件通過(guò)props傳遞數(shù)據(jù),子組件向父組件傳遞數(shù)據(jù)通過(guò)global event方式來(lái)處理,即在root element上接受所有子組件的事件處理
6、移動(dòng)設(shè)備的touch事件需手動(dòng)開(kāi)啟:React.initializeTouchEvents(true)
7、setState(data, callback)中的callback是在re-render完成之后調(diào)用的
61,簡(jiǎn)答的輸出
> ```class Mytab1 extends React.Component{
render(){
return(<div>
<span> 我是span1</span>
<span> 我是span2</span>
<span>我是span3</span></div>
)
}
}
class Mytab extends React.Component{
render(){
return (<div><ul className="tab">
<li>home</li>
<li>about us1</li>
<li>about us2</li>
<li>about us3</li>
<li>about us4</li>
</ul>
<Mytab1/>//組件類(lèi)
</div>);
}
}
ReactDOM.render(
<Mytab/>,//是一個(gè)React組件類(lèi)
document.getElementById('example')
);