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界面,逻辑很是简单明了,便于维护,强烈推荐尝试。