Vue.js implements simple folding panel

Vue.js implements simple folding panel

This article example shares the specific code of Vue.js to implement a simple folding panel for your reference. The specific content is as follows

The code is as follows:

Main file: app.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <collpase>
      <collpase-item
        :title="item.name"
        :showAnimation="true"
        v-for="(item, i) in chapterList"
        :key="i"
      >
        <div class="list" v-for="(it, index) in item.list" :key="index">
          {{it.name}}
        </div>
      </collpase-item>
    </collpase>
  </div>
</template>

<script>
import Collpase from './components/Collpase.vue';
import CollpaseItem from './components/CollpaseItem.vue'

export default {
  name: 'App',
  data() {
    return {
      chapterList: [
        {
          name: 'Title 1',
          list: [
            {
              name: 'Yes, yes, yes, yes, yes'
            },
            {
              name: 'Ahhhhh'
            }
          ]
        },
        {
          name: 'Title 2',
          list: [
            {
              name: 'Yes, yes, yes, yes, yes'
            },
            {
              name: 'Ahhhhh'
            },
            {
              name: 'Ahhhhh'
            }
          ]
        }
      ]
    }
  },
  components:
    Collpase,
    CollpaseItem,
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Subcomponents:

<template>
 <div class="collapse">
  <slot />
 </div>
</template>
<script>
 export default {
  name: 'Collapse',
  props: {
   accordion: {
    type: [Boolean, String],
    default: false
   }
  },
  provide() {
   return {
    collapse: this
   }
  },
  created() {
   this.childrens = []
  },
  methods: {
   onChange() {
    let activeItem = []
    this.childrens.forEach((vm) => {
     if (vm.isOpen) {
      activeItem.push(vm.nameSync)
     }
    })
    this.$emit('change', activeItem)
   }
  }
 }
</script>
<style lang="css" scoped>
 .collapse {
  width: 100%;
  display: flex;
  flex: 1;
  flex-direction: column;
 }
</style>

Subcomponents:

<template>
 <div>
    <div :class="{ 'collapse-disabled': disabled,'collapse-cell--notdisabled': !disabled, 'collapse-cell--open': isOpen,'collapse-cell--hide': !isOpen }" class="collapse-cell">
      <div :class="{ 'collapse-disabled': disabled}" class="collapse-cell__title" @click="onClick">
        <span class="collapse-cell__title-text">{{ title }}</span>
        <img :class="{ 'active': isOpen, 'active-animation': showAnimation === true }" class="title-arrow" src="https://static-mumway.oss-cn-zhangjiakou.aliyuncs.com/NetworkFrontEnd/wsj/yslbq/btn_dropdown.png"/>
      </div>
      <div :class="{'collapse-cell__content--hide':!isOpen}" class="collapse-cell__content">
        <div :class="{ 'active-animation': showAnimation === true }" class="collapse-cell__wrapper" :style="{'transform':isOpen?'translateY(0)':'translateY(-50%)','-webkit-transform':isOpen?'translateY(0)':'translateY(-50%)'}">
          <slot />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
 export default {
  name: 'UniCollapseItem',
  props: {
   title:
    // List title type: String,
    default: ''
   },
   name: {
    // Unique identifier type: [Number, String],
    default: 0
   },
   disabled:
    // Whether to disable type: Boolean,
    default: false
   },
   showAnimation:
    // Whether to display animation type: Boolean,
    default: false
   },
   open:
    // Whether to expand type: Boolean,
    default: false
   },
   thumb:
    // thumbnail type: String,
    default: ''
   }
  },
  data() {
   return {
    isOpen: false
   }
  },
  watch:
   open(val) {
    this.isOpen = val
   }
  },
  inject: ['collapse'],
  created() {
   this.isOpen = this.open
   this.nameSync = this.name ? this.name : this.collapse.childrens.length
   this.collapse.childrens.push(this)
   if (String(this.collapse.accordion) === 'true') {
    if (this.isOpen) {
     let lastEl = this.collapse.childrens[this.collapse.childrens.length - 2]
     if (lastEl) {
      this.collapse.childrens[this.collapse.childrens.length - 2].isOpen = false
     }
    }
   }
  },
  methods: {
   onClick() {
    if (this.disabled) {
     return
    }
    if (String(this.collapse.accordion) === 'true') {
     this.collapse.childrens.forEach(vm => {
      if (vm === this) {
       return
      }
      vm.isOpen = false
     })
    }
    this.isOpen = !this.isOpen
    this.collapse.onChange && this.collapse.onChange()
    this.$forceUpdate()
   }
  }
 }
</script>

<style lang="css" scoped>
 .collapse-cell {
  flex-direction: column;
  border-color: #f0f0f0;
  border-bottom-width: 1px;
 }
 .collapse-cell--open {
  background-color: #fff;
 }
 .collapse-disabled {
  cursor: not-allowed !important;
 }
 .collapse-cell--hide {
  height: 48px;
 }
 .active-animation {
  transition-property: transform;
  transition-duration: 0.3s;
  transition-timing-function: ease;
 }

 .collapse-cell__title {
  border-bottom: 1px solid #f0f0f0;
  padding: 12px 20px;
  position: relative;
  display: flex;
  width: 100%;
  box-sizing: border-box;
  height: 44px;
  line-height: 44px;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  cursor: pointer;
 }
 .collapse-cell__title-img {
  margin-right: 10px;
 }
 .title-arrow {
  width: 22px;
  height: 14px;
 }
 .active {
  transform: rotate(180deg);
 }
 .collapse-cell__title-text {
  flex: 1;
  font-size: 16px;
  margin-right: 16px;
  white-space: nowrap;
  color: #333333;
    font-weight: bold;
  lines: 1;
  overflow: hidden;
  text-overflow: ellipsis;
 }
 .collapse-cell__content {
  overflow-x:hidden;
 }
 .collapse-cell__wrapper {
  display: flex;
  flex-direction: column;
 }
 .collapse-cell__content--hide {
  height: 0px;
  line-height: 0px;
 }
</style>

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Public multi-type attachment image upload area in Vue page and applicable folding panel (sample code)
  • Vuejs realizes the expansion and contraction animation effect of the folding panel
  • Encapsulation of Vue folding panel component

<<:  Use neat HTML markup to build your pages

>>:  Detailed explanation of 5 solutions for CSS intermediate adaptive layout

Recommend

Mysql solution to improve the efficiency of copying large data tables

Preface This article mainly introduces the releva...

How to query json in the database in mysql5.6 and below

When saving data in MySQL, sometimes some messy a...

Summary of commonly used commands for docker competition submission

Log in to your account export DOCKER_REGISTRY=reg...

Use of Linux usermod command

1. Command Introduction The usermod (user modify)...

The difference between KEY, PRIMARY KEY, UNIQUE KEY, and INDEX in MySQL

The problem raised in the title can be broken dow...

MySQL encryption and decryption examples

MySQL encryption and decryption examples Data enc...

Some tips on website design

In fact, we have been hearing a lot about web des...

Nexus uses API to operate

Nexus provides RestApi, but some APIs still need ...

Detailed process record of nginx installation and configuration

Table of contents 1 Introduction to nginx 1 What ...

What we have to say about CSS absolute and relative

Written in the opening: Absolute said: "Rela...

Mysql queries the transactions being executed and how to wait for locks

Use navicat to test and learn: First use set auto...

Summary of how to modify the root password in MySQL 5.7 and MySQL 8.0

MySQL 5.7 version: Method 1: Use the SET PASSWORD...

Detailed explanation of Vue save automatic formatting line break

I searched for many ways to change it online but ...