实现带有动画效果的路由组件切换一般是通过 router-view 开启 v-slot 并结合 transition 组件实现
<router-view v-slot="{ Component }">
<transition name="fade">
<component :is="Component" />
</transition>
</router-view>
Vue文档链接:https://router.vuejs.org/zh/guide/advanced/transitions.html
但是这种方式只支持 路由的整体切换,无法达到我们想要的从 list 的卡片中心出现/消息的过渡效果,所以我们只得寻求他法。
这里其实没太懂为什么就不可以……希望老师解答一下
这里我们采用了手动向当前浏览器会话的历史堆栈中添加一个状态(state)的方式。利用 history.pushState() 函数 (https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState) 插入一个路由(修改浏览器的URL),但是并不进行页面跳转,这点很重要,下面会说如何验证这一点。
也就是说,在 list.vue 组件中点击一个卡片,完成了两件事
pins/${item.id}
),相当于在 浏览器会话的历史堆栈中 添加一个 /pins/:id 的页面(因为 list.vue 是首页 / 的子组件,相对 URL地址拼接得到 /pins/:id )这样,就可以利用
pins/${item.id}
)来“进入”页面(实际上是显示隐藏的 pins.vue 组件 + 插入路由),而通过
来“离开”页面(实际上是隐藏 pins.vue 组件 + 路由回退)
这就是为什么 要给浏览器的回退按钮事件 “popstate” 增加一个 isPinsVueVisable.value = false; 靠 “popstate” 只能完成 路由出栈回退。
这里不确定我说的对不对
但是这样是有问题的,我们此时插入的路由 /pins/:id 页面没有设置对应的组件作为页面,一旦刷新,此时就会页面空白。所以我们需要在 router 中注册一个组件用于对应路由 /pins/:id
@/views/pins/index.vue 便由此诞生,它就是一个div套着 pins.vue 的简单组件,用div补足一些在 list.vue 套着 pins.vue 时会有的样式。
说到底,第一次点击卡片的时候,弹出的组件由于是全屏,形成了页面切换的错觉,实际上此时我们打开控制台,一直都还在 list.vue,只不过路由确实改了。而只要在 img详情页 点击一次刷新,此时就会变成了 @/views/pins/index.vue 组件,这里和刷新之前是两个组件,证据就是改变一下 @/views/pins/index.vue 中用于套着 pins.vue 的 div 的样式(比如说背景色),可以看到刷新前后背景色是不一样的。
这也解释了为什么@/views/pins/index.vue 在刷新的时候,需要立刻拿到当前所在的URL中的id参数,传给自己包裹的 pins.vue ,这样才导致信息不会丢失。
<pins-vue :routerId="$route.params.id"/>