VuePress 博客优化之中文锚点跳转问题

简介: 「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

0.png


「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。


前言


《一篇带你用 VuePress + Github Pages 搭建博客》中,我们使用 VuePress 搭建了一个博客,最终的效果查看:TypeScript 中文文档


VuePress 会在每个标题左侧都加一个锚点链接:


1.png


点击后链接变为:


http://ts.yayujs.com/learn-typescript/handbook/TheBasics.html#降级-downleveling
复制代码


此时刷新下页面,会发现,页面并不能正确的定位到锚点位置,而且打开开发者工具,还会看到报错:


2.png


那这个问题该怎么解决呢?


错误定位


在线上由于代码都是压缩混淆后的,不好排查,我们在本地运行项目,然后查看报错信息:


3.png


可以看到错误是来自于 vuerepss-plugin-smooth-scroll 这个插件中,我们点击查看具体的源码:


4.png


可以看到,报错是来自于 document.querySelector(to.hash) 这句,为什么会在这里报错呢?


这是因为对于每一个标题,VuePress 都会生成这样一个 DOM 结构:


5.png


可以看到h2标签的id是以 hash 值命名的,如果我们的 hash 是纯英文,并没有什么问题,但是现在我们的 hash 中有中文,由于中文被编码,document.querySelector报错。


官方方案


这个问题这么容易复现,且这么明显,我想肯定有人提了 issue,查看 VuePress 的 issue,可以看到在 2020 年  10 月 3 号就有人提了 PR,并且 merge 了。


那为什么还会报错呢?


如果我们去掉我们目前在用的 reco主题,我们就会发现,页面并不会有报错,只不过依然不能定位到锚点而已。


实际上,我们的报错是来自于我们使用的 reco 主题使用的 vuerepss-plugin-smooth-scroll 插件。


社区方案


那成吧,那搜索看下其他人是否也遇到过这个问题吧,可以查到这样一个方案


新建一个 docs/.vuepress/theme/layouts/Layout.vue文件,代码写入:


<script>
export default {
  methods: {
    scrollTo(selector) {
      if (!selector || selector === '#') return
      const el = document.querySelector(decodeURIComponent(selector))
      if (el && el.offsetTop) {
        window.scrollTo(0, el.offsetTop)
      }
    }
  },
  mounted() {
    this.scrollTo(location.hash)
  }
}
</script>
复制代码


使用后,页面是不报错了,但会发现样式全部丢失了,因为使用这种方式相当于新建了一个主题,vuePress 已经改用我们的自定义主题了。


不过 VuePress 提供了主题继承的功能,新建一个 docs/.vuepress/theme/index.js,代码写入:


module.exports = {
  extend: '@vuepress/theme-default'
}
复制代码


样式是恢复了一些,但是因为我们本来使用的是 reco 主题,现在改成了继承 vuepress 默认主题,reco 主题带来的一些功能就全丢失了,那我们能继承 reco 主题吗?


答案是不能,这在 VuePress 官方文档的「主题的继承 」章节里有讲到:


主题继承暂时不支持高阶继承,也就是说,一个派生主题无法被继承。


所以为了解决这个方案,就要放弃 reco 主题,而放弃了  reco 主题,本来也不会有报错了……


那我们换个方案吧。


自己动手


成吧成吧,我自己解决。


梳理下当下的问题,当访问带中文锚点的链接时:


  1. 页面有报错,而报错来自于 reco主题使用的 vuepress-plugin-smooth-scroll主题。
  2. 不能正常跳转到锚点位置


页面报错这个问题最简单粗暴的方式就是修改源码了,我们打开 node_modules/vuepress-plugin-smooth-scroll/lib/enhanceApp.js,直接修改:


const enhanceApp = ({ Vue, router }) => {
    router.options.scrollBehavior = (to, from, savedPosition) => {
        // ...
        else if (to.hash) {
            //...
            // 加上 decodeURIComponent
            const targetElement = document.querySelector(decodeURIComponent(to.hash));
            //...
        }
        // ...
    };
};
复制代码


