Vue3从0到1组件开发-系统组件:Steps步骤条

1,945 阅读1分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

缘何

前面的几篇关于系统组件的文章可以在专栏中看到,这几个组件在如今的前端开发中可以说是必不可少的常见组件。

而Steps步骤条这一组件相较而言都不算常见了,只是在特定情况下,才会使用到,并且也并非比可替代的。

算是一个功能性的组件吧。

不过这里,既然是封装成组件了,自然是需要去完善他,使其更加丰富。

主要还是以考虑横向以及纵向、图标的多样性这些为主。在用的时候也能有更多的选择。

结构

结构的话,简单的做法可以按照业务需求设计为单向,固定图标的。但是在组建中的话,自然是考虑水平垂直的。

此外图标因为直接用现成的组件,但是也可以加上slot插槽实现自定义图标。

block content
div.yx-steps(
  :class="[`yx-steps-${direction}`, size ? `yx-steps-${size}` : '']"
)
  div.yx-steps-wrap(
    :class="[`yx-steps-item`, `yx-steps-${status}`, icon || $slots.icon ? 'yx-stpes-custom' : '']"
  )
    div.yx-steps-item-head
      div.yx-steps-item-head-inner
        span(
          v-if="!icon && !$slots.icon && status !== 'finish' && status !== 'error'"
        ) {{stepNumber}}
        span(
          :class="icon ? `yx-items-step-${icon}` : ''"
          v-else
        )
    div.yx-steps-item-main
      div.yx-steps-item-title
        slot(name="title") {{ title }}
      div.yx-steps-items-content(
        v-if="content || $slots.content"
      )
        slot(name="content") {{ content }}

这里的结构主要是包含的步骤的标题和内容部分。

样式可以自定义的哦。

逻辑部分。

因为只是步骤条,所以没有什么复杂的逻辑。

需要注意的就是,当前步骤的状态改变时,需要触发事件去更改当前步骤的状态。

例如当进行下一步时,当前步骤要修改为已完成的状态,之后修改对应的样式即可。

const updateChildProps = (isInit) => {
  const total = ctx.$children.length;
  ctx.$children.forEach((child, index) => {
    child.stepNumber = index + 1;

    if (props.direction === 'horizontal') {
      child.total = total;
    }
    if (!(isInit && child.status)) {
      if (index === props.current) {
        if (props.status !== 'error') {
          child.status = 'process';
        }
      } else if (index < props.current) {
        child.status = 'finish';
      } else {
        child.status = 'wait';
      }
    }

    if (child.status !== 'error' && index !== 0) {
      .$children[index - 1].nextError = false;
    }
  });
}

步骤的状态可以自定义,这里的话是按照三种状态来处理的。

最后

步骤的内容和宽\高在实际开发中是允许伸缩的。

所以对溢出的处理也是需要考虑在其中的。

const updateCurrent = (isInit) => {
  if (ctx.current < 0 || ctx.current >= ctx.$children.length ) {
    return;
  }
  if (isInit) {
    const current_status = ctx.$children[props.current].currentStatus;
    if (!current_status) {
      ctx.$children[props.current].currentStatus = props.status;
    }
  } else {
    ctx.$children[props.current].currentStatus = props.status;
  }
}