用react的思惟考虑网页用户登录的逻辑

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 * 上面提到的数据结构

 可能的用户操做流程:服务器

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

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

  3. 用户可能中途刷新了浏览器,那么就和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界面,逻辑很是简单明了,便于维护,强烈推荐尝试。

相关文章
相关标签/搜索