在騰訊應用寶前端分享會上分享了react,現將資料整理成這篇文章,但願對react的初學者可以有所幫助;若是文中有描述不恰當或者錯誤的地方,請望斧正。javascript
react 是facebook在2013年開源的一個javascript庫,主要用來快速的構建頁面,使用react主要有如下兩個緣由:html
<h1>This is a title</h1> <script> var data="hello world";//在實際中是從後臺獲取數據 var h1=document.querySelector("h1"); h1.innerHTML=data;//關注dom結構的變化 </script>
學習編程語言C++,java可能都是hello world提及的,先看一個簡單的hello world的例子:前端
<!-- javacript files--> <script src="lib/react.js"></script> <script src="lib/react-dom.js"></script> <script src="lib/browser.min.js"></script> //... <div id="app"></div> <script type="text/babel"> var HelloWorld = React.createClass({ render: function() { return <h2>Hello World</h2> } }) const app =document.getElementById("app"); ReactDOM.render(<HelloWorld />, app); </script>
在上面的代碼中,咱們看到引入了兩個庫:react.js,react-dom.js,其實使用react的核心庫,在0.14版本以前是一個文件,以後分紅了兩個,react.js包括了組件相關定義的屬性、方法,如:react.createClass,react.Componet等;react-dom.js主要是包括了將一個react組件渲染到頁面成爲真實dom的相關屬性,例如:reactDOM.render,findDOMNode。使用react構建一個組件分爲如下兩步:
(1)定義一個組件,並給組件一個名稱;
(2)使用reactDOM.render()方法將組件渲染到頁面上。html5
上面有提到組件,那麼react怎麼定義一個組件呢。有兩種方式定義:React.createClass()與class的方式。java
這是是react最先的版本提出的一個建立方式,使用的方式是在rener中返回咱們須要在頁面上看到的dom結構,代碼如上圖的helloworld例子所示。react
第二種方式是使用class的方式,這多是跟es6相契合吧,一個比較建議使用這樣的方式;大致語法是 class componentName extends React.Component(完整代碼見附件demo01中的helloworld.html)。webpack
class HelloWorld extends React.Component { render(){ return ( <h2>Hello World!</h2> ); } }
在組件定義後,其組件的數據是咱們關注的焦點。react中定義了兩個屬性來描述組件的數據props與state;咱們能夠將一個組件想象成一個函數,其中props就是傳遞的參數而且不能夠在函數內修改;而state就是其中定義的變量,咱們能夠對其中的變量進行維護。es6
export default class Article extends React.Component { render() { const { title } = this.props; return ( <div > <h4>{title}</h4> //... </div> ); } } <Article title={title}/>
咱們只須要傳遞標題的值就能夠了,不須要進行其餘的操做,所以使用props。web
constructor() { super(); this.state = { title: "Welcome", }; } <Header changeTitle={this.changeTitle.bind(this)} title={this.state.title} />
這個裏面的標題是獲取input輸入框的值,所以設置爲state。演示的效果以下:
ajax
咱們可能提出疑問,就是若是咱們將一個函數B嵌入到另外一個函數A中,在A中設置一個變量(state),那麼B中就可使用參數(props)的形式了,的確是可行的,這是兩種不一樣的組件:smart component,dumb component.能夠參考Dan的文章 Presentational and Container Components
react中實現事件綁定的方式是很是簡單的,只須要在對應的標籤中使用駝峯命名法給其一個綁定的函數便可。最多見的就是一個輸入框,咱們須要獲取其值,所以能夠給onChange綁定一個事件。其步驟以下:
export default class Header extends React.Component { handleChange(e) { const title = e.target.value; this.props.changeTitle(title); } render() { <input value={this.props.title} onChange={this.handleChange.bind(this)} /> } }
一個react組件有三種狀態:mounting,updating,unmounting
mounting:React Component被render解析生成對應的dom節點並被插入瀏覽器的DOM結構的過程。
updating:當一個組件的狀態state發生變化的時候,會進行從新的render過程。
unmounting:是指一個mounted的React Component對應的DOM節點被從DOM節點移除的過程。
其每個生命狀態都有封裝對應的hook函數,咱們能夠經過狀態的變化過程來進行數據的加載、修改、移除等。以實現頁面的初始化和頁面數據的更新。以mouting狀態爲例,在組件渲染以前,咱們可使用getInitalState來指定數據的初始化值,使用componentDidMount來進行ajax請求,從服務器加載數據等操。代碼示例能夠參照react-webpack/src/components/Content.js
當頁面是組件構成的什麼,就自然的時候作單頁面應用,能夠在發生某種狀況下替換掉組件就能夠呈現不一樣的內容了。在講react-router使用以前,讓咱們先看看路由實現的一個大致的原理。
一個url通常由這幾個部分組成:協議、域名、端口、文件路徑、文件名、查詢條件與hash值,hash值的變化不會使頁面進行更新,基於此原理,能夠實現頁面路由,其過程通常以下:
function Router() { this.routes = {}; this.currentUrl = ''; } Router.prototype.route = function(path, callback) { this.routes[path] = callback || function(){}; }; Router.prototype.refresh = function() { this.currentUrl = location.hash.slice(1) || '/'; this.routes[this.currentUrl](); }; Router.prototype.init = function() { window.addEventListener('load', this.refresh.bind(this), false); window.addEventListener('hashchange', this.refresh.bind(this), false); } window.Router = new Router(); window.Router.init();
在html 5標準出現以前history對象的屬性與方法比較簡單,通常是使用history.back(),history.forward()實現頁面的前進與後退。可是在html5中爲其添加了新的方法與和一個事件,使其爲咱們實現頁面路由提供了新的方法。其中經常使用的方法有: history.pushState向當前瀏覽器的歷史堆棧中添加一個新的url; window.onpopstate會在瀏覽器進行前進後退的時候進行觸發。
react-router對兩種方式都有實現,咱們能夠選擇任意一種。其調用方式以下:
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation"> <ul className='main-menu'> <li><Link to="/">首頁</Link></li> //... </ul> </nav> <Router history={browserHistory}> <Route path="/" component={Layout}> <IndexRoute component={Content}></IndexRoute> //... </Route> </Router>