转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
1 需求
详情页的头部组件,有两个部分组成:
- 当进入详情页时,左上角有一个“返回”按钮;
- 当向下滚动查看内容时,逐渐出现一个顶部的导航栏,导航栏左边也有一个“返回”按钮。
当点击任意“返回”按钮后,都能回到首页:
2 Header 布局
🔗前置知识:
需求分析:整个 Header 由两个部分组成,一个圆形返回按钮和一个导航栏。其中圆形返回按钮,我们可以采用绝对定位;导航栏则需要在页面滚动时,依然在窗口顶部保持不动,所以采用固定定位。
1️⃣在 detail 下的 components 中新建一个 Header.vue:
<template>
<div> <!-- 1️⃣-②:最外层 div 中有两个 div,一个类名为 header-abs,一个为 header-fixed; -->
<div class="header-abs"> <!-- 1️⃣-③:.header-abs 为绝对定位的返回按钮,里边有一个返回
图标,类名为 header-abs-back; -->
<span class="iconfont header-abs-back"></span>
</div>
<div class="header-fixed"></div>
</div>
</template>
<script>
export default {
name: 'DetailHeader' // 1️⃣-①:组件命名为 DetailHeader;
}
</script>
<style lang="stylus" scoped>
.header-abs /*
1️⃣-④:.header-abs 绝对定位,上、左距离为 0.2rem,宽、高为 0.8rem,
border-radius 为 0.4rem(做一个圆形),line-height 为 0.8rem,内容居中,
背景色为 0.8 透明度的黑色; */
position: absolute
top: .2rem
left: .2rem
width: .8rem
height: .8rem
line-height: .8rem
text-align: center
border-radius: .4rem
background: rgba(0, 0, 0, .8)
.header-abs-back /* 1️⃣-⑤:返回图标颜色为白色,大小为 0.56rem; */
color: #fff
font-size: .56rem
</style>
1️⃣-⑥:打开 detail 下的 Detail.vue 使用 Header 组件;
<template>
<div>
<detail-banner></detail-banner>
<detail-header></detail-header> <!--1️⃣-⑨:使用 Header 组件;-->
<div class="content"></div> <!-- ❗️在详情页中添加一个 div,类名为 content,设置它的高
为 20rem 使详情页能够滚动(后边我们再添加别的内容撑开); -->
</div>
</template>
<script>
import DetailBanner from './components/Banner'
import DetailHeader from './components/Header' // 1️⃣-⑦:引入 Header.vue;
export default {
name: 'Detail',
components: {
DetailBanner,
DetailHeader // 1️⃣-⑧:注册 Header 组件;
}
}
</script>
<style lang="stylus" scoped>
.content /* ❗️设置 .content 高为 20rem 撑开内容。 */
height: 20rem
</style>
保存后,返回页面查看,Header 组件正确显示,第一部分的“返回”按钮,布局完成:
1️⃣-⑩:返回 Header.vue,给返回按钮添加 router-link;
<template>
<div>
<!-- 1️⃣-⑪:使用 router-link 标签替换 .header-abs的 div 标签,tag 设为 div,
添加 to 属性跳转至首页 /(❗️这种 router-link 的用法,在详情页开发的“动态路由”已使用过)。 -->
<router-link tag="div" to="/" class="header-abs">
<span class="iconfont header-abs-back"></span>
</router-link>
<div class="header-fixed"></div>
</div>
</template>
<script>
export default {
name: 'DetailHeader'
}
</script>
<style lang="stylus" scoped>
.header-abs
position: absolute
top: .2rem
left: .2rem
width: .8rem
height: .8rem
line-height: .8rem
text-align: center
border-radius: .4rem
background: rgba(0, 0, 0, .8)
.header-abs-back
color: #fff
font-size: .56rem
</style>
保存后,返回页面查看。页面显示正常,点击“返回”按钮可跳转至首页,详情页可滚动:
2️⃣详情页导航栏的布局与城市选择页导航栏相近,我们可以复制这部分的代码粘贴过来进行调整:
<template>
<div>
<router-link tag="div" to="/" class="header-abs">
<span class="iconfont header-abs-back"></span>
</router-link>
<div class="header-fixed"> <!-- 2️⃣-①:.heider 改为 .header-fixed; -->
<router-link to="/">
<!-- 2️⃣-②:图标类名改为 header-fixed-back; -->
<span class="iconfont header-fixed-back"></span>
</router-link>
景点详情 <!-- 2️⃣-③:文字内容改为景点详情; -->
</div>
</div>
</template>
<script>
export default {
name: 'DetailHeader'
}
</script>
<style lang="stylus" scoped>
/* 2️⃣-④:引入 varibles.styl; */
@import '~styles/varibles.styl'
.header-abs
position: absolute
top: .2rem
left: .2rem
width: .8rem
height: .8rem
line-height: .8rem
text-align: center
border-radius: .4rem
background: rgba(0, 0, 0, .8)
.header-abs-back
color: #fff
font-size: .56rem
.header-fixed /* 2️⃣-⑤:将 .header 改为 .header-fixed,position 改为固定定位 fixed,
top、left、right 为 0,添加 z-index 值为 2; */
position: fixed
top: 0
left: 0
right: 0
height: $headerHeight
z-index: 2
line-height: $headerHeight
color: #fff
text-align: center
font-size: .32rem
background: $bgColor
.header-fixed-back
position: absolute
top: 0
left: 0
width: .64rem
text-align: center
font-size: .56rem
color: #fff
</style>
保存后,返回页面查看。点击导航栏的“返回”图标可回到首页;在详情页向下滚动时,导航栏固定显示在页面顶部:
3 Header 逻辑
🔗前置知识:
《JavaScript 基础——浏览器提供的对象:② DOM》
《JavaScript 基础——JS 事件:① 事件流和 DOM2 事件处理程序》
《JavaScript 基础——JS 事件:③ 常见事件使用》
《Vue 入门——⑥ Class 与 Style 绑定》
需求分析:一般情况下,显示单独的“返回”按钮,导航栏在隐藏状态;当滚动到一定距离时,导航栏才出现,“返回”按钮隐藏。所以,可以通过改变一个变量来控制它们状态切换。而导航栏的渐隐渐现效果,可以使用动态绑定样式来实现,在滚动时去动态改变它的透明度 opacity。
3️⃣打开 detail 下 components 中的 Header.vue:
<template>
<div>
<router-link
tag="div"
to="/"
class="header-abs"
v-show="showAbs"
> <!-- 3️⃣-②:.header-abs 上添加 v-show 指令,值为 showAbs 变量
(即,默认显示返回图标); -->
<span class="iconfont header-abs-back"></span>
</router-link>
<div
class="header-fixed"
v-show="!showAbs"
:style="opacityStyle"
> <!-- 3️⃣-③:.header-fixed 添加 v-show,值为 !showAbs(即,与 showAbs 值相反时显示
导航栏);
3️⃣-⑨:动态绑定样式为 opacityStyle; -->
<router-link to="/">
<span class="iconfont header-fixed-back"></span>
</router-link>
景点详情
</div>
</div>
</template>
<script>
export default {
name: 'DetailHeader',
data () {
return {
showAbs: true, // 3️⃣-①:在 data 中定义一个变量 showAbs,默认为 true;
opacityStyle: { // 3️⃣-⑧:定义一个样式变量 opacityStyle,默认 opacity 值为 0;
opacity: 0
}
}
},
methods: {
handleScroll () { // 3️⃣-⑤:在 methods 中定义 handleScroll 方法;
const top = document.documentElement.scrollTop /*
3️⃣-⑥:定义一个变量 top,用来存储
滚动条滚动的位置;
*/
if (top > 50) { /*
3️⃣-⑦:如果 top 大于 50 时,showAbs 为 false(即,显示导航栏),
否则 showAbs 为 true;
*/
let opacity = top / 150 /*
3️⃣-⑩:定义一个变量 opacity,它的值为 top 除以 150
(即,我们让导航栏透明度在滚动距离 50~150 时进行变化);
*/
opacity = opacity > 1 ? 1 : opacity /*
3️⃣-⑪:opacity 的值是否大于 1,如果是,就让它
等于 1,如果不是,则等于它本身;
*/
this.opacityStyle = {opacity} // 3️⃣-⑫:把 opacity 赋值给 opacityStyle;
this.showAbs = false
} else {
this.showAbs = true
}
}
},
activated () { /*
3️⃣-④:在 activated 生命周期函数中,全局绑定 scroll 事件,事件触发后
执行 handleScroll 方法;
*/
window.addEventListener('scroll', this.handleScroll)
},
deactivated () { /*
3️⃣-⑬:最后,不能忘记对全局事件解绑。我们在 deactivated 生命周期函数中解绑
scroll 事件
(❗️使用 keep-alive 时与 activated 对应的生命周期函数,它在我们从当前组件
切换到另一个组件时被调用)。
*/
window.removeEventListener('scroll', this.handleScroll)
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.header-abs
position: absolute
top: .2rem
left: .2rem
width: .8rem
height: .8rem
line-height: .8rem
text-align: center
border-radius: .4rem
background: rgba(0, 0, 0, .8)
.header-abs-back
color: #fff
font-size: .56rem
.header-fixed
position: fixed
top: 0
left: 0
right: 0
z-index: 2
height: $headerHeight
line-height: $headerHeight
color: #fff
text-align: center
font-size: .32rem
background: $bgColor
.header-fixed-back
position: absolute
top: 0
left: 0
width: .64rem
text-align: center
font-size: .56rem
color: #fff
</style>
保存后,返回页面查看。页面显示正常,控制台无报错。当在详情页上下滚动时,导航栏也有了渐隐渐现的效果:
以上,我们完成了详情页的 Header 组件。
祝好,qdywxs ♥ you!