Vue实现StickyTop效果

最近的wap项目开发中有这么一个需求:

  1. 初始情况下页面布局如下图所示:
Vue实现StickyTop效果_第1张图片
  1. 当页面滚动距离大于header时,switch-bar将固定在顶部
Vue实现StickyTop效果_第2张图片
  1. 3个列表可以来回切换

  2. 切换列表时保持switch-bar状态,即当switch-bar固定在顶部时,切换列表后switch-bar仍然固定在顶部,当switch-bar不固定在顶部时,切换列表后页面回跳到顶部。

  3. 3个列表数据均为异步获取

最后的实现效果(简单示例)如下:

下面我们来看下如果实现这个stickyTop效果。

首先说一下这个示例使用的技术栈:Vue + Vue-router + lodash + axios

  使用`Vue-router`: 实现嵌套路由
  使用`lodash`的`throttle`: 节流监听滚动事件,降低性能消耗
  使用`axios`: 发起异步请求

实现思路:

  1. 页面使用流式布局,整个页面可分为4个组件(Home, Products, Orders, Docs
const Home = {
  template: `
    
header
产品 订单 文档
` } const Products = { template: `
  • {{ item.name }}
` } const Orders = { template: `
  • {{ item.name }}
` } const Docs = { template: `
  • {{ item.name }}
` }
  1. 使用嵌套路由
const routes = [{
  path: '/',
  component: Home,
  children: [{
    path: '',
    component: Products
  }, {
    path: 'products',
    component: Products
  }, {
    path: 'orders',
    component: Orders
  }, {
    path: 'docs',
    component: Docs
  }]
}]
  1. 节流监听window滚动事件,当页面滚动高度 >= header高度时,设置switch-barposition属性为fixd,反之取消(实际通过一个变量isFix来控制样式)。
.home.fix .switch-bar {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 10;
}
...
...
...
// 判断是否吸顶效果 if (this.scrollTop >= this.headerHeight) { this.isFix = true } else { this.isFix = false }

做完以上3点其实大部分工作就完成了,这时的运行效果如下:

有两个问题:

  1. 切换列表时并没有保持switch-bar状态,因为示例中Products列表数比较少,导致页面的高度 <= 屏幕的高度,没有滚动条,所以当switch-bar固定在顶部并且从订单或文档切换过来时,由于document.body.scrollTop = 0,页面将跳到顶部
  2. switch-bar固定在顶部时,切换列表,列表数据第一条并没有显示到正确的位置。

为了解决第一个问题,给content加了两个计算属性:contentMinHeightcontentMarginTop,动态计算contentheightmargin-top

computed: { contentMinHeight() { const windowHeight = document.documentElement.clientHeight return this.isFix ? windowHeight - this.switchBarHeight : windowHeight - this.headerHeight - this.switchBarHeight }, contentMarginTop() { return this.isFix ? this.switchBarHeight : 0 } }

为了解决第二个问题,watch $route的变化,手动将滚动条滚动至正确的位置

watch: {
    '$route'(to, from) {
        this.$nextTick(() => {
           if (this.isFix) {
              window.scrollTo(0, 0)  // 兼容chrome
              window.scrollTo(0, this.headerHeight)
           } else {
              window.scrollTo(0, 0)
            }
        })
    }
}

到这里,整个示例就完成啦~

想要查看完整代码可前往:https://github.com/hysunny/Vue-dev-note/blob/master/vue-stickyTop/index.html

或查看在线示例:https://jsfiddle.net/hysunny/yvzyp4kk/2/

你可能感兴趣的:(Vue实现StickyTop效果)