先说下 transition 为何可让你定义了 v-enter, v-enter-active 以后就能够触发transition.
实际过程按个人理解应该是这样:javascript
最开始的时候, 先给元素加上了 v-enter, v-enter-active 两个classcss
在下一帧的时候, 删掉 v-enter 这个class.html
在过渡结束以后, 再删掉 v-enter-active.java
对于2的解释:ide
这个帧的概念我刚开始没理解, 可是实际上能够理解成 '一段时间以后';this
你删掉 v-enter 会致使什么状况?
元素的样式会变化code
那么元素如今只有定义在本身身上的样式了
因此要变回去
而后发现有定义在 v-enter-active 上面的过渡效果
就会应用过渡效果orm
复盘一下过程:
刚开始的时候, 元素有本身的样式, 有 v-enter, v-enter-active 中定义的样式.
在一段时间间隔, 好比说 100ms 以后, 删掉了 v-enter, 意味着元素的样式变化。
变化, 而后发现存在 transition的定义, 就应用 transition,
这就造成了咱们最终看见的 transition效果.router
给个demo:htm
.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; }
类 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>
咱们要先让两个 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' } } }