[TOC]
### vue 實現天貓國際商城導航效果交互
實現效果:

上拉時

*****
實現思路:
1. 頁面上拉時,頂部導航消失,搜索框逐漸滑動到頂部位置
2. 頂部導航產生1px陰影下邊框
2. 頁面滾動到頂部時,還原初始效果,邊框陰影消失
代碼演示:
Home.vue
~~~
<template>
<div class='home'>
<!-- 頂部導航 -->
<search-bar :posy="posy" ref='top'></search-bar>
<!-- 內容滾動區域 -->
<div ref="content" class='main-content' :style="{top:offsetTop+'px'}">
<p>1111111111111111</p>
<p>1111111111111111</p>
<p>1111111111111111</p>
<p>1111111111111111</p>
<p>1111111111111111</p>
<p>1111111111111111</p>
<p>沒有更多了...</p>
</div>
</div>
</template>
<script>
import SearchBar from 'components/home/SearchBar'
export default {
components: {
// 頂部搜索條組件
SearchBar
},
mounted() {
// Dom 加載完成,監聽局部內容滾動
this.$refs.content.addEventListener('scroll', this.handleScroll)
},
data() {
return {
// 判斷向上還是向下滾動 0頂部位置 >0 向下滾動
posy: 0,
// 內容初始距離頂部導航條的偏移量
offsetTop: 90
}
},
methods: {
// 監聽內容滾動事件
handleScroll() {
// 距離頂部偏移
let scrollTop = this.$refs.content.scrollTop
this.posy = scrollTop;
if (scrollTop > 0) {
// 上拉
this.offsetTop = 50
} else {
// 回到頂部
this.offsetTop = 90
}
}
}
}
</script>
<style lang="scss" scoped>
.home {
width: 100%;
height: 100%;
position: relative;
.main-content {
position: absolute;
bottom: 50px;
left: 0;
right: 0;
overflow: auto;
z-index: 500;
}
}
</style>
~~~
*****
SearchBar.vue
~~~
<template>
<div class='search-bar-wrapper' ref='tops' :class="{hideTitle: !titleVisible, hideShaow: !shaowVisible}">
<!-- 頂部導航中間文件 -->
<div class='search-bar-top' v-show="titleVisible">
<div class='text'>天貓國際進口超市</div>
</div>
<!-- 左邊按鈕 -->
<div class='icon-left' :class="{hideTitle: !titleVisible}">
<i class='icon iconfont'></i>
</div>
<!-- 右邊按鈕 -->
<div class='icon-right' :class="{hideTitle: !titleVisible}">
<i class='icon iconfont'></i>
</div>
<!-- 搜索框 -->
<div class='search-bar-input' :class="{hideTitle: !titleVisible}">
<!-- 占位左邊空白元素 -->
<div class='flex-left-empty' :class="{hideTitle: !titleVisible}"></div>
<!-- 中間搜索框 -->
<div class='input-inner'>
<label>搜索進口產品</label>
<div class='icon-search'></div>
</div>
<!-- 占位右邊空白元素 -->
<div class='flex-right-empty' :class="{hideTitle: !titleVisible}"></div>
</div>
</div>
</template>
<script>
export default {
props: {
// Home 父組件傳遞的值,用于判斷上拉還是下拉
posy: {
type: Number,
default: 0
}
},
data() {
return {
// 標題顯示控制
titleVisible:true,
// 邊框陰影顯示控制
shaowVisible: false
}
},
watch: {
// 監聽 Home 父組件傳遞的滾動值
posy(val) {
if (val > 0) {
// 向下滾動,隱藏標題 顯示陰影
this.showTitle()
this.showShaow()
} else if (val === 0) {
// 滾到頂部顯示標題 隱藏陰影
this.hideTitle()
this.hideShaow()
}
}
},
methods: {
// 顯示 && 隱藏 具體實現方法
showTitle() {
this.titleVisible = false;
},
hideTitle() {
this.titleVisible = true;
},
showShaow() {
this.shaowVisible = true;
},
hideShaow() {
this.shaowVisible = false;
}
}
}
</script>
<style lang="scss" scoped>
.search-bar-wrapper {
background: linear-gradient(rgb(255,199,113), rgb(226,142,27)); /* 標準的語法 */
position: relative;
top: 0;
left: 0;
right: 0;
height: 90px;
z-index:1200;
box-shadow: 0 2px 2px 0 rgba(238,238,238, .8);
&.hideTitle {
height: 50px;
}
&.hideShaow {
box-shadow: none;
}
}
.search-bar-top {
position: absolute;
width: 100%;
height: 40px;
line-height: 40px;
.text {
width:100%;
position: absolute;
text-align: center;
color: #fff;
font-size: 16px;
color: rgba(255,255,255,.8);
font-weight: 600;
}
}
.icon-left {
position: absolute;
width: 40px;
height: 40px;
line-height: 40px;
left: 0;
text-align: center;
transition: all .2s linear;
color: #fff;
&.hideTitle {
height: 50px;
line-height: 50px;
}
i {
font-size:20px;
}
}
.icon-right {
position: absolute;
right: 0;
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
transition: all .1s linear;
&.hideTitle {
height: 50px;
line-height: 50px;
}
color: #fff;
i {
font-size: 20px;
}
}
.search-bar-input {
display: flex;
position: absolute;
top: 40px;
width: 100%;
height: 50px;
box-sizing: border-box;
padding: 0 15px;
display: flex;
align-items: center;
justify-content: center;
transition: .1s all linear;
&.hideTitle {
top: 0
}
.flex-left-empty {
flex: 0 0;
width: 0;
transition: all .1s linear;
&.hideTitle {
width:34px;
flex: 0 0 34px;
}
}
.flex-right-empty{
flex: 0 0;
width: 0;
transition: all .1s linear;
&.hideTitle {
width:34px;
flex: 0 0 34px;
}
}
.input-inner {
flex:1;
width: 100%;
line-height: 30px;
text-align: center;
background-color: #fff;
border-radius: 2px;
color: #999;
font-size: 14px;
}
}
</style>
~~~