技术博客里,最常见的就是代码了,没有语法高亮的代码,简直没法看下去。

常用的语法高亮 JS 库有 Highlight.jsPrismSyntaxHighlighter 等等,它们的主要工作原理就是搜索 document 中的 <pre><code> 标签,再对其中内容进行正则匹配,识别出使用的语言并为某些内容添加 class,最后根据 CSS 渲染样式。

 

问题

最近在写一个博客应用(开发中),语法高亮交给前端完成,这里我选择了 Highlight.js 作为语法高亮插件。

因为做的是单页应用,前端框架使用的是 Vue,用 Webpack 作为脚手架,所以很自然地 npm i -S highlight.js 安装,之后把 hljs.initHighlightingOnLoad(); 添加到代码里…

欸?为什么明明 hljs 已经注册为全局变量了,但是高亮不工作?是不是我的姿势不对?

 

解决

搜索了很多文章,之后发现是 Vue-Router 的锅,在 $route 改变进行跳转时,vue 会重新渲染页面,并移除页面上所有事件。所以在渲染页面后,监听已经被移除了,也就不会再进行语法高亮了。

 

有两种解决方案:

Vue 自定义指令:

使用 Vue自定义指令,可以在内容渲染时才搜索对应内容中的 <pre><code> 标签,控制更方便。

import hljs from 'highlight.js';
Vue.directive('hljs', el => {
  let blocks = el.querySelectorAll('pre code');
  Array.prototype.forEach.call(blocks, hljs.highlightBlock);
});

使用方法也很简单,在需要进行代码高亮的地方,加上 v-hljs 即可:

<div class="post-content" v-html="postData.content" v-hljs></div>

 

渲染后重新监听:

this.getReady(); // Ready

hljs.initHighlightingOnLoad();

这要根据实际使用情况修改代码,没有第一种方法简单。这里就是在 Ajax 获取数据成功后,重新监听。

 

FAQ:

Q:为什么明明转换成功了,但是就是不见高亮?

A:Highlight.js 的使用说明比较简陋,不仔细看根本不知道样式文件在 highlight.js/src/styles 文件夹中,并需要自己手动引入。

 

Q:我明明使用的是 railscasts 的黑底样式,为什么总有一个 github 的白底样式,是不是会自动引入样式的,要怎么配置呢?

A:Highlight.js 不会自动引入样式,也无法配置。遇到这个问题可能是因为 PHP 的 DebugBar 会内置 github 样式,而且会覆盖手动引入的样式,需要关掉 DebugBar 或修改样式文件提高优先级。

 

参考:

http://www.ahonn.me/2016/07/13/getting-highlightjs-to-work-with-vue.js/


原创文章,转载请以链接形式注明出处:https://blog.ttionya.com/article-1649.html