基于vue + element 封装一个基本的steps组件
1、新建m-step文件夹和index.js文件
import Step from '../m-steps/src/m-step'; /* istanbul ignore next */ Step.install = function(Vue) { Vue.component(Step.name, Step); }; export default Step;
2、新建m-steps,src文件夹和index.js文件;以及m-step.vue和m-steps.vue文件
2.1、m-steps/src/m-steps.vue
<template> <div class="m-steps-area"> <div class="m-steps"> <slot></slot> </div> </div> </template> <script> export default { name: 'mSteps', props: { active: { type: Number, default: 0 }, finishStatus: { type: String, default: 'finish' }, processStatus: { type: String, default: 'process' } }, data() { return { steps: [], }; }, methods: { }, watch: { active(newVal, oldVal) { this.$emit('change', newVal, oldVal); }, steps(steps) { steps.forEach((child, index) => { child.index = index; }); } } }; </script> <style lang="scss"> </style>
2.2、m-steps/src/m-step.vue
<template> <div class="m-steps-item"> <div class="m-steps-icon" :class="['is-' + currentStatus]"> <template v-if="currentActive <= index"> <i class="el-icon-close" v-if="status == 'error'"></i> <span class="u-icon" v-else>{{ index + 1 }}</span> </template> <template v-else> <i class="el-icon-close" v-if="status == 'error'"></i> <i class="el-icon-check" v-else></i> </template> </div> <div class="m-steps-content" :class="['is-' + currentStatus]"> <div class="u-steps-title">{{ title }}</div> <div class="u-steps-description">{{ description }}</div> </div> </div> </template> <script> export default { name: 'mStep', props: { title: String, icon: String, description: String, status: String }, data() { return { index: "-1", currentActive: this.$parent.active, totalSteps: "", internalStatus: '' } }, beforeCreate() { this.$parent.steps.push(this); this.totalSteps = this.$parent.steps; this.index = this.totalSteps.indexOf(this); }, beforeDestroy() { const steps = this.$parent.steps; const index = steps.indexOf(this); if (index >= 0) { steps.splice(index, 1); } }, computed: { currentStatus() { return this.status || this.internalStatus; }, }, methods: { 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') { this.internalStatus = this.$parent.processStatus; } else { this.internalStatus = 'wait'; } // if (prevChild) prevChild.calcProgress(this.internalStatus); }, }, mounted() { 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(); }); } } </script> <style lang="scss"> .m-steps-area { .m-steps { // padding: 30px 0; display: flex; .m-steps-item { display: inline-block; flex: 1; // 弹性盒模型对象的子元素都有相同的长度,且忽略它们内部的内容 overflow: hidden; font-size: 16px; line-height: 32px; .m-steps-icon { display: inline-block; margin-right: 14px; margin-left: 14px; width: 32px; height: 32px; border-radius: 50%; text-align: center; border: 1px solid rgba(0, 0, 0, .4); color: rgba(0, 0, 0, 0.4); &.is-finish { color: #409EFF; border: 1px solid #409EFF; } &.is-process { border: 1px solid #409EFF; color: #ffffff; background-color: #409EFF; } &.is-error { border: 1px solid #F6384C; color: #F6384C; } } &:first-child { .m-steps-icon { margin-left: 0; } } &:last-child { flex: none; .u-steps-title { &::after { height: 0; } } } .m-steps-content { display: inline-block; vertical-align: top; color: rgba(0, 0, 0, 0.4); &.is-process, &.is-finish { color: #409EFF; } &.is-finish { .u-steps-title { &::after { background: #409EFF; } } } &.is-error { color: #F6384C; .u-steps-title { &::after { background: #F6384C; } } } .u-steps-title { position: relative; padding-right: 17px; font-weight: bold; display: inline-block; &::after { position: absolute; top: 16px; left: 100%; display: block; width: 9999px; height: 1px; background: #DCDCDC; content: ""; } } .u-steps-description { font-size: 14px; max-width: 140px; } } } } } </style>
2.3、m-steps/index.js
import Steps from './src/m-steps'; /* istanbul ignore next */ Steps.install = function(Vue) { Vue.component(Steps.name, Steps); }; export default Steps;
3、main.js文件引入
import mSteps from '@/components/m-steps' import mStep from '@/components/m-step' Vue.use(mStep) Vue.use(mSteps)
4、使用
<mSteps :active="active" class="mb15" style="margin-top:60px;"> <mStep title="填写项目信息"></mStep> <mStep title="上传申请材料"></mStep> <mStep title="支付保费"></mStep> <mStep title="金融机构审核"></mStep> <mStep title="出具保函"></mStep> </mSteps> </div>