React 特點
- 聲明式設計 −React采用聲明範式,可以輕松描述應用。
- 高效 −React通過對DOM的模拟,最大限度地減少與DOM的互動。
- 靈活 −React可以與已知的庫或架構很好地配合。
- JSX − JSX 是 JavaScript 文法的擴充。React 開發不一定使用 JSX ,但我們建議使用它。
- 元件 − 通過 React 建構元件,使得代碼更加容易得到複用,能夠很好的應用在大項目的開發中。
- 單向響應的資料流 − React 實作了單向響應的資料流,進而減少了重複代碼,這也是它為什麼比傳統資料綁定更簡單。
-
官網位址
<!-- more -->
簡單Demo
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script>
<script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script>
<script src="http://static.runoob.com/assets/react/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
引入依賴
執行個體中我們引入了三個庫: react.min.js 、react-dom.min.js 和 browser.min.js:
react.min.js - React 的核心庫
react-dom.min.js - 提供與 DOM 相關的功能
browser.min.js - 用于将 JSX 文法轉為 JavaScript 文法
React代碼
<script type="text/babel"></script>
React JSX文法
React 使用 JSX 來替代正常的 JavaScript。JSX 是一個看起來很像 XML 的 JavaScript 文法擴充。我們不需要一定使用 JSX,但它有以下優點:
JSX 執行更快,因為它在編譯為 JavaScript 代碼後進行了優化。
它是類型安全的,在編譯過程中就能發現錯誤。
使用 JSX 編寫模闆更加簡單快速。
簡單嵌套元素
JSX 看起來類似 HTML ,我們可以看下執行個體:
ReactDOM.render方法接受兩個參數:
一個虛拟 DOM 節點和一個真實 DOM 節點,作用是将虛拟 DOM 挂載到真實 DOM。
執行個體:Hello, world!
ReactDOM.render(content,element);
ReactDOM.render(<h1>Hello, world!</h1>,document.getElementById('example'));
index1
複雜嵌套元素
我們可以在以上代碼中嵌套多個 HTML 标簽,需要使用一個 div 元素包裹它,執行個體中的 p 元素添加了自定義屬性 data-myattribute,添加自定義屬性需要使用 data- 字首。
執行個體:文字
ReactDOM.render(
<div>
<h1>菜鳥教程</h1>
<h2>歡迎學習 React</h2>
<p data-myattribute = "somevalue">這是一個很不錯的 JavaScript 庫!</p>
</div>,
mountNode
);
index2
JavaScript 表達式
我們可以在 JSX 中使用 JavaScript 表達式。表達式寫在花括号 {} 中。執行個體如下:
執行個體:計算
ReactDOM.render(
<div><h1>{1+1}</h1></div>,mountNode
);
index3
判斷語句
在 JSX 中不能使用 if else 語句,但可以使用 conditional (三元運算) 表達式來替代。以下執行個體中如果變量 i 等于 1 浏覽器将輸出 true, 如果修改 i 的值,則會輸出 false.
執行個體:判斷
const i = 1;
ReactDOM.render(
<div>
<h1>{i == 1 ? 'True!' : 'False'}</h1>
</div>,
mountNode
);
index4
樣式
React 推薦使用内聯樣式。我們可以使用 camelCase 文法來設定内聯樣式. React 會在指定元素數字後自動添加 px 。以下執行個體示範了為 h1 元素添加 myStyle 内聯樣式:
執行個體:CSS樣式
const myStyle = {
fontSize: 100,
lineHeight: '30px',
color: '#FF0000'
};
ReactDOM.render(
<h1 style = {myStyle}>菜鳥教程</h1>,mountNode
);
ReactDOM.render(<h1 style = {{fontSize: 100,lineHeight: '30px',color: '#FF0000'}}>菜鳥教程</h1>,mountNode);
ReactDOM.render(<h1 className = 'class_name'>菜鳥教程</h1>,mountNode);
index5
注釋
注釋需要寫在花括号中,執行個體如下:
執行個體:注釋
ReactDOM.render(
<div>
<h1>菜鳥教程</h1>
{/*注釋...*/}
</div>,mountNode
);
React.Component元件
基礎文法
HTML 标簽 vs. React 元件
React 可以渲染 HTML 标簽 (strings) 或 React 元件 (classes)。要渲染 HTML 标簽,隻需在 JSX 裡使用小寫字母的标簽名。
要渲染 React 元件,隻需建立一個大寫字母開頭的本地變量。
執行個體:建立元件
class DivElement extends React.Component{
render() {
return (
<div className="foo">arr</div>
);
}
}
ReactDOM.render(<DivElement />, mountNode);
執行個體:元件嵌套
class MyComponent extends React.Component{
render() {
return <div className="MyComponent">arr</div>;
}
}
class DivElement extends React.Component{
render() {
return <MyComponent />;
}
}
ReactDOM.render(<DivElement />, mountNode);
React 的 JSX 使用大、小寫的約定來區分本地元件的類和 HTML 标簽。
注意:
由于 JSX 就是 JavaScript,一些辨別符像 class 和 for 不建議作為 XML 屬性名。作為替代,React DOM 使用 className 和 htmlFor 來做對應的屬性。
執行個體:元件文法
class HelloMessage extends React.Component{
render() {
return <div className="HelloMessage">arr</div>;
}
}
class HelloMessage extends React.Component{
render() {
return (
<div className="HelloMessage">arr</div>
);
}
}
React.Component方法用于生成一個元件類 HelloMessage。<HelloMessage /> 執行個體元件類并輸出資訊。
注意:原生 HTML 元素名以小寫字母開頭,而自定義的 React 類名以大寫字母開頭,比如 HelloMessage 不能寫成 helloMessage。除此之外還需要注意元件類隻能包含一個頂層标簽,否則也會報錯。
如果我們需要向元件傳遞參數,可以使用 this.props 對象,執行個體如下:
執行個體:擷取父元素的值
class DivElement extends React.Component{
render() {
return (
<div className="foo">{this.props.name}</div>
);
}
}
ReactDOM.render(<DivElement name="Runoob" />, mountNode);
以上執行個體中 name 屬性通過 this.props.name 來擷取(自身的數字)。
注意,在添加屬性時, class 屬性需要寫成 className ,for 屬性需要寫成 htmlFor ,這是因為 class 和 for 是 JavaScript 的保留字。
複合元件
通過建立多個元件來合成一個元件,即把元件的不同功能點進行分離。
以下執行個體我們實作了輸出網站名字和網址的元件:
執行個體:連結
class WebSite extends React.Component{
render() {
return (
<div className={this.props.name}><Name name={this.props.name} /><Link site={this.props.site} /></div>
);
}
}
class Name extends React.Component{
render() {
return (
<h1>{this.props.name}</h1>
);
}
}
class Link extends React.Component{
render() {
return (
<a href={this.props.site}>{this.props.site}</a>
);
}
}
ReactDOM.render(<WebSite name="菜鳥教程" site=" http://www.runoob.com" />, mountNode);
React State(狀态)
把元件看成是一個狀态機(State Machines)。通過與使用者的互動,實作不同狀态,然後渲染 UI,讓使用者界面和資料保持一緻。React 裡,隻需更新元件的 state,然後根據新的 state 重新渲染使用者界面(不要操作 DOM)。
constructor()初始狀态
執行個體:點選喜歡&不喜歡
class LikeButton extends React.Component{
constructor() {
super();
this.state ={liked: false};
}
handleClick() {
this.setState({
liked: !this.state.liked
});
}
render() {
let text = this.state.liked ? '喜歡' : '不喜歡';
return (
<p onClick={this.handleClick.bind(this)}>你<b>{text}</b>我。點我切換狀态。</p>
);
}
};
ReactDOM.render(<LikeButton />, mountNode);
handleClick = ()=>{
this.setState({
liked: !this.state.liked
});
}
constructor是元件的構造函數,會在建立執行個體時自動調用。
...args表示元件參數,super(...args)是 ES6 規定的寫法。
this.state對象用來存放内部狀态,這裡是定義初始狀态,也就是一個對象,這個對象可以通過 this.state 屬性讀取。當使用者點選元件,導緻狀态變化,this.setState 方法就修改狀态值,每次修改以後,自動調用 this.render 方法,再次渲染元件。
onClick={this.handleClick.bind(this)}綁定事件,傳回參數。
e.target.value綁定事件後的傳回值。
執行個體:輸入文字實時顯示
class MyTitle extends React.Component{
constructor() {
super();
this.state ={name: 'can you speek English!'};
}
handleChange(e) {
let name = e.target.value;
this.setState({
name: name
});
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange.bind(this)} />
<p>luuman,{this.state.name}</p>
</div>
);
}
}
ReactDOM.render(<MyTitle />, mountNode);
React Props
props通過元件擷取資料
基礎文法
執行個體:資料傳遞
class HelloMessage extends React.Component{
render(){
return <h1>Hello {this.props.name}</h1>;
}
}
ReactDOM.render(
<HelloMessage name="Runoob" />,mountNode
);
執行個體中 name 屬性通過 this.props.name 來擷取。
defaultProps預設值
預設Props:你可以通過defaultProps()方法為props設定預設值,執行個體如下:
class HelloMessage extends React.Component{
render(){
return <h1>Hello {this.props.name}</h1>;
}
}
HelloMessage.defaultProps = {
name: 'Runoob'
}
ReactDOM.render(<HelloMessage />,mountNode);
class WebSite extends React.Component{
render() {
return (
<div className={this.props.name}><Name name={this.props.name} /><Link site={this.props.site} /></div>
);
}
}
WebSite.defaultProps ={
name: "菜鳥教程",
site: "http://www.runoob.com"
}
class Name extends React.Component{
render() {
return (
<h1>{this.props.name}</h1>
);
}
}
class Link extends React.Component{
render() {
return (
<a href={this.props.site}>{this.props.site}</a>
);
}
}
ReactDOM.render(<WebSite />, mountNode);
this.props.children
執行個體:點選次數
class NotesList extends React.Component{
render(){
return(
<ol>{
React.Children.map(this.props.children,function(child){
console.log(child);
return <li>{child}</li>
})
}</ol>
);
}
}
ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
<span>world</span>
<span>world</span>
</NotesList>,
mountNode
);
PropTypes驗證
Props 使用propTypes,它可以保證我們的應用元件被正确使用,React.PropTypes 提供很多驗證器 (validator) 來驗證傳入資料是否有效。當向 props 傳入無效資料時,JavaScript 控制台會抛出警告。
執行個體:判斷元件屬性title是否為字元串:
const name = 123;
console.log(name);
class HelloMessage extends React.Component{
render(){
return <h1>Hello {this.props.title}</h1>;
}
}
HelloMessage.propTypes = {
title: React.PropTypes.string
}
ReactDOM.render(<HelloMessage title={name} />,mountNode);
如果 title 使用數字變量,控制台會出現以下錯誤資訊:
Warning: Failed prop type: Invalid prop `title` of type `number` supplied to `HelloMessage`, expected `string`.
PropTypes屬性值
.propTypes = {
// 可以聲明 prop 為指定的 JS 基本資料類型,預設情況,這些資料是可選的
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol,
// 可以被渲染的對象 numbers, strings, elements 或 array
optionalNode: React.PropTypes.node,
// React 元素
optionalElement: React.PropTypes.element,
// 用 JS 的 instanceof 操作符聲明 prop 為類的執行個體。
optionalMessage: React.PropTypes.instanceOf(Message),
// 用 enum 來限制 prop 隻接受指定的值。
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// 可以是多個對象類型中的一個
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// 指定類型組成的數組
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// 指定類型的屬性構成的對象
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// 特定 shape 參數的對象
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// 任意類型加上 `isRequired` 來使 prop 不可空。
requiredFunc: React.PropTypes.func.isRequired,
// 不可空的任意類型
requiredAny: React.PropTypes.any.isRequired,
// 自定義驗證器。如果驗證失敗需要傳回一個 Error 對象。不要直接使用 `console.warn` 或抛異常,因為這樣 `oneOfType` 會失效。
customProp(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
customArrayProp: React.PropTypes.arrayOf(
function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
}
)
}
state和props差別
在于props是不可變的,而子元件隻能通過props來擷取資料。
而state可以根據與使用者互動來改變。這就是為什麼有些容器元件需要定義state來更新和修改資料。
以下執行個體示範了如何在應用中組合使用state和props。我們可以在父元件中設定state,并通過在子元件上使用props将其傳遞到子元件上。在render函數中,我們設定name和site來擷取父元件傳遞過來的資料。
執行個體:連結
class WebSite extends React.Component{
constructor(props) {
super(props);
this.state = {
name: "菜鳥教程",
site: "http://www.runoob.com"
};
}
render(){
return <div><Name name={this.state.name} /><Link site={this.state.site} /></div>
}
}
class Name extends React.Component{
render(){
return <h1>{this.props.name}</h1>
}
}
class Link extends React.Component{
render(){
return <a href={this.props.site}>{this.props.site}</a>
}
}
ReactDOM.render(<WebSite />,mountNode);
React 元件 API
在本章節中我們将讨論 React 元件 API。
基礎文法
mixins去重
const ExampleMixin = {
componentDidMount(){
// bind some event listeners here
}
componentWillUnmount(){
// unbind those events here!
}
}
class ExampleComponent extends React.Component{
mixins: [ExampleMixin];
render(){}
}
class AnotherComponent extends React.Component{
mixins: [ExampleMixin];
render(){}
}
<!-- 設定狀态:setState
setState(object nextState[, function callback])
參數說明
nextState,将要設定的新狀态,該狀态會和目前的state合并
callback,可選參數,回調函數。該函數會在setState設定成功,且元件重新渲染後調用。
合并nextState和目前state,并重新渲染元件。setState是React事件處理函數中和請求回調函數中觸發UI更新的主要方法。
關于setState
不能在元件内部通過this.state修改狀态,因為該狀态會在調用setState()後被替換。
setState()并不會立即改變this.state,而是建立一個即将處理的state。setState()并不一定是同步的,為了提升性能React會批量執行state和DOM渲染。
setState()總是會觸發一次元件重繪,除非在shouldComponentUpdate()中實作了一些條件渲染邏輯。 -->
執行個體:點選次數
class Counter extends React.Component{
constructor(){
super();
this.state = {
clickCount: 0
};
}
handleClick(){
this.setState({
clickCount: this.state.clickCount +1
});
}
render(){
return <h2 onClick={this.handleClick.bind(this)}>點我!點選次數為: {this.state.clickCount}</h2>;
}
}
ReactDOM.render(<Counter />,mountNode);
<!--
執行個體中通過點選 h2 标簽來使得點選計數器加 1。
替換狀态:replaceState
replaceState(object nextState[, function callback])
nextState,将要設定的新狀态,該狀态會替換目前的state。
callback,可選參數,回調函數。該函數會在replaceState設定成功,且元件重新渲染後調用。
replaceState()方法與setState()類似,但是方法隻會保留nextState中狀态,原state不在nextState中的狀态都會被删除。
設定屬性:setProps
setProps(object nextProps[, function callback])
nextProps,将要設定的新屬性,該狀态會和目前的props合并
callback,可選參數,回調函數。該函數會在setProps設定成功,且元件重新渲染後調用。
設定元件屬性,并重新渲染元件。
props相當于元件的資料流,它總是會從父元件向下傳遞至所有的子元件中。當和一個外部的JavaScript應用內建時,我們可能會需要向元件傳遞資料或通知ReactDOM.render()元件需要重新渲染,可以使用setProps()。
更新元件,我可以在節點上再次調用ReactDOM.render(),也可以通過setProps()方法改變元件屬性,觸發元件重新渲染。
替換屬性:replaceProps
replaceProps(object nextProps[, function callback])
nextProps,将要設定的新屬性,該屬性會替換目前的props。
callback,可選參數,回調函數。該函數會在replaceProps設定成功,且元件重新渲染後調用。
replaceProps()方法與setProps類似,但它會删除原有
props
強制更新:forceUpdate
forceUpdate([function callback])
參數說明
callback,可選參數,回調函數。該函數會在元件render()方法調用後調用。
forceUpdate()方法會使元件調用自身的render()方法重新渲染元件,元件的子元件也會調用自己的render()。但是,元件重新渲染時,依然會讀取this.props和this.state,如果狀态沒有改變,那麼React隻會更新DOM。
forceUpdate()方法适用于this.props和this.state之外的元件重繪(如:修改了this.state後),通過該方法通知React需要調用render()
一般來說,應該盡量避免使用forceUpdate(),而僅從this.props和this.state中讀取狀态并由React觸發render()調用。
擷取DOM節點:findDOMNode
DOMElement findDOMNode()
傳回值:DOM元素DOMElement
如果元件已經挂載到DOM中,該方法傳回對應的本地浏覽器 DOM 元素。當render傳回null 或 false時,this.findDOMNode()也會傳回null。從DOM 中讀取值的時候,該方法很有用,如:擷取表單字段的值和做一些 DOM 操作。
判斷元件挂載狀态:isMounted
bool isMounted()
傳回值:true或false,表示元件是否已挂載到DOM中
isMounted()方法用于判斷元件是否已挂載到DOM中。可以使用該方法保證了setState()和forceUpdate()在異步場景下的調用不會出錯。
本文參考:http://itbilu.com/javascript/... -->
React 元件生命周期
元件的生命周期可分成三個狀态:Mounting、Updating、Unmounting
Mounting:已插入真實 DOM
constructor()
componentWillMount()
在渲染前調用,在用戶端也在服務端。
render()
在渲染時調用
componentDidMount()
在第一次渲染後調用,隻在用戶端。之後元件已經生成了對應的DOM結構,可以通過this.getDOMNode()來進行通路。
如果你想和其他JavaScript架構一起使用,可以在這個方法中調用setTimeout, setInterval或者發送AJAX請求等操作(防止異部操作阻塞UI)。
Updating:正在被重新渲染
componentWillReceiveProps()
在元件接收到一個新的prop時被調用。這個方法在初始化render時不會被調用。
shouldComponentUpdate()
傳回一個布爾值。在元件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。
可以在你确認不需要更新元件時使用。
componentWillUpdate()
在元件接收到新的props或者state但還沒有render時被調用。在初始化時不會被調用。
render()
componentDidUpdate()
在元件完成更新後立即調用。在初始化時不會被調用。
Unmounting:已移出真實 DOM
componentWillUnmount()
在元件從 DOM 中移除的時候立刻被調用。
執行個體:定時器,每隔100毫秒重新設定元件的透明度,并重新渲染
class Hello extends React.Component{
constructor() {
super();
this.state = {
opacity: 1.0
}
}
componentDidMount(){
this.timer = setInterval(function(){
let opacity = this.state.opacity;
opacity -= .05;
if(opacity < .1){
opacity = 1.0;
}
this.setState({
opacity: opacity
})
}.bind(this),100)
}
render(){
return(
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
)
}
}
ReactDOM.render(<Hello name="world" />,mountNode);
執行個體:點選效果
以下執行個體初始化 state , setNewnumber 用于更新 state。所有生命周期在 Content 元件中。
class Button extends React.Component{
constructor() {
super();
this.state = {
data:0
}
}
setNewNumber(){
this.setState({
data: this.state.data + 1
})
}
render(){
return(
<div>
<button onClick={this.setNewNumber.bind(this)}>INCREMENT</button>
<Content myNumber={this.state.data}></Content>
</div>
)
}
}
class Content extends React.Component{
componentWillMount(){
console.log('Component WILL MOUNT!')
}
componentDidMount(){
console.log('Component DID MOUNT!')
}
componentWillReceiveProps(newProps) {
console.log('Component WILL RECEIVE PROPS!')
}
shouldComponentUpdate(newProps, newState) {
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('Component WILL UPDATE!');
}
componentDidUpdate(prevProps, prevState) {
console.log('Component DID UPDATE!')
}
componentWillUnmount(){
console.log('Component WILL UNMOUNT!')
}
render(){
return(
<div>
<h3>{this.props.myNumber}</h3>
</div>
)
}
}
ReactDOM.render(<Button />,mountNode);
執行個體:統計時間
class Timer extends React.Component{
constructor(props) {
super(props);
this.state = {secondsElapsed: 0};
}
tick(){
this.setState((prevState) => ({
secondsElapsed: prevState.secondsElapsed + 1
}));
}
componentDidMount(){
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount(){
clearInterval(this.interval);
}
render(){
return (
<div>Seconds Elapsed: {this.state.secondsElapsed}</div>
);
}
}
ReactDOM.render(<Timer />, mountNode);
Lists and Keys清單周遊
JSX 允許在模闆中插入數組,數組會自動展開所有成員:
const arr = [
<h1>菜鳥教程</h1>,
<h2>學的不僅是技術,更是夢想!</h2>,
];
ReactDOM.render(
<div>{arr}</div>,mountNode
);
index6
Array.map
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number,key) =>
<li key={key}>{number}</li>
);
console.log(listItems);
ReactDOM.render(<ul>{listItems}</ul>,mountNode);
const listItems = numbers.map(function(number,keys){
return(
<li key={keys}>
{number}
</li>
)
});
Array.forEach 周遊
Array.forEach((e) => {
alert(e);
})
Array.forEach(function(e){
alert(e);
})
let repos = this.state.data.items;
let repoList = [];
repos.forEach((p,keys) => {
let item = <li key={keys}><a href={p.html_url}>{p.name}</a>({p.stargazers_count} stars)<br />{p.description}</li>;
repoList.push(item);
})
let repos = this.state.data.items;
let repoList = repos.map(function(repo,index){
return(
<li key={index}>
<a href={repo.html_url}>{repo.name}</a>({repo.stargazers_count} stars)<br />
{repo.description}
</li>
);
});
Array.splice 删除
Array.filter
方法建立一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素
Array.every
Array.push
Handling Events綁定事件
Forms表單
基礎文法
執行個體:輸入文字實時顯示
class HelloMessage extends React.Component{
constructor(){
super();
this.state = {
value: 'Hello World!'
};
}
handleChange(even){
this.setState({
value: even.target.value
})
}
render(){
let value = this.state.value;
return(
<div>
<input type='text' value={value} onChange={this.handleChange.bind(this)} />
<h4>{value}</h4>
</div>
);
}
}
ReactDOM.render(<HelloMessage />,mountNode);
執行個體:輸入文字實時顯示
你需要在父元件通過建立事件句柄 (handleChange) ,并作為 prop (updateStateProp) 傳遞到你的子元件上。
class Content extends React.Component{
render(){
return(
<div>
<input type='text' value={this.props.myDataProp} onChange={this.props.updataStateProp} />
<h4>{this.props.myDataProp}</h4>
</div>
)
}
}
class HelloMessage extends React.Component{
constructor(){
super();
this.state = {
value: 'Hello World!'
};
}
handleChange(even){
this.setState({
value: even.target.value
})
}
render(){
let value = this.state.value;
return(
<div>
<Content myDataProp={value} updataStateProp={this.handleChange.bind(this)} />
</div>
);
}
}
ReactDOM.render(<HelloMessage />,mountNode);
執行個體:點我
class HelloMessage extends React.Component{
constructor(){
super();
this.state={
value: 'Hello World!'
}
}
handleChange(event){
this.setState({
value: 'luuman is good man!'
})
}
render(){
let value = this.state.value;
return(
<div>
<button onClick={this.handleChange.bind(this)}>點我</button>
<h4>{value}</h4>
</div>
)
}
}
ReactDOM.render(<HelloMessage />,mountNode);
當你需要從子元件中更新父元件的 state 時,你需要在父元件通過建立事件句柄 (handleChange) ,并作為 prop (updateStateProp) 傳遞到你的子元件上。執行個體如下:
執行個體:點我
class Content extends React.Component{
render(){
return(
<div>
<button onClick={this.props.updateStateProp}>點我</button>
<h4>{this.props.myDataProp}</h4>
</div>
)
}
}
class HelloMessage extends React.Component{
constructor(){
super();
this.state = {
value: 'Hello World!'
}
}
handleChange(event){
this.setState({
value: 'luuman is good man!'
})
}
render(){
let value = this.state.value;
return <div><Content myDataProp={value} updateStateProp={this.handleChange.bind(this)}></Content></div>
}
}
ReactDOM.render(<HelloMessage />,mountNode);
Refs and the DOM
React Refs
React 支援一種非常特殊的屬性 Ref ,你可以用來綁定到 render() 輸出的任何元件上。
這個特殊的屬性允許你引用 render() 傳回的相應的支撐執行個體( backing instance )。這樣就可以確定在任何時間總是拿到正确的執行個體。
使用方法:
綁定一個 ref 屬性到 render 的傳回值上:
在其它代碼中,通過 this.refs 擷取支撐執行個體:
<input ref="myInput" />
var input = this.refs.myInput;
var inputValue = input.value;
var inputRect = input.getBoundingClientRect();
執行個體:點我輸入框擷取焦點
class MyComponent extends React.Component{
handleClick(){
this.refs.myInput.focus();
}
render(){
return(
<div>
<input type='text' ref='myInput' />
<input type='button' value='點我輸入框擷取焦點' onClick={this.handleClick.bind(this)} />
</div>
);
}
}
ReactDOM.render(<MyComponent />,mountNode);
當元件插入到 DOM 後,ref屬性添加一個元件的引用于到this.refs.name擷取。
執行個體中,我們擷取了輸入框的支撐執行個體的引用,子點選按鈕後輸入框擷取焦點。
我們也可以使用 getDOMNode()方法擷取DOM元素
React AJAX
React 元件的資料可以通過 componentDidMount 方法中的 Ajax 來擷取,當從服務端擷取資料庫可以将資料存儲在 state 中,再用 this.setState 方法重新渲染 UI。
當使用異步加載資料時,在元件解除安裝前使用 componentWillUnmount 來取消未完成的請求。
執行個體
$.get(URL,function(data){})
執行個體:擷取 Github 使用者最新 gist 共享描述:
class UserGist extends React.Component{
constructor() {
super();
this.state = {
username: '',
lastGistUrl: ''
}
}
componentDidMount(){
this.serverRequest = $.get(this.props.source,function(result){
let lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
})
}.bind(this))
}
componentWillUnmount(){
this.serverRequest.abort();
}
render(){
return(
<div>
{this.state.username}
<a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a>
</div>
)
}
}
ReactDOM.render(<UserGist source="https://api.github.com/users/octocat/gists" />,mountNode);
執行個體:拉取資料
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
const mountNode = document.getElementById('root');
class RipoList extends React.Component{
constructor(){
super();
this.state = {
loading: true,
error: null,
data: null
};
}
componentDidMount(){
this.props.promise.then(
value => this.setState({
loading: false,
data: value
}),
error => this.setState({
loading: false,
error: error
})
);
}
render(){
if(this.state.loading){
return <span>Loading...</span>;
}else if(this.state.error != null){
return <span>Error: {this.state.error.message}</span>;
}else{
let repos = this.state.data.items;
let repoList = repos.map(function(repo,index){
return(
<li key={index}>
<a href={repo.html_url}>{repo.name}</a>({repo.stargazers_count} stars)<br />
{repo.description}
</li>
);
});
return(
<main>
<h1>Most Popular JavaScript Projects in Github</h1>
<ol>{repoList}</ol>
</main>
)
}
}
}
ReactDOM.render(<RipoList promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')} />,mountNode);
Add-Ons 添加插件
jquery
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
class HelloWorld extends React.Component{
render(){
return(
<div>HelloWorld</div>
);
}
}
ReactDOM.render(<HelloWorld />,$('#example')[0]);
recharts
- React圖表元件庫
bootstrap
- React元件庫
MarkdownEditor
- MarkDown
ReactDOM
render()
ReactDOM.render(
element,
container,
[callback]
)
unmountComponentAtNode()
ReactDOM.unmountComponentAtNode(container)
findDOMNode()
ReactDOM.findDOMNode(component)
onkeypress
ES6
ECMAScript 6 入門
let
用來聲明變量。它的用法類似于var,但是所聲明的變量,隻在let指令所在的代碼塊内有效。
for循環的計數器
for (let i = 0; i < 10; i++) {}
console.log(i);
//ReferenceError: i is not defined
下面的代碼如果使用var,最後輸出的是10
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
如果使用let,聲明的變量僅在塊級作用域内有效,最後輸出的是6
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6