文章目录

    • 学习链接
    • 通过scrollHeight实现
    • 通过js获取auto时的高度去实现(效果不好)
      • 优化
    • 通过grid实现

学习链接

vue项目列表折叠面板动画效果实现
element-ui之el-collapse-transition(折叠展开动画)源码解析学习

通过scrollHeight实现


以下代码注意两点

  • trainsition是需要有两个值,才能产生过渡动画的,所以一开始就需要获取到box1的高度(通过scrollHeight去获取它的高度)
  • box1收缩,其实就是把它的height改为0,超出部分隐藏,这样子元素就隐藏了(但是注意,这个时候,仍然可以通过scrollHeight获取到box1的实际高度,尽管它的style的height已经是0了)
<template><div><el-button plain type="danger" @click="toggleDiv" size="mini" style="margin-bottom: 10px;" >toggleDiv</el-button><div class="box1" ref="box1" id="box1"><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div></div></div></template><script>export default {name: 'Collapse',components: {},data() {return {isCollapse: false,}},mounted() {// 刚开始的时候, 就必须先获取到这个元素的高度(transition需要有两个数值才能产生过渡), 它必须刚开始就是可见的(不能display:none)console.log('mounted', this.$refs['box1'].scrollHeight);this.$refs['box1'].style.height = this.$refs['box1'].scrollHeight + 'px'},methods: {toggleDiv() {this.isCollapse = !this.isCollapseif(this.isCollapse) {this.$refs['box1'].style.height = 0} else {// 这个时候,box1已经收缩了,但是需要展开,那就必须获取到它的高度(此时它的style的height为0)console.log( this.$refs['box1'].scrollHeight);this.$refs['box1'].style.height = this.$refs['box1'].scrollHeight + 'px'}}}}</script><style>.box1 {width: 200px;/* height: 200px; */background-color: #bfa;transition: height 0.28s;overflow: hidden;}.box1 .box1-item {height: 20px;border: 1px solid red;}</style>

通过js获取auto时的高度去实现(效果不好)


虽然,实现效果并不怎么好,但是比较巧妙,它通过js设置height为auto,然后就可以获取元素的自然高度。这种获取高度的方式可以借鉴下

<template><div><el-button plain type="danger" @click="toggleDiv" size="mini" style="margin-bottom: 10px;" >toggleDiv</el-button><div class="box1" ref="box1" id="box1"><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div></div></div></template><script>export default {name: 'Collapse',components: {},data() {return {isCollapse: false,}},mounted() {console.log(this.$refs['box1'].scrollHeight); // 110this.$refs['box1'].style.height = 'auto'this.$refs['box1'].style.height = window.getComputedStyle(this.$refs['box1']).height},methods: {toggleDiv() {this.isCollapse = !this.isCollapseif(this.isCollapse) {this.$refs['box1'].style.height = 0} else {this.$refs['box1'].style.height = 'auto'let height = window.getComputedStyle(this.$refs['box1']).height// 这里修改的太快,transition都还没开始做动画this.$refs['box1'].style.height = 0this.$refs['box1'].style.height = height}}}}</script><style>.box1 {width: 200px;background-color: #bfa;overflow: hidden;}.box1 .box1-item {height: 20px;border: 1px solid red;}</style>

优化

要使用setTimeout,才能在展开的时候,有过渡效果,不然两个修改高度的js在一起,它是不会有过渡的,可能跟浏览器的渲染有关系

<template><div><el-button plain type="danger" @click="toggleDiv" size="mini" style="margin-bottom: 10px;" >toggleDiv</el-button><div class="box1" ref="box1" id="box1"><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div><div class="box1-item"></div></div></div></template><script>export default {name: 'Collapse',components: {},data() {return {isCollapse: false,styleObj: {}}},mounted() {console.log(this.$refs['box1'].scrollHeight); // 110this.$refs['box1'].style.height = 'auto'this.$refs['box1'].style.height = window.getComputedStyle(this.$refs['box1']).height},methods: {toggleDiv() {this.isCollapse = !this.isCollapseif(this.isCollapse) {this.$refs['box1'].style.height = 0} else {this.$refs['box1'].style.height = 'auto'let height = window.getComputedStyle(this.$refs['box1']).heightconsole.log(height,1);this.$refs['box1'].style.height = 0setTimeout(()=> {this.$refs['box1'].style.height = height})}}}}</script><style>.box1 {width: 200px;background-color: #bfa;overflow: hidden;transition: all 0.5s;}.box1 .box1-item {height: 20px;border: 1px solid red;}</style>

通过grid实现


注意下面的grid网格布局是加给外面的这个容器,外面这个容器从0fr到1fr会产生动画。overflow:hidden是加给里面的这个div。这样就能实现从0->auto的高度变化过渡效果。

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body {margin: 0;}.quick-example {margin: 1rem;padding: 1rem;background: hsl(200, 50%, 50% );border-radius: 0.5rem;display: grid;grid-template-rows: 0fr;transition: grid-template-rows 0.5s;}.quick-example>div {overflow: hidden;}.quick-example:hover {grid-template-rows: 1fr;}</style></head><body><div class="quick-example"><div>this is amazing!this is amazing!this is amazing!this is amazing!this is amazing!this is amazing!this is amazing!this is amazing!</div></div><div>[一段很长的文字Lorem1000]</div></body></html>