javascript - 使用flux时的表单验证

标签 javascript flux

我在我使用 Backbone.View 的应用程序中使用通量作为 View 层。

一般整个页面都有一个store实例,store保存应用的数据(或者状态),view会监听change store事件,当store触发 change事件, View 将相应地重新呈现自身。

到目前为止一切顺利,但是我在使用表单时遇到了一些问题,使用时尝试提交表单或 blur为元素触发的事件,我想验证服务器中的输入并尽快显示错误,这就是我所做的:

  • 当用户点击提交按钮或更改元素的值时,我将调度一个 Action ,如:dispatch({type:"validate",value:"value"});
  • store将响应此操作并向服务器发送请求
  • 当响应返回时,我将更新存储并触发 change事件: store.validate_response=response; store.trigger("change");
  • View (示例中的表单)将重新呈现自身。

  • 我可以显示错误,但我不能保留元素的值,因为表单中的元素被重新渲染,这意味着它们将显示原始值而不是用户键入的值。

    我认为在分派(dispatch)验证操作时也要保存键入的值,如下所示:
    dispatch({type:"validate",value:"value",userTypedValueForEveryElement:"....."});
    

    它在使用点击提交按钮时起作用,因为通常当他们点击按钮时,他们不会在表单中输入任何内容,但是这种情况如何:
    <input type="text" id="A" />
    <input type="text" id="B" />
    

    用户类型 avalueinput A ,然后输入 bvinput B ,同时我会做验证,并在调度 Action 时发送两个值:
    {a:"avalue",b:"bv"}
    
    store将保留这些值。

    在请求期间,用户不断输入元素 B ,现在值为 bvalue ,同时返回验证响应,然后表单将重新渲染,并设置 avalueAbvB ,这就是点,B的值丢失,用户会感到惊讶,他们不知道发生了什么。

    有什么办法解决这个问题吗?

    看来flux方式:
    view trigger action --> 
    store respond to actions --> 
    store trigger changed -->
    view respond to store(re-render in most case) --> 
    view trigger action" 
    

    使这种要求比以前复杂。一旦您的 View 有太多交互性,您将不得不做更多的额外工作来保持 View 的状态。

    这是真的还是因为我错过了什么?

    最佳答案

    听起来您在这里遇到了一些不同的问题,但它们都是可以解决的。这有点长,但希望它能解决您遇到的所有问题。

    店面设计:首先,您的商店实际上要保存哪些信息?尽量不要把 Flux 存储区想成 Backbone 模型,因为它们的目的并不完全相同。 Flux store 应该存储应用程序状态的一部分(不一定是 UI 组件状态的一部分),并且不应该知道或关心使用它的任何 View 。牢记这一点可以帮助您将行为和数据放在正确的位置。因此,假设您的商店正在跟踪用户对特定表单的输入。由于您的应用程序关心输入是否有效,您需要以某种方式在商店中表示它。您可以将每个输入表示为存储中的一个对象,例如 {val: 'someInput', isValid: false} .无论您如何存储它,它都必须在那里;您的应用程序的任何部分都应该能够从商店中提取数据并知道哪些输入有效/无效。

    我同意 @korven 的观点,即在 Stores 中放置大量应用程序逻辑是一个糟糕的选择。我将我的 AJAX 调用放入操作创建逻辑中,AJAX 响应回调在 Dispatcher 上创建实际操作;我已经不止一次看到这个推荐了。

    保留用户输入:一方面,您只想在用户完成输入时呈现表单输入 - 否则,呈现将在他们输入文本时更改文本。这很简单--throttledebounce (这里可能更喜欢去抖动)用户输入事件的输入验证处理程序。 (如果您正在使用焦点或模糊事件,时间不太可能成为问题,但您仍应考虑它。)仅在验证完成后才更新商店。而且,当然,仅在商店更新时才呈现。所以我们只在用户停止输入并且我们已经验证他们的输入时修改 DOM 中输入的值。

    即使使用节流/去抖动,由于验证请求是异步的,并且用户可能(可能)在短时间内触发许多验证请求,因此您不能依赖按顺序返回的响应。换句话说,您无法在每个响应返回时对其进行处理;如果它们乱序返回,您将用旧输入覆盖最近的输入。 (我在现实生活中遇到过这种情况。这对你来说可能是一个边缘情况,但当它发生时,错误会令人困惑,值得预先解决。)幸运的是,我们只关心用户输入的最新内容.所以我们可以忽略对验证请求的所有响应,除了最近请求的响应。通过跟踪每个请求的“键”,您可以轻松地将此逻辑与发出请求的任何内容集成。这是我如何解决这个问题的一个例子:

    // something in your view
    this.on(keyup, function() {
      var input = this.getUserInput();
      validationService.validate(input);
    }
    
    // within validationService
    validate: function(input) {
      // generate random int between 1 and 100
      var randKey = Math.floor(Math.random() * (100 - 1)) + 1;
      this.lastRequestKey = randKey;
      this.doAjaxRequest({
        data: {input: input},
        callback: function() {
          if (randKey !== this.lastRequestKey) {
            // a newer request has modified this.lastRequestKey
            return;
          }
          // do something to update the Store 
      });
    }
    

    在此示例中,负责验证服务的对象仅“记住”最近为请求设置的“ key ”。由于其闭包,每个回调在范围内都有其原始键,并且它可以检查其原始键是否等于服务对象上设置的键。如果没有,那意味着发生了另一个请求,我们不再关心这个响应。您将希望按字段设置“键”,以便对字段 B 的新请求不会覆盖对字段 A 的旧请求。您可以通过其他方式解决此问题,但重点是,除了对任何给定输入的最后一个请求的响应。这有一个额外的好处,即在那些丢弃的响应上节省一些更新/渲染周期。

    多字段渲染:当您正确使用 Flux 时,您永远不应该“丢失”数据,因为所有更改都来自 Dispatcher/Store,并且因为 Dispatcher 在上一次更新完全完成之前不会向 Store 发送新更新。因此,只要您使用每个新输入更新 Store,您就不会丢失任何东西。您不必担心对输入 B 的更改会导致您丢失对正在进行的输入 A 的更改,因为对输入 A 的更改将从 Dispatcher 流到 Store 再到 View 并在 Dispatcher 之前完成渲染将允许对输入 B 的更改开始处理。 (这意味着渲染应该很快,因为它们会阻止下一个操作。React 使用 Flux 运行良好的原因之一。)

    只要您将所有东西都放入商店——并且不要将错误的东西放入商店,上面提到的输入和异步处理内容——您的 UI 就会是准确的。 Flux 模式将每次更改视为保证在下一次更改发生之前完成的原子事务。

    关于javascript - 使用flux时的表单验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35063195/

    相关文章:

    javascript - 修改状态和更新我的 reducer 的正确方法? ( react /Redux)

    reactjs-flux - 通量变化中的emitChange、addChangeListener和removeChangeListener的要点是什么

    javascript - 一旦我在特定部分滚动,使某个 id 消失?

    javascript - 通过async.series传递进度条-nodeJs

    javascript - 如何从 <table><tr><td></td></tr></table> 获取特定的 HTML 控件并将所选控件附加到同一个 <td> 中?

    javascript - 助焊剂及应用状态

    javascript - AngularJS 资源更新时不使用 ID

    javascript - Firefox Add-on SDK 获取选项卡 ID

    javascript - 同构 React 中的实时环境变量

    javascript - Flux + React.js 登录/注册流程