vue3手写步骤条

改写自:Vue步骤条(Steps)_theMuseCatcher的博客-CSDN博客_vue 步骤条

因目前使用技术栈为vue3 所以稍作修改:

修改过程中的问题:

1. ref响应式失效:ref之后,不会对变量直接进行更改,需要.value

2. props中的数据可以直接在页面元素中使用

自定义封装步骤条:

<template>
  <div class="m-steps-area">
    <div class="m-steps">
      <div
        :class="['m-steps-item',
          { 'finished': current > n,
            'process': current === n && n !== totalSteps,
            'last-process': current === totalSteps && n === totalSteps,
            'middle-wait': current < n && n !== totalSteps,
            'last-wait': current < n && n === totalSteps,
          }
        ]"
        v-for="n in totalSteps"
        :key="n"
        @click="onChange(n)">
        <div class="m-steps-icon">
          <span class="u-icon">{{ current }}</span>
        </div>
        <div class="m-steps-content">
          <div class="u-steps-title">{{ stepsLabel[n-1] || 'S ' + n }}</div>
          <!-- <div class="u-steps-description">{{ stepsDesc[n-1] || 'Desc ' + n }}</div> -->
        </div>
      </div>
    </div>
    <el-button @click="onChange">下一步</el-button>
  </div>
</template>
<script>
import { reactive,  toRefs,ref } from 'vue'

export default {
  props: {
    stepsLabel: { // 步骤title数组
      type: Array,
      default: () => {
        return []
      }
    },
    stepsDesc: { // 步骤description数组
      type: Array,
      default: () => {
        return []
      }
    },
    totalSteps: { // 总的步骤数
      type: Number,
      default: 3
    },
    currentStep: { // 当前选中的步骤
      type: Number,
      default: 1
    }
  },
 setup(prop){
  let state = reactive({
    
  }) 
  let current = ref(1)

  const onChange  = ()=>{ // 点击切换选择步骤
      
      // if (state.current < prop.totalSteps) {
      //   // console.log(state.current)
      //   state.current++
      // }else {
      //   state.current = 1
      // }

      if (current.value < prop.totalSteps) {
        // console.log(current)
        current.value++
      }else {
        // console.log('ll',current)
        current.value = 1
      }
      
    }
  return {
    ...toRefs(state),
    current,
    onChange
  }
 }
}
</script>
<style lang="scss" scoped>
.m-steps-area {
  width: 900px;
  margin: 0px auto;
  .m-steps {
    padding: 30px 0;
    display: flex;
    .m-steps-item {
      display: inline-block;
      flex: 1; // 弹性盒模型对象的子元素都有相同的长度,且忽略它们内部的内容
      text-align: left;
      overflow: hidden;
      font-size: 16px;
      line-height: 32px;
      .m-steps-icon {
        display: inline-block;
        margin-right: 8px;
        width: 32px;
        height: 32px;
        border-radius: 50%;
        text-align: center;
      }
      .m-steps-content {
        display: inline-block;
        vertical-align: top;
        padding-right: 10px;
        .u-steps-title {
          position: relative;
          display: inline-block;
          padding-right: 16px;
        }
        .u-steps-description {
          font-size: 14px;
          max-width: 140px;
        }
      }
    }
    .finished {
      margin-right: 16px;
      cursor: pointer;
      // &:hover {
      //   .m-steps-content {
      //     .u-steps-title {
      //       color: #1890ff;
      //     }
      //     .u-steps-description {
      //       color: #1890ff;
      //     }
      //   }
      // }
      .m-steps-icon {
        background: #1890ff;
        border: 1px solid rgba(0,0,0,.25);
        border-color: #1890ff;
        .u-icon {
          color: #fff;
        }
      }
      .m-steps-content {
        color: rgba(0,0,0,.65);
        .u-steps-title {
          color: rgba(0,0,0,.65);
          &:after {
            background: #1890ff;
            position: absolute;
            top: 16px;
            left: 100%;
            display: block;
            width: 9999px;
            height: 1px;
            content: "";
          }
        }
        // .u-steps-description {
        //   color: rgba(17, 153, 67, 0.45);
        // }
      }
    }
    .process {
      margin-right: 16px;
      .m-steps-icon {
        background: #1890ff;
        border: 1px solid rgba(0,0,0,.25);
        border-color: #1890ff;
        .u-icon {
          color: #fff;
        }
      }
      .m-steps-content {
        color: rgba(0,0,0,.65);
        .u-steps-title {
          color: rgba(0,0,0,.85);
          &:after {
            background: #e8e8e8;
            position: absolute;
            top: 16px;
            left: 100%;
            display: block;
            width: 9999px;
            height: 1px;
            content: "";
          }
        }
        .u-steps-description {
          color: rgba(0,0,0,.65);
        }
      }
    }
    .last-process {
      margin-right: 0;
      .m-steps-icon {
        background: #1890ff;
        border: 1px solid rgba(0,0,0,.25);
        border-color: #1890ff;
        .u-icon {
          color: #fff;
        }
      }
      .m-steps-content {
        color: rgba(0,0,0,.65);
        .u-steps-title {
          color: rgba(0,0,0,.85);
        }
        .u-steps-description {
          color: rgba(0,0,0,.65);
        }
      }
    }
    .middle-wait {
      margin-right: 16px;
      cursor: pointer;
      &:hover {
        .m-steps-icon {
          border: 1px solid #1890ff;
          .u-icon {
            color: #1890ff;
          }
        }
        .m-steps-content {
          .u-steps-title {
            color: #1890ff;
          }
          .u-steps-description {
            color: #1890ff;
          }
        }
      }
      .m-steps-icon {
        background: #fff;
        border: 1px solid rgba(0,0,0,.25);
        .u-icon {
          color: rgba(0,0,0,.25);
        }
      }
      .m-steps-content {
        color: rgba(0,0,0,.65);
        .u-steps-title {
          color: rgba(0,0,0,.45);
          &:after {
            background: #e8e8e8;
            position: absolute;
            top: 16px;
            left: 100%;
            display: block;
            width: 9999px;
            height: 1px;
            content: "";
          }
        }
        .u-steps-description {
          color: rgba(0,0,0,.45);
        }
      }
    }
    .last-wait {
      margin-right: 0;
      cursor: pointer;
      &:hover {
        .m-steps-icon {
          border: 1px solid #1890ff;
          .u-icon {
            color: #1890ff;
          }
        }
        .m-steps-content {
          .u-steps-title {
            color: #1890ff;
          }
          .u-steps-description {
            color: #1890ff;
          }
        }
      }
      .m-steps-icon {
        background: #fff;
        border: 1px solid rgba(0,0,0,.25);
        .u-icon {
          color: rgba(0,0,0,.25);
        }
      }
      .m-steps-content {
        color: rgba(0,0,0,.65);
        .u-steps-title {
          color: rgba(0,0,0,.45);
        }
        .u-steps-description {
          color: rgba(0,0,0,.45);
        }
      }
    }
  }
}
</style>

