导航与内容相互锚点定位--导航对应内容(内容滑动对应导航)

QQ20241211-15176


public/index.js文件

// 判断元素是否可见
export function elVisible(fn = () => null, config = {}) {
  // console.log(fn,'fn')
  // visible = true 元素不可见时也返回事件,否则我只需要元素可见时触发
  // threshold = 0 监听元素出现交叉就触发 / = 1 元素必须完全出现才触发 / = 0.5 元素出现一半就触发
  // rootMargin 扩张 向内或向外扩张交叉区域
  let { visible = false, ...rest } = config;
  let configs = { threshold: 0, rootMargin: "-50%", ...rest };
  const observe = entries => {
    for (const { isIntersecting = false, target = {} } of entries) {
      // created && created(target);
      if (visible) {
        fn && fn(target, isIntersecting)
      } else {
        isIntersecting && fn && fn(target, isIntersecting, subsidiary)
      };
    };
  };
  let subsidiary = new IntersectionObserver(observe, configs);
  const carryOut = refs => {
    let fn = item => subsidiary.observe(item.$el || item);
    let arrFn = () => refs && refs.map(item => subsidiary.observe(item.$el || item));
    switch (dataType(refs)) {
      case "HTMLImageElement": fn(refs); break; // 监听一个dom
      case "HTMLDivElement": fn(refs); break; // 监听一个dom
      case "Array": arrFn(refs); break; // 监听多个dom
      default: return false;
    };
  };
  // console.log(carryOut,'carryOut')
  return carryOut;
};
// 让元素到达指定位置
export function Scroll(dom = '', config = {}) {
  let configs = { behavior: "smooth", block: "start", ...config };
  dom && dom.scrollIntoView && dom.scrollIntoView(configs);
};

test.vue文件

<template>
  <div class="box">
   
    <ul>
      {{ active }}==active
      <li
        class="li"
        v-for="(item,index) in arr"
        @click="changeNav(item.id)"
        :class="active == item.id ? 'active' : ''"
        :key="index"
      >第{{item.name}}导航</li>
    </ul>
    <div>
      <div class="div" ref="SCROLL" v-for="(item,index) in arr" :key="index + 'a'">第{{item.name}}内容</div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: 0,
      arr: [
        { id: 0, name: 0 },
        { id: 1, name: 1 },
        { id: 2, name: 2 },
        { id: 3, name: 3 },
        { id: 4, name: 4 },
        { id: 5, name: 5 }
      ],
      subsidiary: this.$FN.elVisible(this.fn)
    };
  },
  mounted() {
    this.$nextTick(() => {
      window.addEventListener("scroll", this.findNav);
    });
  },
  methods: {
    findNav() {
      this.getRef();
    },
    getRef() {
      let refs = this.$refs.SCROLL;
      this.subsidiary(refs);
    },
    fn(res) {
      let index = res.innerText[1];
      console.log( res.innerText,' res.innerText',index,'index')
      this.active = index;
    },
    changeNav(i) {
      this.active = i;
      this.$FN.Scroll(this.$refs.SCROLL[i]);
    }
  }
};
</script>

<style lang="less" scoped>
.box {
  width: 50%;
  display: flex;
  margin: auto;
  justify-content: space-between;
  ul {
    position: fixed;
    left: 20%;
    top: 100px;
    .li {
      line-height: 30px;
      background-color: antiquewhite;
      margin-bottom: 20px;
      padding: 10px;
    }
  }
  .div {
    height: 500px;
    background-color: antiquewhite;
    margin-bottom: 20px;
    width: 500px;
    text-align: center;
    line-height: 500px;
  }
  .active {
    color: red;
  }
}
</style>

main.js文件 引入public/index.js

import * as FN from '@/public';
Vue.prototype.$FN = FN;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值