Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it's easy to try it out on a small feature in an existing project.css
我大體意譯一下:React僅僅嘗試解決關於UI的某一個方面(不是所有)的問題,它不來假設你使用了什麼其它技術。它易於理解,能夠在您已經存在的項目中嘗試使用。背後的哲學是:我只作一件事(關於UI),而且把它作到極致。html
這不是一篇叫你如何使用React的文章。它只是用react的方式思考一個問題,把它表達出來,若是您是業內人士,必定會用本身的技術棧和它做出對比。若是你這樣作了,這篇文章的目的就達到了。react
這是一個登錄頁面,服務器一端提供restful形式的響應,這是一個單頁面程序。服務器響應的數據結構以下,| 表示可能性:
json
{ state: ANONYMOUS | REMEMBER_ME | FULL, showCaptcha: true | false, message: WRONG_JSON_MESSAGE | USERNAME_PASSWORD_NOT_MATCH | UNKNOWN | SHOW_CAPTCHA | WRONG_CAPTCHA | NO_MESSAGE, user: null | {email: xxx@yyy}, wtg: where to go }
客戶端rest請求的表:瀏覽器
路徑 | http方法 | content-type | 響應 |
/login | GET | * | 登錄頁面HTML(靜態) |
/login | POST | application/json | 上面提到的數據結構 |
/loginstatus | GET | * | 上面提到的數據結構 |
可能的用戶操做流程:服務器
用戶訪問/login,返回登錄html頁面。頁面內的rest客戶端訪問/loginstatus,獲取數據。restful
用戶輸入用戶名密碼等,rest客戶端post到服務器,獲取數據數據結構
用戶可能中途刷新了瀏覽器,那麼就和1同樣了。app
不論是哪一種可能,咱們都會獲取一個數據。數據有許多不一樣的組合,咱們把不一樣的組合叫作狀態,react的核心就是狀態(數據)和UI之間創建單向的聯繫。
工具
下面來分析一下可能的狀態:
一、用戶打開登錄頁面,此時經過/loginstatus獲取的數據多是:
{state: ANONYMOUS, message: NO_MESSAGE, showCaptcha: false}
這種狀態下,顯示,用戶名框,密碼框,登錄按鈕
二、用戶登陸時返回錯誤,此時的數據多是:
{state: ANONYMOUS, message: USERNAME_PASSWORD_NOT_MATCH, showCaptcha: false}
這時能夠文本框添加顯示錯誤狀態的css等。
三、用戶嘗試了好幾回,超過顯示驗證碼的閾值
{state: ANONYMOUS, message: USERNAME_PASSWORD_NOT_MATCH, showCaptcha: true}
此時開始,驗證碼字段顯示。爲何說此時開始呢?即便你刷新了瀏覽器,仍是會顯示驗證碼字段。
四、用戶登陸成功:
state: FULL, message: NO_MESSAGE, showCaptcha: false, wtg: "http://哪裏跌倒,哪裏起來"}
此時客戶端根據狀況開始新的頁面。
從整個過程來講,用react提倡的狀態來思考,一切行爲都通用化,沒有什麼特殊性。UI只是忠實的反應狀態而已,至因而顯示驗證碼,或提示用戶名錯誤都一視同仁。
代碼:
一、表單容器組件,主要是爲登錄表單增長一些效果切換,好比頁面初始打開時顯示的是Loading,而後在請求登錄狀態的時候顯示"querying state",最後根據query結果,顯示登錄表單。
var LoginFormContainer = React.createClass({ getInitialState: function() { return {queryLoginState: true}; }, componentDidMount: function() { console.log(this.props.ucRestClient ? "ucrestclient is set." : "no ucrestclient"); var that = this, restClient = this.props.ucRestClient; restClient.loginstate().then(function(response){ console.log('response: ', response); that.setState({queryLoginState: false, entity: response.entity}); }); }, render: function() { var c; if (this.state.queryLoginState) { c = <p>queryLoginState....</p>; } else { c = <LoginForm {...this.props} {...this.state.entity}/>; } return ( <div className="login-form-container"> {c} </div> ); } });
二、表單組件:
var UserNameField = React.createClass({ componentDidMount: function() { console.log(this.props.value); // => true }, render: function() { return ( <div className="pure-control-group"> <label htmlFor="username">Username</label> <input name="username" value={this.props.value} type="text" placeholder="Username"/> </div>); } }); var PasswordField = React.createClass({ render: function() { return ( <div className="pure-control-group"> <label htmlFor="password">Password</label> <input name="password" value={this.props.value} type="password" placeholder="Password"/> </div>); } }); var CaptchaField = React.createClass({ render: function() { return ( <div className="pure-control-group"> <label htmlFor="captcha">Captcha</label> <input name="captcha" value={this.props.value} placeholder="Captcha"/> </div>); } }); var LoginForm = React.createClass({ getInitialState: function() { return {}; }, handleSubmit: function(e) { e.preventDefault(); if (this.state.submiting) { return; } var username = this.state.username, password = this.state.password, captcha = this.state.captcha, ucClient = this.props.ucRestClient, that = this; var canSubmit = true; if (!username || username.length < 3) { canSubmit = false; } if (!password || password.length < 6) { canSubmit = false; } if (this.state.showCaptcha) { if (!captcha || captcha.length !== 5) { canSubmit = false; } } if (canSubmit) { this.setState({submiting: true}); ucClient.login({ username: username, password: password, captcha: captcha }).then(function(response) { console.log('response: ', response); that.setState({submiting: false}); }); } }, handleChange: function(e) { // DOMEventTarget, id, tagName var stateo = {}; stateo[e.target.name] = event.target.value.trim(); this.setState(stateo); // console.log(e.target.value); }, render: function() { var captchaField; if (this.state.showCaptcha) { captchaField = <CaptchaField value={this.state.captcha} />; } return ( <form className="pure-form pure-form-aligned" action="/login" method="POST" onSubmit={this.handleSubmit} onChange={this.handleChange}> <fieldset> <UserNameField value={this.state.username} /> <PasswordField value={this.state.password} /> {captchaField} <div className="pure-controls"> <label htmlFor="cb" className="pure-checkbox"> <input id="cb" type="checkbox"/> I've read the terms and conditions </label> <button type="submit" className="pure-button pure-button-primary">Submit</button> </div> </fieldset> </form> ); } });
三、rest客戶端工具代碼:
'use strict'; var rest, mime, csrf, client; rest = require('rest'); mime = require('rest/interceptor/mime'); csrf = require('rest/interceptor/csrf'); var _csrf = window.jQuery("meta[name='_csrf']").attr("content"), _csrf_header = window.jQuery("meta[name='_csrf_header']").attr("content"), ucclient = rest.wrap(mime, {mime: 'application/json'}).wrap(csrf, {token: _csrf}); module.exports = { login: function(entity) { return ucclient({ path: '/login', method: "POST", entity: entity}); }, loginstate: function() { return ucclient({ path: '/loginstate', method: "GET" }); } };
注意:以上代碼是本人在2天時間內(包括尋找開發環境的設置)經過閱讀reactjs官方文檔寫做而成,可能會存在很是規的代碼寫法,請指正。
結論:以reactjs編寫UI界面,邏輯很是簡單明瞭,便於維護,強烈推薦嘗試。