【问题标题】:How to implement a stepper decision flow in JavaScript?如何在 JavaScript 中实现步进式决策流程?
【发布时间】:2020-03-29 14:28:28
【问题描述】:

我实际上并不确定要描述的内容的最佳名称。决策流、决策矩阵、流程图……

实现基本上是“选择你自己的冒险”步进器的流程或将流程图变成步进器的最佳方式是什么?

例如,您有一个带有步骤的 UI,而将显示的下一步和上一步取决于上一步中的数据。现在,我有一个 switch 语句来确定要出现的步骤,以及非常丑陋的逻辑来确定应该是下一步还是上一步。

(我正在使用 React 为每个步骤渲染组件,但我认为这与问题无关)。

renderStep = () => {
    switch (currentStep) {
      case 1:
        return <FirstStep/>
      case 2:
        return <SecondStep />
      case 2.5:
        return <SecondStepA />
      case 3:
        return <ThirdStep />
      case 3.25:
        return <ThirdStepA />
      case 3.5:
        return <ThirdStepB />
      case 3.75:
        return <ThirdStepC />
      case 4:
        return <FourthStep />
      default:
        return null
    }
  }

现在单击“下一步”或“上一步”将发送数据,并确定每个步骤要转到哪个步骤。如果流是线性的,那将非常容易——更新数据,递增或递减一。但是使用条件流,它变得更加复杂。

  goToPreviousStep = () => {
    const { currentStep } = this.state

    this.setState(prevState => {
      if (currentStep === 4 && prevState.someDataHappened) {
        return { currentStep: prevState.currentStep - 0.5 }
      } else if (currentStep === 3.5) {
        return { currentStep: prevState.currentStep - 0.5 }
      } else {
        return { currentStep: prevState.currentStep - 1 }
      }
    })
  }

如果尝试支持超出此范围的其他嵌套可能会更加复杂。随着它的增长,我知道它将变得无法维护,但是我找不到任何好的资源来将这些数据存储在表中或使其更具程序性。有人能指出我正确的方向吗?

不确定我是否必须写一些非确定性的有限自动机之类的......

【问题讨论】:

  • Javascript 与这里的任何其他语言没有什么不同,可能更强大。但正如你所说。忘记表示层。您需要数据 (JSON) 和基本的 rule 类。从那里您可以派生和创建更复杂的规则。最基本的是一个处理步骤。更复杂的是 IF 规则。名单还在继续。
  • @Bibberty 假设每个步骤都由获取数据的新 API 调用确定,而下一个步骤由该 API 数据确定...我无法内置 JSON进步。这种方法还能用吗?
  • Tania,您构建了一组类,从一个基类开始,该类接受来自父类的数据并执行派生类中的逻辑。这反过来又基于实现的逻辑影响数据并调用其一个或多个子级。

标签: javascript reactjs decision-tree flowchart stepper


【解决方案1】:

您是否看过类似于链表的工作原理的东西?每个步骤都是一个对象,每个步骤都引用其上一步以及潜在的下一步。遍历可以通过这些链接完成,并且当前步骤可以存储为对象而不是某种数字。如果你想给它们编号,你可以简单地计算所有的步骤,然后向后遍历到第一步,看看你在哪个步骤编号。

您可以在 Step 原型中放入所需的尽可能多的数据,以便每个步骤定义渲染它所需的一切,基于它采取行动等。标题、文本、关联的 url 等。

function Step() {}

Step.prototype.previous = null;
Step.prototype.next = [];

Step.prototype.addNext = function(nextStep) {
  let step = Object.assign(new Step(), nextStep);
  step.previous = this;
  this.next.push(step);
}

Step.prototype.getNumber = function() {
  var number = 0;
  var step = this;
  
  while(step) {
    step = step.previous;
    number += 1;
  }
  
  return number;
}


let CurrentStep = null;
function createSteps() {

  const step1 = new Step();
  const step2 = new Step();
  const step2_1 = new Step();
  const step2_2 = new Step();
  const step3 = new Step();
  
  CurrentStep = step1;
  
  step1.addNext(step2);
  step1.addNext(step2_1);
  step1.addNext(step2_2);
  
  step2.addNext(step3);
  step2_1.addNext(step3);
  step2_2.addNext(step3);

}

createSteps();

console.log(CurrentStep.getNumber());
console.log(CurrentStep.next[0].getNumber());
console.log(CurrentStep.next[1].getNumber());
console.log(CurrentStep.next[2].getNumber());

【讨论】:

  • 这看起来是个不错的方法。仍然有很多逻辑来确定要移动到哪个步骤,但是确定选择哪个下一个或上一个比减去和添加 0.5 更好......
  • 在这个例子中你会如何“转到(有条件的)下一个”?
  • 接下来(有条件的)是什么意思?你能说得更具体点吗?
  • 不幸的是,这种方法的“以前”存在问题。 step1.addNext(step2) 会做 step2->step1 的前一个,然后step1.addNext(step2_1) 会做 step2_1->step1 的前一个,然后step2.addNext(step3) 会做 step3->step2 的前一个,然后step2_1.addNext(step3) 会做 step2_1->step2 的前一个step3->step2_1,这意味着如果您从第 2 步到第 3 步,它将假定您从第 2_1 步到达那里。
  • 谢谢,@flagoworld,我最终做了类似的事情,并为以前使用了一个数组。这很有帮助。
猜你喜欢
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 2013-05-29
  • 2014-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多