共计 3432 个字符,预计需要花费 9 分钟才能阅读完成。
简介
步骤条组件 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.vue
beforeCreate() {this.$parent.steps.push(this);
},
再次,定义了 mounted
钩子函数,当子组件 el-step
被挂载之后,应用命令式的 $watch()
创立侦听器。用于监听属性 index
更改, 执行侦听回调一次后,调用办法 unwatch()
就会进行该侦听器。
// packages\steps\src\step.vue
data() {
return {index: -1 // 实例数组 steps 中索引值};
},
mounted() {
const unwatch = this.$watch('index', val => {
// 省略 ...
// 进行该侦听器
unwatch();});
}
而后,顶层组件的属性 steps
数组长度大于 0, 会执行侦听回调,更新每个子组件实例的属性 index
值,即实例在数组 steps 中索引值。
// packages\steps\src\steps.vue
watch: {steps(steps) {steps.forEach((child, index) => {child.index = index;});
}
}
而后,触发子组件的 index
的属性侦听回调,此时会在子组件创立侦全局状态 active
、processStatus
的侦听器,用于更新各个子组件的状态显示。用于触发回调办法updateStatus
,参数是以后激活步骤的 index。
// packages\steps\src\step.vue
const 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.vue
updateStatus(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
关注专栏
如果本文对您有所帮忙请关注➕、点赞👍、珍藏⭐!您的认可就是对我的最大反对!