一个step组件

问题描述

开发一个step组件,发现当页面放缩后step的步骤之间间隙变大,不能自动伸缩,于是想到监听元素宽度变化,重新设置step的宽度。

解决方法

  1. 使用element-resize-detector
// 首先安装 `element-resize-detector`

// 引入
const Detector = require('element-resize-detector')

// 使用
mounted () {
   this.handleStep()
},
methods: {
   // 监听step元素宽度变化
   handleStep() {
      let vm = this
      let detector = Detector()
      detector.listenTo(document.querySelector('.j-steps'), el => {
         vm.$nextTick(() => {
            vm.stepWidth = el.offsetWidth / this.curSteps.length + 'px'
           })
       })
    },
}
  • 衍生问题--无法触发以下css发生变化
li:not(:first-child) {}
li:first-child {
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
    .left-arrow {
        display: none;
    }
}
li:last-child {
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
    .right-arrow {
        display: none;
    }
}
  1. 使用指令监听
directives:{
      resize: { // 指令的名称
        bind(el, binding) { // el为绑定的元素,binding为绑定给指令的对象
          console.log(el,"绑定",binding);
          let width = '', height = '';
          function isReize() {
            const style = document.defaultView.getComputedStyle(el);
            if (width !== style.width || height !== style.height) {
              binding.value({width:style.width,height:style.height});  // 关键(这传入的是函数,所以执行此函数)
            }
            width = style.width;
            height = style.height;
          }
          el.__vueSetInterval__ = setInterval(isReize, 300);
        },
        unbind(el) {
          console.log(el,"解绑");
          clearInterval(el.__vueSetInterval__);
        }
      }
    },
<div id="Chart1" v-resize="domResize"></div>
domResize(data){
        let {width, height} = data; // 这里返回的宽高都是带单位的
        console.log("width:",width,"height:",height,"   dom尺寸方式改变");
      },
  • 这个方法是可行的。

最终解决方法

最终发现使用flex布局后,如果盒子内部的元素宽度足够大且相等,就能实现实时等分布局,于是直接设置每一个盒子内的 元素长度为1000px解决了[ganga]。

step组件

<template>
   <ul class="j-steps" ref="stepRef">
    <li class="step"
        :class="[index <= curVal?'isActive':'']"
        :style="{width: '1000px'}"
        v-for="(item, index) in curSteps"
        :key="item">
      <div class="right-arrow"></div>
      <div class="left-arrow"></div>
      <span class="cur-step" v-html="index<curVal?'✓':index+1"></span>
      <span class="step-info">{{ item }}</span>
    </li>
   </ul>
</template>
<script>
export default {
    name: 'Step',
    props: {
        value: {
            type: [String, Number],
            default: ''
        },
        steps: {
            type: Array,
            default: () => {
                return []
            }
        }
    },
    watch: {
        value(val) {
            this.curVal = val
        },
        steps(val) {
            this.curSteps = val
        }
    },
    data() {
        return {
            curVal: this.value,
            curSteps: this.steps,
            stepWidth: 0
        }
    }
}
</script>
<style lang="scss">
    @mixin j-step-arrow {
        content: '';
        width: 0;
        height: 0;
        border-top: 24px solid transparent;
        border-bottom: 24px solid transparent;
        position: absolute;
        top: -1px;
    }

    .j-steps{
        display: flex;
        flex-wrap: nowrap;
        justify-content: space-between;
        li:not(:first-child) {
            margin-left:8px
        }
        li.step {
            position: relative;
            width: 238px;
            height: 48px;
            background: #F7F8FA;
            line-height: 48px;
            text-align: center;
        }

        .right-arrow:after {
            @include j-step-arrow;
            border-left: 12px solid #F7F8FA;
            right: -13px;
            z-index: 9;
        }

        .right-arrow:before {
            @include j-step-arrow;
            border-left: 12px solid #F7F8FA;
            right: -12px;
            z-index: 10;
        }
        .left-arrow:after{
            @include j-step-arrow;
            border-left: 12px solid #fff;
            left: -1px;
            z-index: 7;
        }
        .left-arrow:before{
            @include j-step-arrow;
            border-left: 12px solid #fff;
            left: -2px;
            z-index: 8;
        }
        li:first-child {
            border-top-left-radius: 4px;
            border-bottom-left-radius: 4px;
            .left-arrow {
                display: none;
            }
        }
        li:last-child {
            border-top-right-radius: 4px;
            border-bottom-right-radius: 4px;
            .right-arrow {
                display: none;
            }
        }

        .cur-step {
            display: inline-block;
            width: 18px;
            height: 18px;
            background: #C1C1C1;
            border-radius: 9px;
            color: #fff;
            line-height: 18px;
            text-align: center;
            margin: 0 6px 0 0;
        }

        .isActive {
            border: 1px solid #4260DB;
            .cur-step {
                background: #4260DB;
            }
            .step-info{
                color: #4260DB;
                font-weight: 600;
            }
            .left-arrow:after,
            .right-arrow:after {
                border-left: 12px solid #4260DB;
            }
        }
    }
</style>
<Step :steps="steps" v-model="curStep"></Step>
data() {
   return {
      curStep: 0,
      steps: ['step1', 'step2'],
   };
}

handleNext() {
    let len = this.steps.length - 1
    if(++this.curStep > len) this.curStep = 0
},
posted @ 2021-01-21 20:41  小方块的世界  阅读(195)  评论(0编辑  收藏  举报