多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] ### vue 实现天猫国际商城导航效果交互 实现效果: ![](https://box.kancloud.cn/91a141e72f7608a9421df518360633d4_375x396.png) 上拉时 ![](https://box.kancloud.cn/58a47bd162ab0a6f083f9db3a24710f7_377x305.png) ***** 实现思路: 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'>&#xe604;</i> </div> <!-- 右边按钮 --> <div class='icon-right' :class="{hideTitle: !titleVisible}"> <i class='icon iconfont'>&#xe635;</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> ~~~