1. 程式人生 > 其它 >基於vue + element 封裝一個基本的steps元件

基於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; .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>