博客篇 -- Vurperss 优化中文锚点滚动定位问题

Ray Shine 2023/8/1 博客优化Vuepress

记录一下,禁用 vuepress-plugin-smooth-scroll 插件,并将插件内容移动到本地来解决中文锚点跳转失败的问题。

最近使用DocSearch (opens new window)实现全文搜索功能发现一个问题:

  • 当页面锚点为中文时,每次点击锚点,不能实时滚动到锚点位置。

原因是:

插件源码片段:

// 获取锚点,并跳转到锚点位置
const targetElement = document.querySelector(to.hash);
if (targetElement) {
    return window.scrollTo({
        top: getElementPosition(targetElement).y,
        behavior: 'smooth',
    });
}

由于插件是 npm 插件,不方便修改,所以就禁用了插件 vuepress-plugin-smooth-scroll (opens new window),并将插件内容移植到本地实现。

👉 感谢vuepress-plugin-smooth-scroll (opens new window)插件 👈

# Step 1 禁用插件

.vuepress/theme/index.js中,将插件禁用




 



plugins: [
  // ...
  '@vuepress-reco/back-to-top',
  ['vuepress-plugin-smooth-scroll', false]
  // ...
]

# Step 2 实现 SmoothScroll 效果

# scrollBehavior 扩展

.vuepress/theme/helpers/other.js (或者新建JS文件)中实现 router.options 扩展。













 


























export function RouterSmoothScroll(Vue, router) {
  router.options.scrollBehavior = (to, from, savedPosition) => {
    if (savedPosition) {
        return window.scrollTo({
            top: savedPosition.y,
            behavior: 'smooth',
        });
    }
    else if (to.hash) {
        if (Vue.$vuepress.$get('disableScrollBehavior')) {
            return;
        }
        const targetElement = document.querySelector(decodeURIComponent(to.hash));
        if (targetElement) {
            return window.scrollTo({
                top: getElementPosition(targetElement).y,
                behavior: 'smooth',
            });
        }
    }
    else {
        return window.scrollTo({
            top: 0,
            behavior: 'smooth',
        });
    }
  }
}

function getElementPosition(el) {
  const docEl = document.documentElement;
  const docRect = docEl.getBoundingClientRect();
  const elRect = el.getBoundingClientRect();
  return {
      x: elRect.left - docRect.left,
      y: elRect.top - docRect.top,
  };
}

实际只是将原本的 querySelector 选择器中的 to.hash 进行 URL 转码。

// 找到以下代码并修改
const targetElement = document.querySelector(to.hash);
// 修改后
const targetElement = document.querySelector(decodeURIComponent(to.hash));

# smoothscroll 样式

.vuepress/theme/styles 文件夹下新建 smoothscroll.styl 文件。

html
  scroll-behavior smooth

# smoothscroll 混入

.vuepress/theme/mixins 文件夹下新建 smoothscroll.js 文件。

混入 smoothscroll-polyfill页面平滑滚动插件。

import smoothscroll from 'smoothscroll-polyfill'
import '../styles/smoothscroll.styl'
export default {
    mounted() {
        smoothscroll.polyfill()
    },
}

::: tips 此处只针对 Vuepress 博客设置,如需了解更多,点这里 (opens new window) :::

# enhanceApp.js 引入

修改 .vuepress/theme/enhanceApp.js 主题入口文件。



 
 









 

 




import postMixin from '@theme/mixins/posts'
import localMixin from '@theme/mixins/locales'
import smoothscroll from '@theme/mixins/smoothscroll'
import { interceptRouterError, fixRouterError404, RouterSmoothScroll} from '@theme/helpers/other'

export default ({
  Vue,
  siteData,
  isServer,
  router
}) => {
  Vue.mixin(postMixin)
  Vue.mixin(localMixin)
  Vue.mixin(smoothscroll)

  RouterSmoothScroll(Vue, router)
  interceptRouterError(router)
  fixRouterError404(router)
}

# Step 3 重新启动

npm run dev

yarn dev
最后更新时间: 2025/8/27 00:23:57
ON THIS PAGE