Nuxt.js中自己实现锚点功能,真香😜

692 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

NuxtJS是一个基于Vue开发的一款支持服务器渲染(SSR模式)的开源框架,它利用Node.js服务器将基于Vue的组件渲染成HTML并传输到客户端,与传统的SPA不同的是,使用SSR技术将带来巨大的SEO提升,这也是我当初选择该框架原因。

1.背景

最近运营小姐姐在后台配置富文本的时候配置了一篇包含锚点功能的文章,主要是以目录的形式提升用户阅读体验。但是发布之后点击锚点链接,Vue尽然跳转到一个404页面, 锚点功能失效。运营小姐姐很不开心😟,我当时表情:

看了一下问题以后,原来是传统的锚点定位跟我们的Vue Router中的路由设置冲突了,都是通过#XXX的形式实现,所以需要我们自己实现一个锚点功能,哎,还是自己手撸一码😂😂😂.

2.代码实现

基本思路分为三步走:

  1. 页面加载完成触发Js脚本,获取文章中锚点DOM元素,例如:
<a href="#menu1" target="_self">1.Anchor1</a>
  1. 将获取到锚点DOM属性处理成href="javascript:void(0)",将之前的锚点自定义属性data-href="#menu1"(该值对应锚点的id),target属性设置为_self(这里需要注意如果后台富文本添加的时候设置了target=_blank,需要将target设置为_self,或者删掉该DOM属性,否则会跳转),最终处理结果如下:
<a href="javascript:void(0)" data-href="#menu1" target="_self">1.Anchor1</a>
  1. 给每个锚点DOM绑定click事件,点击的时候获取DOM上我们自定的属性data-href,并将前面的#号去掉,获取对应id锚点的滚动像素高度,控制浏览器滚动条滚动到对应位置。

代码static/js/articel.js

window.onload=function(){
  article.init()
}
const article = (() => {
  const controller = {
      linkToFun: (domArr) => {
        if (domArr.length) {
            Object.keys(domArr).forEach(function(key){
              if (domArr[key].getAttribute("href") != null && domArr[key].getAttribute("href").indexOf("#") === 0) {
                let href = domArr[key].getAttribute("href");
                domArr[key].setAttribute("data-href",href)
                domArr[key].setAttribute("href","javascript:void(0)")
                domArr[key].setAttribute("target","_self")
                domArr[key].onclick  = function (e) {
                  if (domArr[key].getAttribute("data-href")) {
                      e.preventDefault();
                      var idName = domArr[key].getAttribute("data-href").split("#")[1];
                      var scrollVal = document.getElementById(idName).offsetTop;
                      document.documentElement.scrollTop = scrollVal
                  }
                }
              }
            })
        }
      },
  }
  const init = () => {
    controller.linkToFun(document.getElementsByClassName('article-contents')[0].getElementsByTagName('a'))
  }
  return {
      init
  }
})()

对应内容页引入:

head() {
    return {
      script: [
        { src: "/js/article.js", defer: true },
      ]
    }
  }

引用时,不需要添加/static目录,因为/static目录编译后会被映射到/目录

好啦,又可以跟运营小姐姐愉快的玩耍了,今天分享就到这里。

文章内容属于个人拙见,如有什么疑问,欢迎大家评论区留言!