前言

要实现一个评论的消息框, 要求是当字数为 0 或者超过 120 的时候,评论按钮不可单击,并且剩余字数会跟着变。

以微博评论框为例:

  • 用一个 state 来保存当前的状态,然后当用户输入的时候,这个 state 的数据会跟着变,同时更新评论按钮的状态。
var commentBox = {
  init() {
    // 初始化一个state
    this.state = {};
    commentBox.bindEvent();
  },

  setState(key, value) {
    this.state[key] = value;
  },

  changeSubmit() {
    // 通过获取当前state
    $("#submit")[0].disabled = commentBox.state.text.length === 0 || commentBox.state.text.length > 120;
  },

  showLeftTextCount() {
    $("#text-count").text(120 - this.state.text.length);
  },

  bindEvent() {
    $(".cmt-textarea").on('input', function() {
      // 改变当前state
      commentBox.setState({"text", this.value});
      commentBox.changeSubmit();
      commentBox.showLeftTextCount();
    })
  }
}

我们再稍加修改,在在上面 setState 的时候, 自动去更新 DOM。

var commentBox = {
  ...
  setState(key, value) {
    this.state[key] = value;
    commentBox.changeSubmit();
    commentBox.showLeftTextCount();
  },
  ...
  bindEvent() {
    $(".cmt-textarea").on('input', function() {
      // 改变当前state
      commentBox.setState({"text", this.value});
    })
  }
}

还可以再做得更智能,状态变的时候自动去比较当前状态所渲染的虚拟 DOM 和真实 DOM 的区别,自动去改变真实 DOM:

var commentBox = {
  setState(key, value) {
    this.state[key] = value;
    renderDom($('.comment'));
  },

  renderDom($currentDom) {
    diffAndChange($currentDom, renderVirtualDom(commentBox.state));
  }
};

('<input type="submit" disabled={{this.state.text.length === 0 || this.state.text.length > 140}} />');

这里其实就是 React 的设计原型,不同的状态有不同的表现行为,所以可以认为是一个状态模式,并且通过状态去驱动 DOM 的更改。