今天小編給大家分享一下怎么用VuePress開發(fā)一個代碼復(fù)制插件的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
成都創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站設(shè)計、成都網(wǎng)站制作與策劃設(shè)計,新疆網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:新疆等地區(qū)。新疆做網(wǎng)站價格咨詢:18980820575
但是如果你在配置文件中要做的事情太多了,最好還是將它們提取到單獨的插件中,然后通過設(shè)置絕對路徑或者通過 require 來使用它們:
module.exports = { plugins: [ path.resolve(__dirname, './path/to/your-plugin.js'), require('./another-plugin'), ], }
那就讓我們開始吧!
我們在 .vuepress
文件夾下新建一個 vuepress-plugin-code-copy
的文件夾,用于存放插件相關(guān)的代碼,然后命令行進(jìn)入到該文件夾,執(zhí)行 npm init
,創(chuàng)建 package.json
,此時文件的目錄為:
.vuepress ├─ vuepress-plugin-code-copy │ └─ package.json └─ config.js
我們在 vuepress-plugin-code-copy
下新建一個 index.js
文件,參照官方文檔插件示例中的寫法,我們使用返回對象的函數(shù)形式,這個函數(shù)接受插件的配置選項作為第一個參數(shù)、包含編譯期上下文的 ctx 對象作為第二個參數(shù):
module.exports = (options, ctx) => { return { // ... } }
再參照官方文檔 Option API 中的 name,以及生命周期函數(shù)中的 ready 鉤子,我們寫一個初始的測試代碼:
module.exports = (options, ctx) => { return { name: 'vuepress-plugin-code-copy', async ready() { console.log('Hello World!'); } } }
此時我們運行下 yarn run docs:dev
,可以在運行過程中看到我們的插件名字和打印結(jié)果:
現(xiàn)在我們可以設(shè)想下我們的代碼復(fù)制插件的效果了,我想要實現(xiàn)的效果是:
在代碼塊的右下角有一個 Copy 文字按鈕,點擊后文字變?yōu)?Copied!然后一秒后文字重新變?yōu)?Copy,而代碼塊里的代碼則在點擊的時候復(fù)制到剪切板中。
如果是在 Vue 組件中,我們很容易實現(xiàn)這個效果,在根組件 mounted
或者 updated
的時候,使用 document.querySelector
獲取所有的代碼塊,插入一個按鈕元素,再在按鈕元素上綁定點擊事件,當(dāng)觸發(fā)點擊事件的時候,代碼復(fù)制到剪切板,然后修改文字,1s 后再修改下文字。
那 VuePress 插件有方法可以控制根組件的生命周期嗎?我們查閱下 VuePress 官方文檔的 Option API,可以發(fā)現(xiàn) VuePress 提供了一個 clientRootMixin 方法:
指向 mixin 文件的路徑,它讓你可以控制根組件的生命周期
看下示例代碼:
// 插件的入口 const path = require('path') module.exports = { clientRootMixin: path.resolve(__dirname, 'mixin.js') }
// mixin.js export default { created () {}, mounted () {} }
這不就是我們需要的嗎?那我們動手吧,修改 index.js
的內(nèi)容為:
const path = require('path'); module.exports = (options, ctx) => { return { name: 'vuepress-plugin-code-copy', clientRootMixin: path.resolve(__dirname, 'clientRootMixin.js') } }
在 vuepress-plugin-code-copy
下新建一個 clientRootMixin.js
文件,代碼寫入:
export default { updated() { setTimeout(() => { document.querySelectorAll('div[class*="language-"] pre').forEach(el => { console.log('one code block') }) }, 100) } }
刷新下瀏覽器里的頁面,然后查看打印:
接下來就要思考如何寫入按鈕元素了。
當(dāng)然我們可以使用原生 JavaScript 一點點的創(chuàng)建元素,然后插入其中,但我們其實是在一個支持 Vue 語法的項目里,其實我們完全可以創(chuàng)建一個 Vue 組件,然后將組件的實例掛載到元素上。那用什么方法掛載呢?
我們可以在 Vue 的全局 API 里,找到 Vue.extend
API,看一下使用示例:
// 要掛載的元素
// 創(chuàng)建構(gòu)造器 var Profile = Vue.extend({ template: '{{firstName}} {{lastName}} aka {{alias}}
', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 創(chuàng)建 Profile 實例,并掛載到一個元素上。 new Profile().$mount('#mount-point')
結(jié)果如下:
// 結(jié)果為:Walter White aka Heisenberg
那接下來,我們就創(chuàng)建一個 Vue 組件,然后通過 Vue.extend
方法,掛載到每個代碼塊元素中。
在 vuepress-plugin-code-copy
下新建一個 CodeCopy.vue
文件,寫入代碼如下:
{{ buttonText }}
該組件實現(xiàn)了按鈕的樣式和點擊時將代碼寫入剪切版的效果,整體代碼比較簡單,就不多敘述了。
我們修改一下 clientRootMixin.js
:
import CodeCopy from './CodeCopy.vue' import Vue from 'vue' export default { updated() { // 防止阻塞 setTimeout(() => { document.querySelectorAll('div[class*="language-"] pre').forEach(el => { // 防止重復(fù)寫入 if (el.classList.contains('code-copy-added')) return let ComponentClass = Vue.extend(CodeCopy) let instance = new ComponentClass() instance.code = el.innerText instance.$mount() el.classList.add('code-copy-added') el.appendChild(instance.$el) }) }, 100) } }
這里注意兩點,第一是我們通過 el.innerText
獲取要復(fù)制的代碼內(nèi)容,然后寫入到實例的 code
屬性,在組件中,我們是通過 this.code
獲取的。
第二是我們沒有使用 $mount(element)
,直接傳入一個要掛載的節(jié)點元素,這是因為 $mount()
的掛載會清空目標(biāo)元素,但是這里我們需要添加到元素中,所以我們在執(zhí)行 instance.$mount()
后,通過 instance.$el
獲取了實例元素,然后再將其 appendChild
到每個代碼塊中。關(guān)于 $el
的使用可以參考官方文檔的 el 章節(jié) 。
此時,我們的文件目錄如下:
.vuepress ├─ vuepress-plugin-code-copy │ ├─ CodeCopy.vue │ ├─ clientRootMixin.js │ ├─ index.js │ └─ package.json └─ config.js
至此,其實我們就已經(jīng)實現(xiàn)了代碼復(fù)制的功能。
有的時候,為了增加插件的可拓展性,會允許配置可選項,就比如我們不希望按鈕的文字是 Copy,而是中文的「復(fù)制」,復(fù)制完后,文字變?yōu)?「已復(fù)制!」,該如何實現(xiàn)呢?
前面講到,我們的 index.js
導(dǎo)出的函數(shù),第一個參數(shù)就是 options 參數(shù):
const path = require('path'); module.exports = (options, ctx) => { return { name: 'vuepress-plugin-code-copy', clientRootMixin: path.resolve(__dirname, 'clientRootMixin.js') } }
我們在 config.js
先寫入需要用到的選項:
module.exports = { plugins: [ [ require('./vuepress-plugin-code-copy'), { 'copybuttonText': '復(fù)制', 'copiedButtonText': '已復(fù)制!' } ] ] }
我們 index.js
中通過 options
參數(shù)可以接收到我們在 config.js
寫入的選項,但我們怎么把這些參數(shù)傳入 CodeCopy.vue
文件呢?
我們再翻下 VuePress 提供的 Option API,可以發(fā)現(xiàn)有一個 define API,其實這個 define 屬性就是定義我們插件內(nèi)部使用的全局變量。我們修改下 index.js
:
const path = require('path'); module.exports = (options, ctx) => { return { name: 'vuepress-plugin-code-copy', define: { copybuttonText: options.copybuttonText || 'copy', copiedButtonText: options.copiedButtonText || "copied!" }, clientRootMixin: path.resolve(__dirname, 'clientRootMixin.js') } }
現(xiàn)在我們已經(jīng)寫入了兩個全局變量,組件里怎么使用呢?答案是直接使用!
我們修改下 CodeCopy.vue
的代碼:
// ... // ...
以上就是“怎么用VuePress開發(fā)一個代碼復(fù)制插件”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。