引用步骤条组件:

<template>
<div class="index">
  <Steps :currentStep="1" :totalSteps="6" :stepsLabel="stepsLabel" :stepsDesc="stepsDesc"  />
  
</div>

手写Vue3日期选择器可以通过以下步骤实现: 1. 创建一个名为DatePicker的Vue组件。 2. 在组件中定义一个data属性,包含所需的日期数据,例如当前日期、选择的开始日期和结束日期。 3. 在模板中创建日期选择器的界面,包括一个日历表格和选择按钮。 4. 在方法中实现选择日期的逻辑。可以通过按钮点击事件或者直接在日历表格中选择日期来触发选择逻辑。在选择日期后,更新开始日期和结束日期的值。 5. 在组件中定义一个computed属性,用于计算并返回选择的日期范围。 6. 在模板中使用v-model指令将选择的日期范围绑定到父组件的数据上。 以下是一个简单的Vue3日期选择器的示例代码: ``` <template> <div> <input type="text" v-model="selectedRange" readonly> <button @click="showCalendar">选择日期</button> <div v-if="showCalendar"> <!-- 日历表格 --> </div> </div> </template> <script> import { ref, reactive, computed } from 'vue'; export default { setup() { // 数据初始化 const selectedRange = ref(''); const showCalendar = ref(false); const startDate = ref(null); const endDate = ref(null); // 显示日历 const showCalendar = () => { showCalendar.value = true; }; // 选择日期 const selectDate = (date) => { if (!startDate.value) { startDate.value = date; } else if (!endDate.value) { if (date > startDate.value) { endDate.value = date; } else { endDate.value = startDate.value; startDate.value = date; } } else { startDate.value = date; endDate.value = null; } }; // 计算选择的日期范围 const selectedRange = computed(() => { if (startDate.value && endDate.value) { return `${startDate.value} - ${endDate.value}`; } else if (startDate.value) { return startDate.value; } else { return ''; } }); return { selectedRange, showCalendar, selectDate }; } }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值