您的位置:首页 > Web前端 > React

用react的思维考虑网页用户登陆的逻辑

2015-06-03 10:16 609 查看
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.

我大致意译一下:React仅仅尝试解决关于UI的某一个方面(不是全部)的问题,它不来假设你使用了什么其它技术。它易于理解,可以在您已经存在的项目中尝试使用。背后的哲学是:我只做一件事(关于UI),并且把它做到极致。

这不是一篇叫你如何使用React的文章。它只是用react的方式思考一个问题,把它表达出来,如果您是业内人士,一定会用自己的技术栈和它作出对比。如果你这样做了,这篇文章的目的就达到了。

这是一个登陆页面,服务器一端提供restful形式的响应,这是一个单页面程序。服务器响应的数据结构如下,| 表示可能性:

{
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响应
/loginGET*登陆页面HTML(静态)
/loginPOSTapplication/json上面提到的数据结构
/loginstatusGET*上面提到的数据结构
可能的用户操作流程:

用户访问/login,返回登陆html页面。页面内的rest客户端访问/loginstatus,获取数据。

用户输入用户名密码等,rest客户端post到服务器,获取数据

用户可能中途刷新了浏览器,那么就和1一样了。

不管是哪种可能,我们都会获取一个数据。数据有许多不同的组合,我们把不同的组合叫做状态,react的核心就是状态(数据)和UI之间建立单向的联系。

下面来分析一下可能的状态:

1、用户打开登陆页面,此时通过/loginstatus获取的数据可能是:

{state: ANONYMOUS, message: NO_MESSAGE, showCaptcha: false}

这种状态下,显示,用户名框,密码框,登陆按钮

2、用户登录时返回错误,此时的数据可能是:

{state: ANONYMOUS, message: USERNAME_PASSWORD_NOT_MATCH, showCaptcha: false}

这时可以文本框添加显示错误状态的css等。

3、用户尝试了好几次,超过显示验证码的阈值

{state: ANONYMOUS, message: USERNAME_PASSWORD_NOT_MATCH, showCaptcha: true}

此时开始,验证码字段显示。为什么说此时开始呢?即使你刷新了浏览器,还是会显示验证码字段。

4、用户登录成功:

state: FULL, message: NO_MESSAGE, showCaptcha: false, wtg: "http://哪里跌倒,哪里起来"}

此时客户端根据情况开始新的页面。

从整个过程来说,用react提倡的状态来思考,一切行为都通用化,没有什么特殊性。UI只是忠实的反应状态而已,至于是显示验证码,或提示用户名错误都一视同仁。

代码:

1、表单容器组件,主要是为登陆表单增加一些效果切换,比如页面初始打开时显示的是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>
);
}
});

2、表单组件:

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>
);
}
});

3、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界面,逻辑非常简单明了,便于维护,强烈推荐尝试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: