日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > vue >内容正文

vue

js显示格式化代码并高亮(vue中实现代码高亮)

發(fā)布時(shí)間:2023/12/31 vue 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js显示格式化代码并高亮(vue中实现代码高亮) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • js 實(shí)現(xiàn)代碼格式化
      • 調(diào)用 api
    • 實(shí)現(xiàn)代碼高亮
      • 引入
      • 用法
    • highlight.js 高亮代碼不換行
      • innerText 和 innerHTML 有什么區(qū)別
      • 解決 innerHTML 渲染為真實(shí)節(jié)點(diǎn)的問(wèn)題
      • 上色后都是 span 標(biāo)簽,是怎么做到換行的?
    • vue 中使用 highlight.js
    • 用指令使用 js_beautify
    • 關(guān)于文章開(kāi)頭的編輯器
      • 獲取的代碼再次格式化格式亂了

實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的網(wǎng)頁(yè)編輯器,沒(méi)有智能提示,也不會(huì)自動(dòng)高亮標(biāo)簽(需要手動(dòng)高亮)

用的是 vue+ Highlight.js + js-beautify

效果如下圖

js 實(shí)現(xiàn)代碼格式化

首先我們會(huì)用到 <pre></pre>和 <code></code> 標(biāo)簽,包裹我們要展示的 html 代碼,因?yàn)橹挥羞@樣他們才能保持換行/縮進(jìn)等

格式化代碼用到的是 js-beautify

js-beautify 是分別為 js,css,html 提供了 3 個(gè) JS,不必一次性引入那么多不需要的內(nèi)容,比如我要實(shí)現(xiàn)的效果只需要引入 html 的即可

  • cdn 方式:
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify-css.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify-html.min.js"></script>
  • npm 方式
npm install js-beautify@next import { js_beautify, css_beautify, html_beautify } from 'js-beautify'

調(diào)用 api

<pre><code id="html_code"></code></pre> <pre><code id="css_code"></code></pre> <pre><code id="js_code"></code></pre><script>document.querySelector('#html_code').innerText = html_beautify('<div><div>html格式化</div><div>第二行</div></div>',{indent_size: 2,space_in_empty_paren: true})document.querySelector('#css_code').innerText = js_beautify('body{background:red;width:100%;}', {indent_size: 2,space_in_empty_paren: true})document.querySelector('#js_code').innerText = css_beautify("var test = 'a';function(){console.log('test',test)}",{indent_size: 2,space_in_empty_paren: true}) </script>

配置項(xiàng)的參數(shù)有很多,具體可以參照 GitHub 提供的參數(shù)配出相應(yīng)的格式 注意 pre 標(biāo)簽后,不要有空格和回車(chē),不然也會(huì)渲染出來(lái),也一定要有 pre 標(biāo)簽,不然代碼縮進(jìn)的空格也渲染不出來(lái)

小小吐槽一下 html_beautify,感覺(jué)這個(gè) api 有點(diǎn)雞肋,還不如 innerHtml 來(lái)得快,比如

<pre><code id="html_template_code"></code></pre><div style="display: none;" id="html_template"><div><h1>標(biāo)簽格式化</h1><div>html格式化</div></div> </div><script>document.querySelector('#html_template_code').innerText = document.querySelector('#html_template').innerHTML </script>

也能達(dá)到一樣的效果,并且還少引入了一個(gè)庫(kù)~

實(shí)現(xiàn)代碼高亮

用到的就是 highlight.js

highlight.js 中文網(wǎng)、highlight.js 官網(wǎng)

引入

  • cdn 模式
<!-- 核心的JS庫(kù) --> <script src="https://cdn.bootcdn.net/ajax/libs/highlight.js/11.0.1/highlight.min.js"></script> <!-- 代碼高亮的樣式 --> <link href="https://cdn.bootcss.com/highlight.js/9.12.0/styles/atom-one-dark.min.css" rel="stylesheet" />
  • npm 模式
npm install highlight.js// highlight.js 代碼高亮指令 import Hljs from "highlight.js"; import "highlight.js/styles/stackoverflow-light.css"; // 代碼高亮風(fēng)格,選擇更多風(fēng)格需導(dǎo)入 node_modules/hightlight.js/styles/ 目錄下其它c(diǎn)ss文件

