10

Vue 的 transition & 实现路由类 Tab 左右滑动切换的效果

先说下 transition 为什么可以让你定义了 v-enter, v-enter-active 之后就可以触发transition.
实际过程按我的理解应该是这样:

  1. 最开始的时候, 先给元素加上了 v-enter, v-enter-active 两个class

  2. 在下一帧的时候, 删掉 v-enter 这个class.

  3. 在过渡结束之后, 再删掉 v-enter-active.

对于2的解释:

  • 这个帧的概念我刚开始没理解, 但是实际上可以理解成 '一段时间之后';

  • 你删掉 v-enter 会导致什么情况?
    元素的样式会变化

那么元素现在只有定义在自己身上的样式了
所以要变回去
然后发现有定义在 v-enter-active 上面的过渡效果
就会应用过渡效果

复盘一下过程:
刚开始的时候, 元素有自己的样式, 有 v-enter, v-enter-active 中定义的样式.
在一段时间间隔, 比如说 100ms 之后, 删掉了 v-enter, 意味着元素的样式变化。
变化, 然后发现存在 transition的定义, 就应用 transition,
这就形成了我们最终看见的 transition效果.

给个demo:

.box {
  height: 100px;
  width: 100px;
  background: red;
}
.v-enter {
  height: 200px;
  width: 200px;
}
.v-enter-active {
  transition: all 2s;
}
<div class="box"></div>
    var box = document.querySelector('.box');

    box.classList.add('v-enter');
    box.classList.add('v-enter-active');

    setTimeout(function(){
      box.classList.remove('v-enter');
    }, 100);

再说下元素从显示到消失的时候
我们知道, 如果过渡效果的终点是 display:none, 那么过渡效果是不会生效的, 所以我觉得
v-if, v-show 对过渡效果都是有所控制的, 它们应该是在 transitionEnd 的时候才去应用
display:none; 或者移除元素.

但是元素离开和元素进入还有点不一样:

你的元素在离开的时候, 元素是已经存在于页面上, 是你已经能看见的
然后你给它加上 v-leave, v-leave-active
按照之前的逻辑, v-leave 有样式, v-leave-active 里面有 transition
元素的样式变更-> 触发 transition, 所以加上就直接触发 transition, 还等个什么下一帧。
既然加上就触发 transition, 那你要 v-leave 干嘛, 为什么不直接把
样式和 transition 都加在 v-leave-active 上面呢。

暂时没有发现 v-leave 的作用, 感觉不是必须的, 就是对称一样. 或者为了样式分离.

transition 过渡效果的样式实际上是有通用规律的:

.v-enter {
  opacity:0;
}
.v-enter-active {
  transition: all 1s;
}
.v-leave-active {
  opacity: 0;
  transition: all 1s;
}

更常见的写法是这样:

.v-enter {
  opacity:0;
}
.v-enter-active, .v-leave-active {
  transition: all 1s;
}
.v-leave-active {
  opacity: 0;
}

关于 transition 的一个应用: 实现路由 类 Tab 左右滑动切换的效果.

类 Tab 左右滑动切换的效果,就是这样:

      [viewport]
      [router1]   [router2]

router1,2 左右拉来拉去, 就是左右滑动切换的效果.

那我们的问题就可以变成:
把当前的路由 router1, 和下一个路由 router2, 并列放到一行,
用户点击跳转的的时候, 同时滑动 router1,router2

但是直觉都告诉我们, 路由压根就不是这么排列的, 当你在 router1 的时候, router2 根本就不存在啊.
不存在何来并排.

但是想想我们之前说的, 加上 transition 之后, 元素消失会怎么办?
元素先应用 transition, transitionEnd 的时候, 元素才会消失.

这个的意思就是说:
跳转的一瞬间, 当前的 route1 会开始应用 transition, 还没有消失于页面之上.
然后下一个 router2 已经创建, 已经存在于页面之上.
此时, 两个 router 都是存在的.

这就是时机.
先说下我们的 DOM 结构

    <transition>
      <router-view></router-view>
    <transition>
  1. 我们要先让两个 router 并排, how ?
    定位啊:

.router-view {
  position: absolute;
  top: 0;
  left: 0;
}

按理说两个 router 都是 left:0, top:0, 应该是重叠的是不是?
对.
所以我们对要进入的那个 router 做下 translate
比如当前的是 router1, 点击要向前跳转到 router2, 那么对 router2 translateX(100%);
这样两个 router 是不是就并排了.

并排之后就是动起来, 也就是应用滑动效果.
两个组件都是被 transition 包裹起来所以只要定义相应的class就可以了.

先说向前进:
假设 transition 的 name = 'slide-forward'

对于 router1:
start: 是当前的位置
end: 是当前位置的 translateX(-100%), 也就是当前位置的左边.

对于 router2:
start: 是相对于当前位置的 translateX(100%);
end: 是当前位置.

// router1
.slide-forward-leave-active {
  transition: all 1s;
  transform: translate(-100%);
}
// router2
.v-enter {
  transform: translateX(100%);
}
.v-enter-active {
  transition: all 1s;
}

再说后退, 设 transition 的 name = 'slide-back';
class就是:

// router1
.v-enter {
  transfrom: translateX(-100%);
}
// router2
.v-enter-active {
  transition: all 1s;
}
.v-leave-active {
  transfrom: translateX(100%);
  transition: all 1s;
}

整理一下, 得到的两个 transition,

.slide-forward-enter {
  transform: translate(100%);
}
.slide-forward-enter-active {
  transition: all 1s ease-in-out;
}
.slide-forward-leave-active {
  transform: translate(-100%);
  transition: all  1s ease-in-out;
}


.slide-back-enter {
  transform: translate(-100%);
}
.slide-back-enter-active {
  transition: all 1s ease-in-out;
}
.slide-back-leave-active {
  transform: translate(100%);
  transition: all  1s ease-in-out;
}

现在再讨论一下: 我们该如何判断当前是前进还是后退呢?
下面这样:

  watch: {  
    '$route' (to, from) {  
      if (!this.map[to.path]) {
        this.map[to.path] = +new Date() + 1;
      }
      if (!this.map[from.path]) {
        this.map[from.path] = +new Date();
      }

      if (this.map[to.path] > this.map[from.path]) {
        this.transitionName = 'slide-forward';
      } else {
        this.transitionName = 'slide-back'
      } 
    }  
  }

云水摇啊摇
362 声望15 粉丝

不信人间有白头.