阅读 456

Vue 列表上下过渡效果

前言

最近有个需求,一个列表上下移动要有简单过渡效果,在网上找了找没找到,可能是我搜的关键词不对?

试了试 Vue 的transition-group,也没有达到预期的效果,然后就花了点时间做了一个操作Demo。

项目源码

在线演示:jsrun.net/hdyKp

Demo源码:github.com/thinkupp/vu…

最终效果

某列的数据由 X 位置上升到 Y 位置的过渡效果

技术点

  • visibility: hidden
  • v-for key
  • 这么简单的实现哪有什么技术点,哈哈哈

实现方式

这个过渡效果一共由三部分组成:

  • Y行位置插入X行位置的数据,添加一个高度展开效果,并使该行的数据不可见
  • X行数据不可见, 并添加一个高度收起效果
  • 原地克隆X行的DOM, 设置为固定定位fixedtop取X行距离body的位置(offsetTop), 并做一个向上移动效果到Y行位置

这里仅仅依靠`offsetTop`并不准确,具体见文章后面的内容.

来看一个放慢版的效果,加了个边框并且没有设置visibility属性,看的会更明了:

简单说一下。

第一部分描述一个让目标位置底下所有行有一个向下移动的过程。

第二部分描述那个移动的行消失的过程。

第三部分描述一个移动的过程。

为了不污染数据渲染出来的视图,除了固定定位的那个盒子是直接操作DOM,之外的两个效果是通过操作数据+类名实现的。

遇到的问题

  • 图片闪烁问题

原因:由于 v-for 的时候给每行的keyindex,数据源发生变化后会导致受影响的元素的index也发生改变。

解决:将key的值由index更换为item(唯一值, 在这里item指的是图片url) 。

  • 频繁更新数据问题

当位置频繁改变的时候要清除上一次的动画遗留元素,不然元素会发生各种错乱,这个很容易想的到,错误演示就不录了,看一下完成的效果。

  • Duplicate keys detected

原因:第一部分插入X行数据造成,因为两条相同的数据重复的item会造成重复的key

解决:在进行第一部分的时候将原来那一行的key改为其它值。

<li :key="closeIndex === index ? Date.now() : item"></li>
复制代码

我用的时间戳,其实理论上来讲只要能保持唯一写什么都可以,反正这一行数据将在动画结束后从数据中删除。

  • 距离Body距离计算

仅仅依靠offsetTop计算位置是不准确的,当页面发生滚动后元素与Body的实际距离就不是offsetTop的值了。应该用offsetTop减去scrollTop,这样才是元素当前与Body的实际距离。

  /*
  * 计算盒子当前距离body的距离
  * @param {HTMLElement} ele 要计算位置的盒子
  * @returns {number} 当前位置距离body的距离
  * */
  calcTop(ele) {
    let offsetTop = ele.offsetTop;
    let offsetParent = ele.offsetParent;

    while (offsetParent) {
      offsetTop += offsetParent.offsetTop;
      offsetParent = offsetParent.offsetParent;
    }

    return offsetTop - (document.body.scrollTop || document.documentElement.scrollTop)
  }
复制代码

获取 scrollTop 的方式根据项目不同也不同,并不是所有的情况下都可以通过 document.body.scrollTop || document.documentElement.scrollTop 获取到正确的内容,具体区分项目

描述有点乱,希望能给也遇到此问题的朋友提供一个思路,有误的地方麻烦大家及时指正。

关注下面的标签,发现更多相似文章
评论