简介

步骤条组件Steps是疏导用户依照流程实现工作的分步导航条。当工作简单或者存在先后关系时,将其分解成一系列步骤,从而简化工作,一半步骤不得少于 2 步。

本文将剖析其源码实现,急躁读完,置信会对您有所帮忙。 组件文档 Steps gitee源码

更多组件分析详见 Element 2 源码分析组件总览

组件源码

步骤条性能提供了两个组件:顶层组件el-steps和 子组件el-step

各组件的 prop 申明,各属性性能阐明详见官网文档 Steps#attributes 。

顶层组件 steps.vue

顶层组件基本上就是一个容器,蕴含着子组件el-step用到的共享状态。在el-step中间接通过$parent获取父实例,扭转和同步其共享状态。

模板渲染成一个类名el-steps的简略div元素,同时应用匿名插槽渲染步骤元素。

  • 申明props 用于内部传入的属性。
  • 属性 steps 用于保留以后实例下子组件el-step的实例数组。
  • 属性 stepOffset 用于设置步骤元素的距离。
  • 定义了侦听器,监听属性 active用于触发的自定义change事件,监听属性 steps 更新每个子组件实例步骤索引。

    // packages\steps\src\steps.vue<template><div  class="el-steps"  :class="[     !simple && 'el-steps--' + direction,     simple && 'el-steps--simple'   ]">    <slot></slot></div></template><script> export default {  // props ... data() {  return {    steps: [],    stepOffset: 0  };}, watch: {  active(newVal, oldVal) {    this.$emit('change', newVal, oldVal);  },   steps(steps) {    steps.forEach((child, index) => {      child.index = index;    });  }}};</script> 

步骤组件状态初始化

为了更好了解步骤组件一些状态初始化操作, 接下联合父子组件的生命周期流程进行解说。

父子组件实例在创立时经验一系列的初始化步骤:父beforeCreate -> 父created -> 父beforeMount ->子beforeCreate -> 子created -> 子beforeMount -> 子mounted-> 父mounted

首先,顶层组件el-steps初始化实例、 解析props、data()和侦听器等选项设置结束。

其次,子组件el-step初始化实例、 解析props、data() 、计算属性、办法和侦听器等选项设置结束。定义了beforeCreate钩子函数,当子组件实例初始化实现之后立刻将该实例增加至父组件的属性steps数组中。

// packages\steps\src\step.vuebeforeCreate() {  this.$parent.steps.push(this);},

再次,定义了mounted钩子函数,当子组件el-step被挂载之后,应用命令式的 $watch() 创立侦听器。用于监听属性index更改,执行侦听回调一次后,调用办法unwatch()就会进行该侦听器。

// packages\steps\src\step.vuedata() {  return {    index: -1 // 实例数组steps中索引值  };},mounted() {   const unwatch = this.$watch('index', val => {    // 省略 ...     // 进行该侦听器    unwatch();  });}

而后,顶层组件的属性steps数组长度大于0,会执行侦听回调,更新每个子组件实例的属性 index值,即实例在数组steps中索引值。

// packages\steps\src\steps.vuewatch: {   steps(steps) {     steps.forEach((child, index) => {       child.index = index;    });  }}

而后,触发子组件的index的属性侦听回调,此时会在子组件创立侦全局状态activeprocessStatus的侦听器,用于更新各个子组件的状态显示。用于触发回调办法updateStatus,参数是以后激活步骤的index。

// packages\steps\src\step.vueconst unwatch = this.$watch('index', val => {   this.$watch('$parent.active', this.updateStatus, { immediate: true });  this.$watch('$parent.processStatus', () => {    const activeIndex = this.$parent.active;    this.updateStatus(activeIndex);  }, { immediate: true });  // 进行该侦听器  unwatch();});

最初,执行办法 updateStatus,初始化子组件状态。因为定义了immediate: true,在侦听器创立时立刻办法,所以会调用两次办法。

子组件有三个外部状态(隐式) 激活/已实现/未激活,应用属性internalStatus示意外部状态值(显式)。

  • 已实现 以后激活步骤索引大于此步骤所在数组索引值,internalStatus值为属性finishStatus值。
  • 激活 以后激活步骤索引等于步骤所在数组索引值,若非首元素,则上一步骤元素的状态值不能为 error,也就是 error会中断步骤流程。 internalStatus值为属性processStatus值。
  • 未激活 以后激活步骤索引小于此步骤所在数组索引值,internalStatus值为wait

依据以后子组件的索引,获取它的上一元素prevChild,调用prevChild的办法prevChildcalcProgress计算步骤间轴线款式,此办法稍后会具体介绍。

// packages\steps\src\step.vueupdateStatus(val) {  // 获取上一步骤  const prevChild = this.$parent.$children[this.index - 1];  if (val > this.index) {    // 以后激活步骤索引大于此步骤索引值,该步骤状态为已实现    this.internalStatus = this.$parent.finishStatus;  } else if (val === this.index && this.prevStatus !== 'error') {    // 上一步骤的状态是 'error'的化,之后步骤不会被激活    this.internalStatus = this.$parent.processStatus;  } else {    // 未激活的状态为 'wait'    this.internalStatus = 'wait';  }  // 存在上一步骤  步骤间轴线款式计算  if (prevChild) prevChild.calcProgress(this.internalStatus); },

步骤的状态

下面介绍了整个初始化的流程,兴许大家会有纳闷,动静更新的属性internalStatus值作用是什么?

步骤组件提供了属性status值用于设置以后步骤的状态值;如果未设置, 就会依据属性internalStatus确定状态值。

计算属性currentStatus返回以后步骤的状态值,计算属性 prevStatus 返回上一步骤的状态值。

props:   // ...  status: String // 设置以后步骤的状态,不设置则依据 steps 确定状态}, computed: {  // 以后步骤的状态  currentStatus() {    return this.status || this.internalStatus;  },  // 上一步骤的状态  prevStatus() {    const prevStep = this.$parent.steps[this.index - 1];    return prevStep ? prevStep.currentStatus : 'wait';  },}

参考&关联浏览

'生命周期',vuejs
'watch',vuejs

关注专栏

如果本文对您有所帮忙请关注➕、 点赞、 珍藏⭐!您的认可就是对我的最大反对!