React簡介
React在2013年5月開源恃逻。
React可能是將來web開發(fā)的主流工具枪狂。
React不是一個(gè)完整的MVC框架桂躏,頂多充當(dāng)一個(gè)View層。
-
MVC(Model+View+Controller)
不適用于前端開發(fā)劳殖,因?yàn)閂iew不允許知道用戶的輸入督暂,用戶的輸入是從Controller這一層進(jìn)入。然而用戶直接通過view層交互解藻,所以不可能不監(jiān)聽View層。
MVVM(Model+View+ViewModel)
——MVC的演變葡盗,更適合前端的開發(fā)模式螟左。
-
JSX 解析器
將JSX轉(zhuǎn)化成JS,在JS中直接編寫HTML觅够。
通過組建的state
來維護(hù)改變HTML DOM中的內(nèi)容胶背。
所有和Dom有關(guān)的都應(yīng)該通過框架來維護(hù),
將各功能做成組建——模板(容器)喘先、控件钳吟。
-
React組件及數(shù)據(jù)傳遞
React是一個(gè)組件化的框架,在項(xiàng)目開發(fā)之初需要將組件分化
搭建React Start Kit
1. 新建項(xiàng)目文件夾
這里取名newReactproject窘拯。
在該目錄下打開終端红且,初始化package.json
npm init
(可以輸入項(xiàng)目的名稱,這里為new-react-project
)
2. 安裝插件
npm install --dev-save browser-sync gulp gulp-webpack jsx-loader react react-dom
3. JSX轉(zhuǎn)換成JS的方法
在gulpfile.js中用webpack來將.jsx文件轉(zhuǎn)化為.js文件
(gulp的使用在其他的章節(jié)里面會(huì)詳細(xì)說明)
var webpackConfig = {
output:{
filename: 'index.js'
},
devtool: 'inline-source-map',
module:{
loaders:[
{test: /\.jsx$/, loader: 'jsx-loader'}
]
},
resolve:{
extensions:['','.js','.jsx']
}
}
gulp.task('script',function(){
gulp.src('./jsx/index.jsx') //以index.jsx為程序的入口
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('./www/script/'))
.pipe(browserSync.stream());//同步瀏覽器
})
如此一來涤姊,就可以在.jsx文件中撰寫開發(fā)代碼了暇番。
同時(shí),需要注意的是:index.jsx中需要引用react
var React = require('react');
var ReactDom = require('react-dom')
如果需要在index.jsx中引用的組件思喊,例如header,footer等壁酬,需要使用module.exports
module.exports = React.createClass({
render:function(){
return <p>這是一個(gè)React頁面</p>
}
})
注意:實(shí)際項(xiàng)目中,node_modules文件會(huì)被刪除 恨课,那么運(yùn)行項(xiàng)目的時(shí)候需要在終端輸入以下命令:
npm install gulp-cli -g
npm install
gulp
4. render語法
render一個(gè)變量時(shí)舆乔,要用html的方法來寫。
例如:
ReactDom.render(<Main />,document.getElementById('main'));
前面一個(gè)指render的內(nèi)容剂公,后一個(gè)變量是render的目的地
注意:ReactDom.render
是新版本的寫法希俩,舊版本是React.render()
//jsx語法中類名:
className="className";
//jsx語法中樣式:
style={{background:'#f00'}}
//jsx語法:
<tag prop={a:value}>{children}</tag>
//轉(zhuǎn)換成js是:
React.createElement(tag, {a:value}, children)
創(chuàng)建一個(gè)組件類,需要注意的幾點(diǎn):
- React中創(chuàng)建的組件類以大寫字母開頭纲辽,
駝峰命名法
- 在React中使用React.createClass方法創(chuàng)建一個(gè)組件類
- 核心代碼:每個(gè)組件類都必須實(shí)現(xiàn)自己的
render
方法颜武。輸出定義好的組件模板贫母。返回值:null、false盒刚、組件模板 - 注意:組件類只能包含一個(gè)頂層標(biāo)簽
5. React Component
- render:渲染html的方法
- getInitialState: 返回初始化的State的方法
- getDefaultProps:返回默認(rèn)props的方法
(state維護(hù)component內(nèi)部的狀態(tài)變化腺劣,props是component的外部的參數(shù)傳入component的方式)- propTypes:定義props的類型的屬性
- mixins:用來合并兩個(gè)組件的屬性
- statics:定義靜態(tài)對(duì)象的屬性
- displayName:定義該類在Debug信息中顯示的名稱
6. Props
Props是組件自身的屬性,一般用于嵌套的內(nèi)外層組件中因块,負(fù)責(zé)傳遞信息(通常是由父層組件向子組件傳遞)
注意:props對(duì)象中的屬性與組件的屬性一一對(duì)應(yīng)橘原,不要直接去修改props中的屬性值。
//定義WebName
var WebName = React.createClass({
render:function(){
return <h1>{this.props.webname}</h1>;
}
})
//定義WebLink
var WebLink = React.createClass({
render:function(){
return <a href={this.props.weblink}>{this.props.weblink}</a>;
}
})
//定義WebShow
var WebShow = React.createClass({
render:function(){
return (
<div>
<WebName webname={this.props.wname} />
<WebLink weblink={this.props.wlink} />
</div>
);
}
})
//渲染
ReactDOM.render(
<WebShow wname="網(wǎng)站名稱" wlink="http://www.baidu.com" />,
document.getElementById("container")
)
-
...this.props:
Props
提供的語法糖涡上,可以將父組件中的全部屬性都復(fù)制給子組件
例如:定義一個(gè)組件Link趾断,Link組件中只包含一個(gè)<a>
,我們不給<a>
設(shè)置任何屬性吩愧,所有屬性全部從父組件膚質(zhì)得到芋酌。代碼如下:
var Link = React.createClass({
render:function(){
return <a {...this.props}>{this.props.name}</a>
}
});
ReactDOM.render(
<Link name="百度"/>,
document.getElementById("container")
)
//這樣父組件上的屬性href和name都會(huì)被復(fù)制到子組件Link中的<a>上。
-
this.props.children:
children是一個(gè)例外雁佳,不是跟組件的屬性對(duì)應(yīng)的脐帝。children表示組建的所有子節(jié)點(diǎn)
var ListComponent = React.createClass({
render:function(){
return (
<ul>
{
/*
列表項(xiàng)數(shù)量以及內(nèi)容不確定,在創(chuàng)建模板時(shí)才能確定
利用this.props.children從父組件獲取需要展示的列表項(xiàng)內(nèi)容
獲取到列表項(xiàng)內(nèi)容后糖权,需要遍歷children逐行進(jìn)行設(shè)置
使用React.Children.map方法
該方法的返回值:數(shù)組對(duì)象
*/
React.Children.map(this.props.children, function(child){
//child是便利得到的父組件的子節(jié)點(diǎn)
return <li>{child}</li>
})
}
</ul>
)
}
});
//渲染
ReactDOM.render(
(
<ListComponent>
<h1>百度</h1>
<a >http://www.baidu.com</a>
</ListComponent>
),
);
7. 屬性驗(yàn)證 propTypes
組件類的屬性堵腹,用于驗(yàn)證組建實(shí)例的屬性是否符合要求
var ShowTitle = React.createClass({
propTypes: {
//title數(shù)據(jù)類型必須為字符串
title:React.PropTypes.string.isRequired
},
render:function(){
return <h1>{this.props.title}</h1>
}
});
ReactDOM.render(
<ShowTitle title="123" />,
document.getElementById("container")
)
-
設(shè)置組件屬性的默認(rèn)值
通過實(shí)現(xiàn)組件的getDefaultProps方法,對(duì)屬性設(shè)置默認(rèn)值星澳。
var MyTitle = React.createClass({
getDefaultProps: function(){
return {
title: "百度"
};
},
render: function(){
return <h1>{this.props.title}</h1>
}
});
ReactDOM.render(
<MyTitle />,
document.getElementById("container")
);
8. state:
state和props一樣都是組件自身的屬性疚顷,都可以用來傳遞數(shù)據(jù)。
在和用戶交互的過程中禁偎,組件的狀態(tài)可能需要更新腿堤,就會(huì)觸發(fā)組件的重新渲染。
先舉個(gè)例子說明React事件的引用:
//定義一個(gè)button組件如暖,綁定onClick事件
//React中的事件名稱首字母小寫笆檀,駝峰命名法
var MyButton = React.createClass({
handleClick: function(){
alert('點(diǎn)擊按鈕觸發(fā)的效果');
},
render: function(){
return (
<button onClick={this.handleClick}>{this.props.buttonTitle}</button>
)
}
});
ReactDOM.render(
<MyButton buttonTitle="按鈕" />,
document.getElementById("container")
);
在知道事件引用的方法后,再舉個(gè)經(jīng)典案例:
需求:創(chuàng)建一個(gè)CheckButton的組件装处,包含一個(gè)checkbox類型的input误债,復(fù)選框在選中和未選中的兩種狀態(tài)下回顯示不同的文字浸船,即根據(jù)狀態(tài)渲染妄迁。
var CheckButton = React.createClass({
//定義初始狀態(tài)
getInitialState: function(){
return {
//在這個(gè)對(duì)象中設(shè)置的屬性將會(huì)存儲(chǔ)在state中
//默認(rèn)狀態(tài)是:未選中
isCheck: false
}
},
//定義事件綁定的方法
handleChange: function(){
//修改狀態(tài)值,通過this.state讀取設(shè)置的狀態(tài)值
this.setState({
isCheck: !this.state.isCheck
});
},
render:function(){
//根據(jù)狀態(tài)值李命,設(shè)置顯示的文字
//在JSX語法中登淘,不能直接使用if..else函數(shù),使用三目運(yùn)算符
var text = this.state.isCheck ? "已選中" : "未選中";
return (
<div>
<input type="checkbox" onChange={this.handleChange} />
{text}
</div>
);
},
});
//渲染
ReactDOM.render(
<CheckButton />,
document.getElementById("container")
);
需要注意的時(shí):當(dāng)state發(fā)生變化時(shí)封字,會(huì)調(diào)用組件內(nèi)部的render方法
-
表單
舉例說明:
需求:定義一個(gè)組件黔州,將用戶在輸入框內(nèi)輸入的內(nèi)容進(jìn)行實(shí)時(shí)顯示
分析:組件與用戶交互過程中耍鬓,存在狀態(tài)的變化,即輸入框的值流妻。
var Input = React.createClass({
getInitialState: function(){
return (
value: "請(qǐng)輸入"
)牲蜀;
},
handleChange: function(event){
//通過event.target.value讀取用戶輸入的值
this.setState({
value: event.target.value
});
},
render: function(){
var value = this.target.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
)
},
});
ReactDOM.render(
<input />,
document.getElementById("container")
);
9. React Component生命周期時(shí)間
組件的生命周期分為三個(gè)狀態(tài)
:
-
Mounting
: 組件掛載,已插入真實(shí)DOM相關(guān)接口:
(1)
componentWillMount
- 組件將要掛載绅这。
在render之前執(zhí)行涣达,但僅執(zhí)行一次,即使多次重復(fù)渲染該組件证薇,或者改變了組件的state(2)
componentDidMount
- 組件已經(jīng)掛載度苔。
在render之后執(zhí)行,同一個(gè)組件重復(fù)渲染只執(zhí)行一次 -
Updating
: 組件更新浑度,正在被重新渲染相關(guān)接口:
(1)
componentWillReceiveProps
(object nextProps)- 已加載組件收到新的props之前調(diào)用寇窑,注意組件初始化渲染時(shí)則不會(huì)執(zhí)行(2)
shouldComponentUpdate
(object nextProps, object nextState) - 組件判斷是否重新渲染時(shí)調(diào)用。該接口實(shí)際是在組件收到了新的props或者新的state的時(shí)候會(huì)立即調(diào)用箩张,然后通過下面兩個(gè)方法來進(jìn)行更新(3)
componentWillUpdate
(object nextProps, object nextState) - 組件將要更新(4)
componentDidUpdate
(object prevProps, object prevState) - 組件已經(jīng)更新 -
Unmounting
: 組件移出甩骏,已移出真實(shí)DOM相關(guān)接口:
componentWillUnmount
- 在組件要被移除之前的時(shí)間點(diǎn)觸發(fā),可以利用該方法來執(zhí)行一些必要的清理組件的工作
生命周期中與props和state相關(guān)的接口:
(1)getDefaultProps
- 設(shè)置props屬性默認(rèn)值
(2)getInitialState
- 設(shè)置state屬性初始值
總結(jié)下來先慷,一共九個(gè)接口横漏,如下:
- componentWillMount:組件的html即將加載時(shí)調(diào)用
- componentDidMount:組件的html已經(jīng)加載時(shí)調(diào)用
- componentWillReceiveProps:組件props改變時(shí)調(diào)用
- shouldComponentUpdate:判定組件是否更新HTML
- componentWillUpdate:組件即將更新HTML時(shí)調(diào)用
- componentDidUpdate:組件HTML更新完后調(diào)用
- componentWillUnmount:組件HTML即將卸載時(shí)調(diào)用
- getDefaultProps:設(shè)置props屬性默認(rèn)值
- getInitialState:設(shè)置state屬性初始值
組件的生命周期可分為四個(gè)階段
:創(chuàng)建
、實(shí)例化
熟掂、更新
缎浇、銷毀
生命周期個(gè)階段介紹
var Demo = React.createClass({
/*
一、創(chuàng)建階段
流程:只調(diào)用getDefaultProps方法
*/
getDefaultProps: function(){
//在創(chuàng)建類的時(shí)候被調(diào)用赴肚,設(shè)置this.props的默認(rèn)值
console.log("getDefaultProps");
return {};
},
/*
二素跺、實(shí)例化階段
流程:
getInitialState,
componentWillMount,
render,
componentDidMount
*/
getInitialState: function(){
//設(shè)置this.state的默認(rèn)值
console.log("getInitialState");
return {};
},
componentWillMount: functon(){
//在render之前調(diào)用
console.log("componentWillMount");
},
render:function(){
//渲染并返回一個(gè)虛擬DOM
console.log("render");
return <div>Hello React</div>
},
componentDidMount: function(){
//在render之后調(diào)用
//在該方法中,React會(huì)使用render方法返回的虛擬DOM對(duì)象創(chuàng)建真實(shí)的DOM結(jié)構(gòu)
//可以在這個(gè)方法中讀取DOM節(jié)點(diǎn)
console.log("componentDidMount");
},
/*
三誉券、更新階段
流程:
componentWillReceiveProps,
shouldComponentUpdate (如果返回值是false指厌,后三個(gè)方法不執(zhí)行),
componentWillUpdate,
render,
componentDidUpdate
*/
componentWillReciveProps: function(){
console.log("componentWillReciveProps")
},
shouldComponentUpdate: function(){
//是否需要更新
console.log("shouldComponentUpdate");
return true;
},
componentWillUpdae: function(){
console.log("componentWillUpdae");
},
componentDidUpdate: functon(){
console.log("componentDidUpdate")
},
/*
四、銷毀階段
流程:componentWillUnmount
*/
componentWillUnmount: function(){
console.log("componentWillUnmount")
},
});
//第一次創(chuàng)建并加載組件
//將得到以下順序:getDefaultProps,getInitialState,componentWillMount,render,componentDidMount
ReactDOM.render(
<Demo />,
document.getElementById("container")
);
//第二次創(chuàng)建并加載組件
//將在第一次加載的基礎(chǔ)上踊跟,添加以下順序:componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate
ReactDOM.render(
<Demo />,
document.getElementById("container")
);
//移除組件
ReactDOM.unmountComponentAtNode(document.getElementById("container"))
10. 設(shè)置組件的樣式
- 內(nèi)連樣式
- 對(duì)象樣式
- 選擇器樣式
注意:在React
和HTML5
中踩验,樣式的書寫方式是有所區(qū)別的
主要體現(xiàn)在:
- HTML5以;結(jié)尾商玫,React以箕憾,結(jié)尾
- HTML5中key、value都不加引號(hào)拳昌,React中屬于JavaScript對(duì)象袭异,key的名字不能出現(xiàn)“-”,需要使用駝峰命名法炬藤。如果value為字符串御铃,需要加引號(hào)碴里。
- HTML5中,value如果是數(shù)字上真,需要帶單位咬腋,React中不需要帶單位。
//樣式
<style>
.pStyle {
font-size:20px;
}
</style>
//創(chuàng)建設(shè)置h1樣式對(duì)象
var hStyle = {
backgroundColor:"green",
color:"red"
}
var ShowMessage = React.createClass({
render:function(){
return(
//內(nèi)連樣式
<div style={{backgroundColor:"yellow",borderWidth:5,borderColor:"black",borderStyle:"solid"}}>
//對(duì)象樣式
<h1 style={hStyle}>{this.props.firstRow}</h1>
//選擇器樣式
<p className="pStyle">{this.props.secondRow}</p>
</div>
)
}
})
//渲染效果
ReactDOM.render(
<ShowMessage firstRow="第一行" secondRow="第二行"/>,
document.getElementById("container")
)
注意:在React中使用選擇器樣式設(shè)置組件樣式時(shí)睡互,屬性名不能使用class
帝火,因?yàn)?code>class是React
中的保留字,需要使用className
替換湃缎。
類似的還有使用htmlfor
替換for
犀填,因?yàn)?code>for也是React
中的保留字。
11. 復(fù)合組件 —— 也稱為組合組件嗓违,父子組件(創(chuàng)建多個(gè)組件合成一個(gè)組件)
//定義WebName組件
var WebName = React.createClass({
render:function(){
return <h1>網(wǎng)站名稱</h1>;
}
});
//定義WebLink組件
var WebLink = React.createClass({
render:function(){
return <a >http://www.baidu.com</a>;
}
});
//定義WebShow復(fù)合組件
var WebShow = React.createClass({
render:function(){
return (
<div>
<WebName />
<WebLink />
</div>
);
}
});
//渲染
ReactDOM.render(
<WebShow />,
document.getElementById("container")
);
注:以上所有內(nèi)容都是本人的學(xué)習(xí)筆記和總結(jié)九巡,僅供學(xué)習(xí)和參考,如果有遺漏或者不當(dāng)?shù)牡胤秸?qǐng)諒解蹂季,請(qǐng)勿轉(zhuǎn)載冕广。