foreword
In "An article that takes you to build a blog with VuePress + Github Pages" , we used VuePress to build a blog. Check the final effect: TypeScript Chinese document .
VuePress will add an anchor link to the left of each title:
After clicking the link becomes:
http://ts.yayujs.com/learn-typescript/handbook/TheBasics.html#降级-downleveling
At this point, when you refresh the page, you will find that the page cannot be correctly positioned to the anchor point, and when you open the developer tools, you will see an error:
How to solve this problem?
wrong location
Since the code is compressed and obfuscated online, it is not easy to troubleshoot. We run the project locally and check the error message:
You can see that the error comes from vuerepss-plugin-smooth-scroll
, we click to view the specific source code:
It can be seen that the error is from the document.querySelector(to.hash)
, why is the error reported here?
This is because for each title, VuePress generates a DOM structure like this:
I can see h2
label id
is named hash value, the hash if we are pure English, and there is no problem, but now we have the hash in Chinese, because the Chinese are encoded, document.querySelector
error.
Official program
This problem is so easy to reproduce and so obvious, I think someone must have raised an issue, check the VuePress issue, and you can see that on October 3, 2020, someone raised PR and merged.
Then why is it still giving an error?
If we remove the reco
theme we are currently using, we will find that the page will not report an error, but it still cannot locate the anchor point.
In fact, our error came from the vuerepss-plugin-smooth-scroll
plugin reco
community program
That's it, then search to see if other people have encountered this problem, you can find such a scheme :
Create a new docs/.vuepress/theme/layouts/Layout.vue
file and write the code:
<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>
After use, the page will not report an error, but you will find that all styles are lost, because using this method is equivalent to creating a new theme, and vuePress has switched to our custom theme.
However, VuePress provides the theme to inherit , create a new docs/.vuepress/theme/index.js
, and write the code:
module.exports = {
extend: '@vuepress/theme-default'
}
The style has been restored, but because we used the reco theme originally, and now we have changed it to inherit the vuepress default theme, some functions brought by the reco theme are all lost. Can we inherit the reco theme?
The answer is no, this is in the "Theme Inheritance" chapter of the 161f919c34ea9d VuePress official document:
Theme inheritance currently does not support higher-order inheritance, that is, a derived theme cannot be inherited.
So in order to solve this solution, it is necessary to give up the reco theme, and give up the reco theme, and there will be no error...
Then let's change the plan.
Do it yourself
Let it be done, I will solve it myself.
To sort out the current problems, when visiting links with Chinese anchors:
- The page has an error, and the error comes from the
reco
theme used by thevuepress-plugin-smooth-scroll
theme. - Can't jump to the anchor position normally
The simplest and rude way to report an error on the page is to modify the source code. We open node_modules/vuepress-plugin-smooth-scroll/lib/enhanceApp.js
and modify it directly:
const enhanceApp = ({ Vue, router }) => {
router.options.scrollBehavior = (to, from, savedPosition) => {
// ...
else if (to.hash) {
//...
// 加上 decodeURIComponent
const targetElement = document.querySelector(decodeURIComponent(to.hash));
//...
}
// ...
};
};
Because we do not submit the source code, but submit the compiled files to the server, changing the dependent source code has no effect.
The next step is to jump to the anchor position after the page is loaded. Before, we were in "VuePress Blog Optimization: Adding Data Statistics Function" , in enhanceApp.js
to monitor the routing change, we can also monitor the ready event of the route, and then jump to Directly, we modify the code in .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);
});
};
There is no direct access to the position of the title DOM element, and then use window.scrollTo
jump. This is because under the reco
, as the user continues to browse, the routing is also constantly switching, and the directory on the right will follow. Change, the click operation of the right directory is directly simulated here, and it is also to hand over the specific jump behavior to reco
.
series of articles
The blog building series is the only series of practical tutorials I have written so far. It is expected to be about 20 articles, explaining how to use VuePress to build and optimize blogs, and deploy them to GitHub, Gitee, private servers and other platforms. This article is the 20th article, the address of the whole series of articles: https://github.com/mqyqingfeng/Blog
WeChat: "mqyqingfeng", add Yu Yu's friends, and pull you into the front-end learning exchange group.
If there are any mistakes or inaccuracies, please be sure to correct me, thank you very much. If you like or have inspiration, welcome to star, which is also an encouragement to the author.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。