日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

文章目錄

    • js 實現代碼格式化
      • 調用 api
    • 實現代碼高亮
      • 引入
      • 用法
    • highlight.js 高亮代碼不換行
      • innerText 和 innerHTML 有什么區別
      • 解決 innerHTML 渲染為真實節點的問題
      • 上色后都是 span 標簽,是怎么做到換行的?
    • vue 中使用 highlight.js
    • 用指令使用 js_beautify
    • 關于文章開頭的編輯器
      • 獲取的代碼再次格式化格式亂了

實現一個簡易版的網頁編輯器,沒有智能提示,也不會自動高亮標簽(需要手動高亮)

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

效果如下圖

js 實現代碼格式化

首先我們會用到 <pre></pre>和 <code></code> 標簽,包裹我們要展示的 html 代碼,因為只有這樣他們才能保持換行/縮進等

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

js-beautify 是分別為 js,css,html 提供了 3 個 JS,不必一次性引入那么多不需要的內容,比如我要實現的效果只需要引入 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'

調用 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>

配置項的參數有很多,具體可以參照 GitHub 提供的參數配出相應的格式 注意 pre 標簽后,不要有空格和回車,不然也會渲染出來,也一定要有 pre 標簽,不然代碼縮進的空格也渲染不出來

小小吐槽一下 html_beautify,感覺這個 api 有點雞肋,還不如 innerHtml 來得快,比如

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

也能達到一樣的效果,并且還少引入了一個庫~

實現代碼高亮

用到的就是 highlight.js

highlight.js 中文網、highlight.js 官網

引入

  • cdn 模式
<!-- 核心的JS庫 --> <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"; // 代碼高亮風格,選擇更多風格需導入 node_modules/hightlight.js/styles/ 目錄下其它css文件

用法

在對應的 code/pre 標簽上,標注上對應的語言,比如:

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

在頁面渲染好了之后,執行下面的方法,就可以高亮代碼了

hljs.highlightAll()

如果節點是往后渲染,或者你只想更新某個代碼塊,可以用下面的方法

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

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

highlight.js 高亮代碼不換行

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

有文章說是 pre 的 css 問題,其實研究一下高亮后的 html,其實和 pre 沒多大關系,如果你沒寫pre標簽那就真的有關系

看下正確示范:

怎么做到的?把 innerText,改為 innerHTML。下面仔細說說

innerText 和 innerHTML 有什么區別

渲染后界面看上去確實是一樣的,改換行的換行,改空格的空格,不過內部的 html 就很不一一樣。

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

highlight.js 執行高亮的時候是針對 dom 節點,然后改變 dom 節點插入標簽進行高亮的,顯然把代碼中的 <br> 標簽給過濾了(因為看到文檔有一個是否使用<br>標簽的配置,所以自身的 br 標簽就和他沖突了,純屬個人猜測)

解決 innerHTML 渲染為真實節點的問題

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

也是 innerHTML 和 innerText 的區別,innerHTML 時會進行編碼重新轉換,把 <> 重新渲染為字符,innerText 則是字符原樣輸出

別看第一段代碼塊沒換行,其實中間的空格符隱藏了 \n。所以這也是為啥強調要用 pre 和 code 標簽的原因,普通的div或者其他標簽都會把\n和連續的空格給過濾掉。


上色后都是 span 標簽,是怎么做到換行的?

明白了上面的內容后,再來看一邊上色效果

代碼塊如下:

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

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

vue 中使用 highlight.js

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

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

指令寫好后記得要用 Vue 注冊一下:

import Vue from 'Vue' import Highlight from '上面那段代碼的對應目錄' Vue.use(Highlight)// 使用的時候 <code v-highlight>這里寫代碼</code>

用指令使用 js_beautify

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

貪圖方便我就不用項目了,直接建了個 html,用 cdn 引入對應的庫實現了一個

核心的要點上面也都說過了,當然代碼還有更好的實現方式和更多的拓展性,剩下的就多看文檔了~

<!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', {// 被綁定元素插入父節點時調用inserted: function(el) {el.innerHTML = getBeautifyCode(el)hljs.highlightBlock(el)},// 指令所在組件的 VNode 及其子 VNode 全部更新后調用componentUpdated: function(el) {el.innerHTML = getBeautifyCode(el)hljs.highlightBlock(el)}})}Vue.use(code)new Vue({el: '#app'})</script></body> </html>

關于文章開頭的編輯器

在上訴的步驟都完成了之后,并不能在編輯器這么使用,因為編輯器和 vue 并沒有什么特定的 dom 節點的關系(在編輯器加載后,vue 上的數據并不會影響編輯器的內容,只能通過編輯器的 onchange 來給 vue 同步數據)

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

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

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

這是因為進過我們格式化和代碼高亮過后的代碼,已經存在了很多空格和換行符,其實這些空格(或者稱為縮進)是我們不想保存的,保存了這部分縮進后下次進行代碼格式化的時候js-beautify會認為這是故意留下的回車/空格符,導致一系列的問題

所以在我們再次獲取到 html 代碼的時候執行一個操作:

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

把換行符和 2 個尖括號中間的內容的非字符,都替換掉,就可以了

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。