美文网首页前端前端都会去了解的网页前端后台技巧(CSS+HTML)
vue3 简简单单写个向左展开收缩panel的通用组件

vue3 简简单单写个向左展开收缩panel的通用组件

作者: 阿巳交不起水电费 | 来源:发表于2023-11-07 14:51 被阅读0次

    效果如下

    GIF 2023-11-8 14-49-43.gif

    原理:

    收缩按钮是相对父节点定位的。点击后通过更改父组件的left 值进行展开收缩,收缩时left为-1 * 父节点宽度, 展开时还原为初始状态。

    源码:

    <!-- 
       author:yangfeng
       date:20231107
       在此组件父节点添加一个展开收缩的按钮,点击时收缩父组件,再次点击展开父组件
      【原理: 通过更改父组件的left 值进行展开收缩,收缩时left为-1 * 父节点宽度, 展开时还原为初始状态】
      【注意:组件是相对于父组件定位的!】
     -->
    <template>
      <div :class="{ 'ec-arrow': true }" @click="trigger" ref="arrowRefDom">
        <img v-show="open" src="@/assets/ss-left.png" />
        <img v-show="!open" src="@/assets/ss-right.png" />
      </div>
    </template>
    
    <script setup>
    import { ref, onMounted, watch } from 'vue'
    const props = defineProps({
      // 是开启还是关闭状态
      open: {
        type: Boolean,
        default: true
      }
    })
    const emit = defineEmits([
      'update:open', // v-model
      'click'
    ])
    
    const arrowRefDom = ref()
    let parentNodeCssInfo = {} // 父节点初始样式
    
    const trigger = () => {
      let bool = !props.open
      emit('update:open', bool)
      emit('click', bool)
    }
    
    /**
     * 显示隐藏父节点panel
     * @param {*} bool true:展开父节点 false:收缩父节点
     */
    const hideOrShowParentNode = (bool = false) => {
      let parentNode = arrowRefDom.value.parentNode
      if (!parentNode) return
      if (bool) { // 展开父节点
        parentNode.style.left = parentNodeCssInfo.left || 0
      } else { // 折叠父节点
        parentNode.style.left = -1 * parentNode.offsetWidth + 'px'
      }
    }
    
    // 获取样式
    const getStyle = (htmlNode, str) => {
      if(!htmlNode || !str) return ''
      if (htmlNode.currentStyle) { // ie
        return htmlNode.currentStyle[str]
      } else {
        return window.getComputedStyle(htmlNode, null)[str]
      }
    }
    
    // 初始化
    const init = () => {
      // 存储父节点信息
      let parentNode = arrowRefDom.value.parentNode
      if (!parentNode) return
      parentNode.style.transition = 'left ease 0.5s'
      parentNodeCssInfo = {
        left: getStyle(parentNode, 'left')
      }
    
      // 初始状态
      hideOrShowParentNode(props.open)
    }
    
    watch(()=>props.open,(newVal)=>{
      hideOrShowParentNode(newVal)
    })
    
    onMounted(() => {
      init()
    })
    </script>
    
    <style lang="scss" scoped>
    $width: 26px;
    $height: 77px;
    
    .ec-arrow {
      width: $width;
      height: $height;
      top: 50%;
      right: -1 * $width;
      margin-top: -0.5 * $height;
      position: absolute;
      cursor: pointer;
      z-index: 99;
    
      img {
        width: 100%;
        height: 100%;
      }
    }
    </style>
    

    图标:

    image.png

    调用方式:

    image.png

    总结

    代码很简单,考虑到比较常用就分享给大家,遇到panel展开方向不一样的自行扩展!

    若对你有帮助,请点个赞吧,若能打赏不胜感激,谢谢支持!
    本文地址:https://www.jianshu.com/p/d4f9f5107aab?v=1699426268971,转载请注明出处,谢谢。

    相关文章

      网友评论

        本文标题:vue3 简简单单写个向左展开收缩panel的通用组件

        本文链接:https://www.haomeiwen.com/subject/kblfwdtx.html