用法

在對(duì)應(yīng)的 code/pre 標(biāo)簽上,標(biāo)注上對(duì)應(yīng)的語(yǔ)言,比如:

<pre><code class="language-html"></code></pre> <pre><code class="language-javascript"></code></pre> <pre><code class="language-css"></code></pre>

在頁(yè)面渲染好了之后,執(zhí)行下面的方法,就可以高亮代碼了

hljs.highlightAll()

如果節(jié)點(diǎn)是往后渲染,或者你只想更新某個(gè)代碼塊,可以用下面的方法

hljs.highlightBlock(document.querySelector('#html_code'))

更多的還有 hljs.config 等 api,可以翻一下文檔

highlight.js 高亮代碼不換行

如下圖,剛才用 js-beautify 還搞的好好的,高亮后換行都沒(méi)了

有文章說(shuō)是 pre 的 css 問(wèn)題,其實(shí)研究一下高亮后的 html,其實(shí)和 pre 沒(méi)多大關(guān)系,如果你沒(méi)寫(xiě)pre標(biāo)簽?zāi)蔷驼娴挠嘘P(guān)系

看下正確示范:

怎么做到的?把 innerText,改為 innerHTML。下面仔細(xì)說(shuō)說(shuō)

innerText 和 innerHTML 有什么區(qū)別

渲染后界面看上去確實(shí)是一樣的,改換行的換行,改空格的空格,不過(guò)內(nèi)部的 html 就很不一一樣。

  • innerText 方法顯然把代碼塊有換行的地方幫我們替換了<br>標(biāo)簽
  • innerHtml 方法則是把 html 代碼給渲染了出來(lái)

highlight.js 執(zhí)行高亮的時(shí)候是針對(duì) dom 節(jié)點(diǎn),然后改變 dom 節(jié)點(diǎn)插入標(biāo)簽進(jìn)行高亮的,顯然把代碼中的 <br> 標(biāo)簽給過(guò)濾了(因?yàn)榭吹轿臋n有一個(gè)是否使用<br>標(biāo)簽的配置,所以自身的 br 標(biāo)簽就和他沖突了,純屬個(gè)人猜測(cè))

解決 innerHTML 渲染為真實(shí)節(jié)點(diǎn)的問(wèn)題

html = html.replace(/</g, '&lt;').replace(/>/g, '&gt;') html = html.replace(/</g, '&lt;').replace(/>/g, '&gt;')

也是 innerHTML 和 innerText 的區(qū)別,innerHTML 時(shí)會(huì)進(jìn)行編碼重新轉(zhuǎn)換,把 <> 重新渲染為字符,innerText 則是字符原樣輸出

別看第一段代碼塊沒(méi)換行,其實(shí)中間的空格符隱藏了 \n。所以這也是為啥強(qiáng)調(diào)要用 pre 和 code 標(biāo)簽的原因,普通的div或者其他標(biāo)簽都會(huì)把\n和連續(xù)的空格給過(guò)濾掉。


上色后都是 span 標(biāo)簽,是怎么做到換行的?

明白了上面的內(nèi)容后,再來(lái)看一邊上色效果

代碼塊如下:

再怎么看,這都是 span 標(biāo)簽,那 span 標(biāo)簽是怎么控制什么時(shí)候換行,什么時(shí)候不換行,純 css 是做不到的,答案還是 \n

所以明白為什么 br 無(wú)效 \n 有效,為啥要用 innerHTML 了把

vue 中使用 highlight.js

使用方式有很多種,可以用上面的 hljs 的 api 進(jìn)行。也可以用 vue 的特性(自定義指令)來(lái)完成這一系列的東西

import Hljs from 'highlight.js'let Highlight = {} // 自定義插件 Highlight.install = function(Vue) {// 自定義指令 v-highlightVue.directive('highlight', {// 被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用inserted: function(el) {Hljs.highlightBlock(el)},// 指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用componentUpdated: function(el) {Hljs.highlightBlock(el)}}) }export default Highlight

指令寫(xiě)好后記得要用 Vue 注冊(cè)一下:

import Vue from 'Vue' import Highlight from '上面那段代碼的對(duì)應(yīng)目錄' Vue.use(Highlight)// 使用的時(shí)候 <code v-highlight>這里寫(xiě)代碼</code>

用指令使用 js_beautify

結(jié)合上面的指令,直接封裝一個(gè),先格式化代碼,在高亮代碼的指令!

貪圖方便我就不用項(xiàng)目了,直接建了個(gè) html,用 cdn 引入對(duì)應(yīng)的庫(kù)實(shí)現(xiàn)了一個(gè)

核心的要點(diǎn)上面也都說(shuō)過(guò)了,當(dāng)然代碼還有更好的實(shí)現(xiàn)方式和更多的拓展性,剩下的就多看文檔了~

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify-css.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify-html.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/highlight.js/11.0.1/highlight.min.js"></script><link href="https://cdn.bootcss.com/highlight.js/9.12.0/styles/atom-one-dark.min.css" rel="stylesheet" /><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script></head><body><div id="app"><pre><code v-code class="language-html"><div><div>html格式化</div><div>第二行</div></div></code></pre><hr /><pre><code v-code class="language-css">body{background:red;width:100%;}</code></pre><hr /><pre><code v-code class="language-javascript">var test = 'a';function(){console.log('test',test)}</code></pre></div><script>let code = {}function getBeautifyCode(el) {if (!el || !el.innerHTML) return ''var code = el.innerHTML || ''let className = el.classList ? el.classList.value || '' : ''if (className.indexOf('html') !== -1) {code = html_beautify(code).replace(/</g, '&lt;').replace(/>/g, '&gt;')}if (className.indexOf('css') !== -1) {code = css_beautify(code)}if (className.indexOf('javascript') !== -1) {code = js_beautify(code)}return code}code.install = function(Vue) {Vue.directive('code', {// 被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用inserted: function(el) {el.innerHTML = getBeautifyCode(el)hljs.highlightBlock(el)},// 指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用componentUpdated: function(el) {el.innerHTML = getBeautifyCode(el)hljs.highlightBlock(el)}})}Vue.use(code)new Vue({el: '#app'})</script></body> </html>

關(guān)于文章開(kāi)頭的編輯器

在上訴的步驟都完成了之后,并不能在編輯器這么使用,因?yàn)榫庉嬈骱?vue 并沒(méi)有什么特定的 dom 節(jié)點(diǎn)的關(guān)系(在編輯器加載后,vue 上的數(shù)據(jù)并不會(huì)影響編輯器的內(nèi)容,只能通過(guò)編輯器的 onchange 來(lái)給 vue 同步數(shù)據(jù))

所以先用指令,生成一段 html 代碼,拿到 v-code 渲染后的 innerHtml,在插入到編輯器中,注意編輯器中也要用 pre 包裹著要插入的 html 代碼,由于各個(gè)富文本編輯器都不太一樣,也就不好展開(kāi)~

獲取的代碼再次格式化格式亂了

如果你也有編輯器的這種需求,在進(jìn)行一系列改動(dòng)后執(zhí)行保存操作(getContent)。拿到改動(dòng)后的 html 代碼,提交給接口,刷新列表,把新的數(shù)據(jù)重新賦值到編輯器的時(shí)候發(fā)現(xiàn) js-beautify 不生效了?!

這是因?yàn)檫M(jìn)過(guò)我們格式化和代碼高亮過(guò)后的代碼,已經(jīng)存在了很多空格和換行符,其實(shí)這些空格(或者稱為縮進(jìn))是我們不想保存的,保存了這部分縮進(jìn)后下次進(jìn)行代碼格式化的時(shí)候js-beautify會(huì)認(rèn)為這是故意留下的回車(chē)/空格符,導(dǎo)致一系列的問(wèn)題

所以在我們?cè)俅潍@取到 html 代碼的時(shí)候執(zhí)行一個(gè)操作:

html = html.replace(/[\r\n]/g, '').replace(/>\s*?</g, '><')

把換行符和 2 個(gè)尖括號(hào)中間的內(nèi)容的非字符,都替換掉,就可以了

總結(jié)

以上是生活随笔為你收集整理的js显示格式化代码并高亮(vue中实现代码高亮)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。