因为我们并不会提交源码,而是提交编译后的文件到服务器上,所以改了依赖的源码也没有什么影响。


接下来是页面加载完跳转到锚点位置,之前我们在 《VuePress 博客优化之添加数据统计功能》,在 enhanceApp.js 中监听路由的改变,同样我们可以监听路由的 ready 事件,然后跳转到直接的位置,我们修改下 .vuepress/enhanceApp.js中的代码:


export default ({ router }) => {
  // ...
  router.onReady(() => {
    const { hash } = document.location;
    setTimeout(() => {
      if (hash.length > 1) {
        const id = decodeURIComponent(hash);
        const el = document.querySelector(`.reco-side-${decodeURIComponent(id).substring(1)}`);
        el.click();
      }
    }, 1000);
  });
};
复制代码


在这里并没有直接获取标题 DOM 元素的位置,然后使用 window.scrollTo 跳转,这是因为在 reco 主题下,随着用户不断的浏览,其实路由也在不停的切换,右侧的目录才会随之改变,这里直接模拟了右侧目录的点击操作,也是为了将具体跳转的行为交给 reco 来实现。


系列文章


博客搭建系列是我至今写的唯一一个偏实战的系列教程,预计 20 篇左右,讲解如何使用 VuePress 搭建、优化博客,并部署到 GitHub、Gitee、私有服务器等平台。本篇为第 20 篇,全系列文章地址:github.com/mqyqingfeng…


微信:「mqyqingfeng」,加我进冴羽唯一的读者群。


如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。



目录
相关文章
|
Web App开发 编解码 JavaScript
VUE播放RTSP方案,支持H.265!
VUE播放RTSP方案,支持H.265!如果你问一个前端技术人员,近几年最火的前端框架技术是什么,肯定会有人说VUE,确实VUE凭借其简单特性赢得了大家的喜爱,而近期公司有个项目,需要在VUE框架网页上播放RTSP实时视频。
1948 0
|
11月前
|
机器学习/深度学习 编解码 边缘计算
深度学习在图像处理中的应用与展望##
本文旨在探讨深度学习技术在图像处理领域的应用及其未来发展趋势。通过分析卷积神经网络(CNN)等关键技术,展示了深度学习如何提升图像识别、分类和生成等任务的性能。同时,本文也讨论了当前面临的挑战和未来的研究方向,为相关领域的研究和实践提供参考。 ##
|
运维 网络协议 网络架构
网络质量探测
网络质量探测
145 0
|
编解码 算法 安全
实测办公场景下,国产远程控制软件的表现力如何?(技术解析)
大家好,我是码农飞哥,作为一个常年混迹职场的老码农。我在工作和生活中碰到了很多问题,也帮助别人解决了很多问题。前有帮实习生配环境,后有帮同事调BUG,中间还有教老爸如何使用手机。
320 0
实测办公场景下,国产远程控制软件的表现力如何?(技术解析)
|
缓存 前端开发 JavaScript
vue3.0 watch 和 computed源码解析(举例图解)
彻底弄清楚 watch 和 computed 原理
|
编译器
#define 宏定义看这一篇文章就够了
#define 宏定义看这一篇文章就够了
656 0
|
存储 索引
顺序表和链表的优缺点总结
顺序表和链表的优缺点总结
1502 0
|
C++
解决嵌入式中QTableWidget双击出现空白QTableWidgetItem输入
&gt; 嵌入式中QTableWidget一般只能看数据不能编辑,或者是选择 &gt; 所以双击出现空白QTableWidgetItem是不允许的
372 0
|
前端开发 对象存储 容器
一款开源的Markdown转富文本编辑器的实现原理剖析
一款开源的Markdown转富文本编辑器的实现原理剖析
484 1
一款开源的Markdown转富文本编辑器的实现原理剖析

热门文章

最新文章