個人博客搭建完成,歡迎大家來訪問哦
黎默丶lymoo的博客
什么是React
React是一個用于構建用戶界面的JavaScript庫,而不是一個MVC框架,但可以使用React作為MVC架構的View層輕易的在已有項目中使用。React起源于Facebook的內部項目,用來架設Instagram的網站,并于2013年5月開源。React擁有較高的性能,代碼邏輯非常簡單,越來越多的人已開始關注和使用它。
React的特點
虛擬DOM結構
以前沒有ajax技術的時候,web頁面從服務端整體渲染出html輸出到瀏覽器端進行渲染,同樣的,用戶的一個改變頁面的操作也會刷新整個頁面來完成。直到有了ajax出現,實現頁面局部刷新,帶來的高效和分離讓web開發(fā)者們驚嘆不已。但隨之而來的問題是,復雜的用戶交互及展現需要通過大量的DOM操作來完成,這讓頁面的性能以及開發(fā)的效率又出現了新的瓶頸。
時至今日,談到前端性能優(yōu)化,減少DOM元素、減少reflow和repaint、編碼過程中盡量減少DOM的查詢等手段是大家耳熟能詳的。而頁面任何UI的變化都是通過整體刷新來完成的。幸運的是,React通過自己實現的DOM Diff算法,計算出虛擬頁面當前版本和新版本之間的差異,最小化重繪,避免不必要的DOM操作,解決了這兩個公認的前端性能瓶頸,實現高效DOM渲染。
我們知道,頻繁的操作DOM所帶來的性能消耗是很大的,而React之所以快,是因為它不直接操作DOM,而是引進虛擬DOM的實現來解決這個問題
對于頁面的更新,React通過自己實現的DOM Diff算法來進行差異對比、差異更新,反映到頁面上就是只重繪了更新的部分,從而提高渲染效率。
組件化
在業(yè)務開發(fā)中,遇到公共的模板部分,我們不得不將模板和規(guī)定的數據格式耦合在一起來實現組件。而在React中,我們可以使用JSX語法來封裝組件,將組件的結構、數據邏輯甚至樣式都聚合在一起,更加簡單、明了、直觀的定義組件。
有了組件化的實現,我們可以很直觀的將一個復雜的頁面分割成若干個獨立組件,再將這些獨立組件組合完成一個復雜的頁面。這樣既減少了邏輯復雜度,又實現了代碼的重用。
配置React的開發(fā)環(huán)境
獲取相關文件
首先我們需要獲取到React的開發(fā)文件,可以從React官網下載相關配置文件,由于React用到的是JSX語法,瀏覽器是不能夠直接進行解析的,還需要配置一個將JSX轉換成JavaScript的文件,將鏈接中的代碼復制到自己本地的任意新建的一個文件中保存完成配置,最后配置文件如下圖所示:
配置React開發(fā)文件模板
新建一個HTML文件進行如下配置,當這個文件配置好之后,以后需要開發(fā)React的程序都可以以這個為模板進行開發(fā)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!--引入react核心庫-->
<script type="text/javascript" src="build/react.js"></script>
<!--引入react的DOM操作-->
<script type="text/javascript" src="build/react-dom.js"></script>
<!--把JSX語法轉換成瀏覽器能識別的JavaScript-->
<script type="text/javascript" src="build/browser.min.js"></script>
</head>
<body>
<!--把通過react生成的DOM放置在#container里面-->
<div id="container"></div>
</body>
<!--寫JSX的地方需要設置為text/babel-->
<script type="text/babel">
// 在這里寫react代碼
</script>
</html>
JSX的認識
上文提到的JSX是什么東西呢?其實JSX是一種語法,不是一門新的語言,它既包括JavaScript和Xhtml語言,XHTML用標簽來進行表示,JavaScript用{}展示。
這里主要注意的是寫JSX的地方需要設置為text/babel,以及內部的書寫規(guī)范
簡單的React示例
這里舉一個例子展示一個最簡單的React程序
因為React放置的是虛擬的DOM結構,我們需要將它渲染至頁面上,它提供的語法為ReactDOM.render()
它里面可以有三個參數,第一個為我們想要渲染至頁面上的DOM元素,第二個為我們想在頁面的哪個節(jié)點元素中進行渲染,第三個為渲染成功以后的回調
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="build/react.js"></script>
<script type="text/javascript" src="build/react-dom.js"></script>
<script type="text/javascript" src="build/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
</body>
<script type="text/babel">
var name = "zhangsan";
ReactDOM.render(
<h1>hello {name}</h1>,
document.getElementById("container")
);
// 這里有第二種寫法
ReactDOM.render(
React.createElement("h1", null, "hello " + name),
document.getElementById("container")
)
</script>
</html>
展示的效果為
如果想要渲染出多個相同標簽的不同內容,React也提供了一種方式,用key來確定標簽的不同,以下展示部分script代碼
var names = ["Alice", "Cindy", "Rose"];
ReactDOM.render(
<ul>
{
names.map(function (name, key) {
return <li key={key}>{name}</li>
})
}
</ul>,
document.getElementById("container")
)
展示的效果為React組件
在react中將一些重用的dom結構進行了封裝,就稱為組件,它便于我們進行代碼管理以及代碼復用
組件的命名規(guī)則
首字母必須大寫,使用駝峰命名法
組件的構建方法
React提供了一個命令為React.createClass()來創(chuàng)建一個組件,它內部包含一個必須要有的方法render,用來返回一個或多個的DOM結構
封裝一個簡單的組件示例
var HelloMessage = React.createClass({
render: function () {
return <h1>hello message</h1>
}
});
這樣就簡單的封裝了一個名為HelloMessage的組件,如果想要調用這個組件,方法為
ReactDOM.render(
<HelloMessage/>,
document.getElementById("container")
)
復合組件
復合組件簡單來說即是組件套用組件,我們來嘗試封裝一個復合組件
var Component1 = React.createClass({
render: function () {
return <h1>測試</h1>
}
});
var Component2 = React.createClass({
render: function () {
return <a target="_blank">去百度</a>
}
});
var Component3 = React.createClass({
render: function () {
return (
<div>
<Component1/>
<Component2/>
</div>
)
}
});
React的CSS樣式
React有三種添加樣式的方法
1.內聯樣式
var StyleTest = React.createClass({
render: function () {
return <div style={{backgroundColor: "red", border: "10px solid #ccc"}}>Test</div>
}
});
ReactDOM.render(
<StyleTest/>,
document.getElementById("container")
)
效果展示:2.對象樣式
注意這里的styles都是以對象的格式進行書寫的,千萬不要以前的習慣后面寫封號,字段名不加引號等等
var styles = {
color: "blue",
backgroundColor: "green"
};
var StyleTest = React.createClass({
render: function () {
return <div style={styles}>Test</div>
}
});
ReactDOM.render(
<StyleTest/>,
document.getElementById("container")
)
效果展示:3.選擇器樣式
這個就和我們原來的CSS書寫差不多,但是類名的添加不再是class,注意這里是className
<style>
.styles{
color: yellow;
background-color: black;
}
</style>
var StyleTest = React.createClass({
render: function () {
return <div className="styles">Test</div>
}
});
ReactDOM.render(
<StyleTest/>,
document.getElementById("container")
)
效果展示:React的屬性props
props簡單來說就是一個組件的私有屬性,從父組件傳遞一些需要的值到子組件中來使用
使用方法為this.props,這里的this便代表它的父組件,props則代表了父組件上的所有元素,是一個數組
用法示例:
var PropsTest = React.createClass({
render: function () {
return <h1>hello {this.props.name}</h1>
}
});
ReactDOM.render(
<PropsTest name="zhangsan"/>, // 這里的name值會傳遞到h1的標簽中相應的位置
document.getElementById("container")
)
這里有一個特例為this.props.children,它表示的是組件的所有子節(jié)點
var PropsTest = React.createClass({
render: function () {
return {
<ol>
{
React.Children.map(this.props.children, function (child)) {
return <li>{child}</li>
}
}
</ol>
}
}
})
ReactDOM.render({
<PropsTest>
<span>hello</span>
<span>world</span>
</PropsTest>,
document.getElementById("conotainer")
})
效果展示:設置默認值
React提供一個專門設置props的默認值命令getDefaultProps
具體用法為:
var PropsTest = React.createClass({
getDefaultProps: function () {
// 設置該組件屬性的初始值
return {
name: "lisi"
}
},
render: function () {
return <h1>hello {this.props.name}</h1>
}
});
ReactDOM.render(
<PropsTest/>,
document.getElementById("container")
);
效果展示:設置props數據類型
var PropsTest = React.createClass({
propTypes: {
// 設置數據的類型
name: React.PropTypes.string.isRequired
},
getDefaultProps: function () {
return {
name: "lisi"
}
},
render: function () {
return <h1>hello {this.props.name}</h1>
}
});
ReactDOM.render(
<PropsTest/>,
document.getElementById("container")
);
React的狀態(tài)state
React把組件看成是一個狀態(tài)機(State Machines)。通過與用戶的交互,實現不同狀態(tài),然后渲染UI,讓用戶界面和數據保持一致。
React里,只需更新組件的state,然后根據新的state重新渲染用戶界面(不要操作DOM)。
getInitialState方法用于定義初始狀態(tài),也就是一個對象,這個對象可以通過this.state屬性讀取。當用戶點擊組件,導致狀態(tài)變化,this.setState方法就修改狀態(tài)值,每次修改以后,自動調用this.render方法,再次渲染組件。
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? '喜歡' : '不喜歡';
return (
<p onClick={this.handleClick}>
你<b>{text}</b>我。點擊切換狀態(tài)。
</p>
);
}
});
ReactDOM.render(
<LikeButton />,
document.getElementById("container")
);
React組件生命周期
React的生命周期可以分為三個狀態(tài):
1.Mounting:已插入真實DOM
2.Updating:正在被重新渲染
3.Unmounting:已移出真實DOM
生命周期的方法
componentWillMount:在渲染前調用,在客戶端也在服務端。
componentDidMount:在第一次渲染后調用,只在客戶端。之后組件已經生成了對應的DOM結構,可以通過this.getDOMNode()來進行訪問。 如果你想和其他JavaScript框架一起使用,可以在這個方法中調用setTimeout, setInterval或者發(fā)送AJAX請求等操作(防止異部操作阻塞UI)。
componentWillReceiveProps:在組件接收到一個新的prop時被調用。這個方法在初始化render時不會被調用。
shouldComponentUpdate:返回一個布爾值。在組件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。
可以在你確認不需要更新組件時使用。
componentWillUpdate:在組件接收到新的props或者state但還沒有render時被調用。在初始化時不會被調用。
componentDidUpdate:在組件完成更新后立即調用。在初始化時不會被調用。
componentWillUnmount:在組件從DOM中移除的時候立刻被調用。
以下示例在Hello組件加載以后,通過componentDidMount方法設置一個定時器,每隔100毫秒重新設置組件的透明度,并重新渲染
var Hello = React.createClass({
getInitialState: function () {
return {
opacity: 1.0
};
},
componentDidMount: function () {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
},
render: function () {
return (
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
});
ReactDOM.render(
<Hello name="world"/>,
document.getElementById('example')
);