1、使用Vant UI中的组件实现

 Vant - Mobile UI Components built on Vue

2、自定义组件实现:

定义stickySlot.vue

<template>
  <div class="sticky" :style="getPosition">
    <div class="sticky-warp">
      <slot></slot>
    </div>
  </div>
</template>
<script type="text/babel">
export default {
  data() {
    return {};
  },
  computed: {
    getPosition() {
      var position = this.cssSupport("position", "sticky")
        ? "sticky"
        : "relative";
      return "position:" + position;
    },
  },
  mounted() {
    this.init();
  },
  deactivated() {
    if (this.cssSupport("position", "sticky")) {
      return;
    }
    /*复位*/
    var elWarp = this.$el.querySelector(".sticky-warp");
    elWarp.position = "absolute";
  },
  methods: {
    init() {
      if (this.cssSupport("position", "sticky")) {
        return;
      }
      var el = this.$el,
        target = this.$el.parentNode,
        elWarp = this.$el.querySelector(".sticky-warp"),
        top = this.getNumberValue(
          document.defaultView.getComputedStyle(el).top
        );
      this.addScrollListen(target, () => {
        if (el.getBoundingClientRect().top <= top) {
          elWarp.style.position = "fixed";
        }
        if (
          el.getBoundingClientRect().top >= 0 &&
          elWarp.style.position != "absolute"
        ) {
          elWarp.style.position = "absolute";
        }
      });
    },
    cssSupport(attr, value) {
      var element = document.createElement("div");
      if (attr in element.style) {
        element.style[attr] = value;
        return element.style[attr] === value;
      } else {
        return false;
      }
    },
    getNumberValue(pxValue) {
      var value = String(pxValue).match(/^\\-?\+?[0-9]+/g);
      return value ? Number(value) : undefined;
    },
    addScrollListen(target, cb) {
      target.addEventListener("y-scroll", (event) => {
        cb && cb(event);
      });
    },
  },
};
</script>

<style>
.sticky {
  width: 100%;
}
.sticky .sticky-warp {
  width: 100%;
  background: inherit;
  will-change: change;
  height: inherit;
  top: inherit;
}
</style>

 使用组件处:

<template>
  <div>
    <ul>
      <li v-for="(item, index) in headerData" :key="index">{{ item }}</li>
    </ul>
    <!-- 
      这里需要给组件添加一个class,用于控制固定的位置,看css注释部分
     -->
    <sticky-slot class="stickyTop">
      <div class="tab">
        假装这是一个tab栏,当页面滚动的时候要固定在顶部
      </div>
    </sticky-slot>
    <ul>
      <li v-for="(item, index) in footerData" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
import stickySlot from "./stickySlot.vue"; // 需改为对应的组件存放的路径
export default {
  components: {
    stickySlot,
  },
  data() {
    return {
      headerData: [],
      footerData: [],
    };
  },
  created() {
    // 使用假数据撑满屏幕
    for (let i = 0; i < 20; i++) {
      this.headerData.push("第" + i + "条数据");
    }
    for (let i = 20; i < 80; i++) {
      this.footerData.push("第" + i + "条数据");
    }
  },
};
</script>

<style scoped>
/* 
    通过设置top的值,控制需要固定在什么位置,0是顶部,值为number(px)
  */
.stickyTop {
  top: 0;
  z-index: 10;
}
.tab {
  height: 30px;
  line-height: 30px;
  background-color: greenyellow;
}
</style>

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