@页面跳转
定义详情页路由
router/index.js
/* 动态路由 id为动态路由参数 组件实例中this.$route.params.id */
{
path: "/film/:id(\\d{4})",
name: "detail",
meta: { hideTabBar: true },
component: Detail,
},
点击电影条目跳转详情页
<ul v-else>
<!-- 点击跳转详情页,携带动态参数影片id -->
<FilmItem
v-for="film in films"
:key="film.filmId"
:item="film"
@click="$router.push(`/film/${film.filmId}`)">
</FilmItem>
</ul>
从详情页返回
<!-- 详情页导航条 -->
<div class="film-header show-film-header">
<!-- 点击返回 -->
<div
class="goBack"
@click="$router.back()">
<img
src="data:image/png;base64,iVBOR..."
alt="" />
</div>
<div
class="title"
ref="refTitle">
{{ film.name }}
</div>
</div>
@详情页导航条的动态透明
给标题元素添加ref
<!-- 详情页导航条 -->
<div class="film-header show-film-header">
<!-- 点击返回 -->
<div
class="goBack"
@click="$router.back()">
<img
src="data:image/png;base64,iVBOR..."
alt="" />
</div>
<!-- 给导航条中的标题元素添加ref,以便后续捕获这个元素 -->
<div
class="title"
ref="refTitle">
{{ film.name }}
</div>
</div>
在详情渲染完毕时逮到标题栏元素
/* 组件挂载时获取数据 */
mounted() {
/* 获取详情并渲染完毕后,逮到标题栏元素 */
getDetail(this.$route.params.id).then(res => {
console.log("res=", res);
// 渲染页面(数据驱动视图)
this.film = res;
/*
film对应的div元素在渲染完毕后会回调nextTick内的函数
此时根据ref获取title元素
*/
this.$nextTick(() => {
this.titleDom = this.$refs.refTitle;
});
});
/* 组件挂载完毕以后监听窗口的滚动事件 */
...
},
根据页面滚动距离调整标题栏样式
/* 组件挂载时获取数据 */
mounted() {
/* 获取详情并渲染完毕后,逮到标题栏元素 */
...
/* 组件挂载完毕以后监听窗口的滚动事件 */
const mainDom = document.querySelector("main");
mainDom.onscroll = e => {
// 如果标题栏尚未渲染完毕 就什么都不做
if (!this.titleDom) return;
// 实时main元素滚动的距离
console.log("scroll", mainDom.scrollTop);
/* 如果滚动距离超过50就白底黑字,否则透明 */
if (mainDom.scrollTop > 50) {
this.titleDom.style.backgroundColor = "white";
this.titleDom.style.color = "black";
} else {
this.titleDom.style.backgroundColor = "transparent";
this.titleDom.style.color = "transparent";
}
};
},
CSS动画的配合
.title {
padding: 0;
background-color: transparent;
color: transparent;
// 当样式发生改变时使用动画
transition: all 0.5s linear;
}
@详情页摘要的展开与折叠
点击toggle按钮触发展开/折叠
<!-- 点击toggle按钮时 动态切换hideSynopsis的真假 -->
<div
class="toggle"
@click="hideSynopsis = !hideSynopsis">
<!-- 隐藏时使用↓图标 -->
<i
v-if="hideSynopsis"
class="fa fa-angle-down"
style="font-size: 20px"></i>
<!-- 展开时使用↑图标 -->
<i
v-else
class="fa fa-angle-up"
style="font-size: 20px"></i>
</div>
摘要元素的高度随折展动态变化
<!-- 影片摘要 -->
<!--
// 我们让摘要元素的高度随着hideSynopsis的真假与与否动态变化
// 当hideSynopsis为true时 高度为60px 此时为折叠态
// 当hideSynopsis为false时 高度为动态计算的充分展开高度 此时为展开态
:style="{
height: hideSynopsis ? '60px' : `${Math.ceil(film.synopsis.length / 28) * 18}px`,
}"
-->
<div
id="synopsis"
class="film-synopsis grey-text"
:style="{
height: hideSynopsis ? '60px' : `${Math.ceil(film.synopsis.length / 28) * 18}px`,
}"
>
{{ film.synopsis }}
</div>
CSS动画的配合
// 摘要样式
#synopsis {
// 为高度做动画
transition: height 0.5s linear;
// 高度以外的文字隐藏
overflow: hidden;
}
@全局组件切换动画
为根组件的RouterView添加切换动画
<!-- 路由对应的目标组件的承载容器 -->
<main>
<!-- 无动画 -->
<!-- <RouterView /> -->
<!-- 添加组件的切换动画 -->
<router-view v-slot="{ Component }">
<!-- 动画过渡模式 先切走 再切入 -->
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</main>
定义这个切换动画slide-fade
/* 定义组件切换动画 */
/* 组件入场动画 + 组件离场动画 */
.slide-fade-enter-active,
.slide-fade-leave-active {
transition: all 0.5s ease;
}
/* 组件进入之前 + 组件离去以后的状态 */
.slide-fade-enter-from,
.slide-fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
注意事项
- 参与切换的组件必须有唯一的根元素,否则会报警报;
- 这个根元素最好是稳定的、不会反复diff和重新渲染的纯容器元素;
😈 点赞收藏加关注了吗就走?!
本项目源码 watch,follow,fork!!!
祝大家撸码愉快~