如何在代码中让按钮高亮_各种博客的代码高亮是如何实现的
本文來自 「Vue虛擬實驗」的小伙伴? 余xiaoy,在做 Lovue 項目的時候,他負責了代碼高亮顯示功能,目前實現了代碼高亮、主題切換、某行代碼特殊顯示、顯示行號等功能,效果如下。
下面介紹如何通過 Vue 來完成這個功能:Vue 為我們提供了很方便的創建組件的方式,組件化開發能夠將業務進行解耦,進而提高項目的開發效率。在 Vue 中定義組件非常簡單:定
<div?id="app">????????<lovue>lovue>div><script>????//?1.?使用Vue.component(name,{})進行組件全局注冊????Vue.component('lovue',?{ template: '這是lovue組件
'????})l????const?vm?=?new?Vue({????????el:?'#app',????????data:?{},????????methods:?{} });script>以上代碼便定義了一個全局的 lovue 組件,隨后我們可以很愉快地在頁面各個位置通過引入 lovue 標簽的形式使用我們的組件了。
對于 demo 型項目,采用這種方式是可以的,但這種形式缺點很明顯,比如字符串模板無法代碼高亮,無法單獨定義 CSS 樣式等。因此在實際的項目當中,我們更多的是采用單文件組件的形式來定義組件。
1、單文件組件
在 Vue 中,一個.vue 文件就是一個單文件組件,一個基本的單文件組件代碼結構如下:
<template> <div> <h3>這是lovue單文件組件h3> div>template><script>export default { // JS代碼部分,包含組件內定義的屬性及方法 name: "Lovue", data() { return {}; }};script><style scoped>/* CSS代碼,添加scoped屬性將定義為局部樣式 */style>將內嵌的組件定義改造為單文件組件形式后,我們可以在其他頁面中,通過 import 語法進行導入,并采取全局或者局部的方式進行注冊:
import Lovue from '@/components/Lovue'// 1.全局注冊Vue.components('lovue', Lovue)// 2.Vue實例內部局部注冊const vm = new Vue({ el: '#app', components: { Lovue }})使用單文件組件,能讓我們的項目文件結構較為清晰,使用 vue-cli創建的項目,腳手架已經幫我們創建好了專門放置組件的文件夾 `components` 和 `views` ,`components` 一般用來放置小型組件,在其他頁面可能會被多次引用,`views`用來放置頁面級組件,一般不可復用。
2、代碼高亮組件實現(基于?Prismjs)
學會使用單文件組件后,我們便可以定制自己的組件了。在 Lovue 項目,我們便創建了代碼高亮組件,其功能是針對指定的代碼塊進行高亮顯示,同時組件還實現了代碼塊內部的局部代碼高亮及代碼塊的主題切換功能,下面使用迭代的思想介紹該組件的實現過程。
創建組件之前,我們需要清楚組件的使用場景,這樣能讓我們更好地對組件功能進行劃分,并從用戶角度去設計一款體驗良好的組件。
具體到 Lovue 的代碼高亮組件,我們需要能夠對文章作者指定的代碼塊進行高亮顯示,同時對于代碼塊中的重點代碼區域可以進行著重顯示,這樣對于文章的讀者來說,可以很快速的了解到作者想講解的代碼片段。同時,為了適應不同讀者對于代碼顯示風格的喜好,組件還需實現多種預定義主題的切換功能。
分析完成后,我們就可以開始創建代碼高亮組件了。
對于代碼高亮功能的實現,目前已有像 Prismjs, highlight.js 等比較成熟,使用程度較高的庫了,這里我們選用 Prismjs 來實現我們的代碼高亮組件。
因為選用了第三方庫,因此第一步我們需要將 Prismjs 引入到我們的項目當中:
npm i prismjs babel-plugin-prismjs -Sprismjs 為核心庫,babel-plugin-prismjs 可以配置 prismjs 附帶的多種插件;若 npm 下載慢,可以使用 cnpm
安裝完成后,我們需要更新項的目配置文件 babel.config.js,添加如下配置項:
"plugins": [ ["prismjs", { "languages": ["html", "javascript", "css", "markup"], "css": true } ] ]以上配置定義了我們需要高亮顯示的代碼語言,配置好之后,我們就可以搭建我們組件的代碼了。
<template> <pre>?????????<code?class="language-javascript"> const vm = new Vue({ el: '#app', data: {}, methods: {} })??????code>?pre>template><script>import Prism from "prismjs";export default { name: "CodeHighLight", mounted() { // Prismjs內置的代碼高亮方法 Prism.highlightAll(); }};script><style>style>上述代碼通過僅使用 Prismjs 庫自帶的方法,已經實現了一個最基本且可用的代碼高亮組件了。是的,就是這么簡單,你現在可以在你的頁面中引入這個組件了,如無意外,你將看到如下效果:
但該組件目前過于簡單,且代碼塊寫死在組件中,用戶無法自定義,因此需要在此基礎上進行改進。這是一個很好的做項目/寫代碼的方式,首先實現最基本的功能,然后在此基礎上進行更新迭代,慢慢添加新的功能。
考慮我們前面分析的使用場景,用戶在父頁面中引入我們的組件時可定義自己的代碼塊,因此該代碼塊是在父組件中定義,但是要在子組件中可以使用的。解決這個問題,我們需要使用到 Vue 中常用的父子組件傳值方法,群里其他同學分享過具體的使用,這里不再贅述,直接上代碼:
<template> <div> <pre v-if="code"> <code :class="codeClass" v-text="code">code> pre> div>template><script>import Prism from "prismjs";import "prismjs/themes/prism-tomorrow.css";export default { name: "CodeHighLight", props: { // 父組件的代碼塊變量 code: { type: String, required: true }, // 代碼語言,默認為JS lang: { type: String, default: "javascript" } }, computed: { codeClass: function() { return "language-" + this.lang; } }, mounted() { Prism.highlightAll(); }, updated() { Prism.highlightAll(); }};script><style>style>這里我們將從父頁面傳遞過來的 code 變量設置為必需項,若用戶未定義,則控制臺打印錯誤。同時考慮我們使用 javascript 語言較多,我們將代碼語言默認設置為 javascript。
代碼改造后,我們就可以通過以下方式在父頁面中使用了,其中 code,code1 為用戶定義的代碼變量:
:code="code"> :code="code1" lang=如無意外,你可以在頁面中可看到類似下面的效果:
到這里,其實用戶已經可以使用該組件了,但為了更好的用戶體驗及提高組件的靈活性,我們還需要在此基礎上進行進一步的更新迭代。
可選的但不限于:顯示代碼的行號,顯示代碼的語言,對代碼塊中的局部代碼進行著重顯示等。
查閱 Prismjs 官方文檔后發現,官方已經為我們提供了很多可選的插件,找到對應的插件名后,我們就可以在 babel.config.js 中對 prismjs 的插件進行配置了。
'plugins': [ ["prismjs", { "languages": ['html', "javascript", "css", "markup"], "plugins": ['match-braces', 'autolinker', 'inline-color', 'normalize-whitespace', 'copy-to-clipboard', 'show-language', 'line-numbers', 'line-highlight'], "css": true } ] ]以上的插件名及對應的作用可以查閱 Prismjs 官方文檔,完成插件配置后,我們需要增加幾個組件的 prop,用于接收父組件定義的局部高亮代碼行數,高亮背景色等變量,具體可到 Lovue 項目 github 倉庫查看。
至此,我們重啟項目,已經可以看到類似下面的效果了:
效果不錯,保存好這版代碼,我們繼續往下,看下如何實現代碼高亮主題切換的功能。
Vue 本身為我們提供了 class 及 style 的數據綁定功能,也有同學分享過相關的使用方法。但因為 Prismjs 的內部實現是將用戶代碼根據語言類型解析并拆分成不同的字符分組,然后針對不同分組在其上應用不同的 class。在 Prismjs 提供的不同主題文件中,相同分組的 class 名均相同,因此我們無法直接通過使用 class 數據綁定的形式進行主題的切換。
使用該思路,一種可行的方式是采用 Scss 等 css 預編譯工具對不同主題的 css 代碼統一增加前綴 class 類名(不同主題類名不同),然后使用數據綁定功能進行類名/主題切換。但操作起來很不方便,這里不討論。
這里采用另一種方式,在頁面中通過 link 標簽引入主題 css 文件,在用戶切換不同的主題時,替換 link 標簽的 href 值為對應的主題 css 文件,實現代碼主題切換。該方式的核心代碼如下,感興趣的可到 Lovue 項目倉庫查看:
methods: { addCss(theme) { let link = document.createElement("link"); let head = document.getElementsByTagName("head")[0]; link.rel = "stylesheet"; link.type = "text/css"; link.href = this.cssPrefix + theme + ".css"; head.appendChild(link); }, loadCss(theme) { let cssLink = "link[href^='" + this.cssPrefix + "']"; let link = document.head.querySelectorAll(cssLink); if (link.length) { // 判斷主題css文件是否存在 for (let i = 0; i < link.length; i++) link[i].href = this.cssPrefix + theme + ".css"; return; } this.addCss(theme); console.log("loadCss done."); }},watch: { // 監聽theme變化,加載對應主題的css文件 theme: function(newVal) { this.loadCss(newVal); localStorage.setItem("codeTheme", newVal); }},mounted() { this.loadCss(theme);}這里使用了?localStorage?來讀取和保存用戶選擇的主題,可提升用戶體驗
至此,Lovue 項目中的代碼高亮組件已基本完成。整個過程不復雜,感興趣的可以動手創建屬于自己的組件了。
推薦閱讀:不寫一行代碼,即可跨域的技巧Vue 模板的功臣 · 指令第六階段 · 期待已久的 Vue第四階段 · JavaScript 專題結束,有電子書
總結
以上是生活随笔為你收集整理的如何在代码中让按钮高亮_各种博客的代码高亮是如何实现的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java分隔符算法_《Java数据结构和
- 下一篇: 挖掘城市ip_抖in杭州嘉年华,原来城市