[ Nuxt.js 2.x 系列文章 ] Nuxt.js 套件應用-CKEditor 5


版本:nuxt 2.15.8

CKEditor 是一套歷史悠久且功能完整、輕量的富文本編輯器(rich text editor),為使用者提供所見即所得(WYSIWYG)的編輯區域,CKEditor 5 與舊版不同,使用 MVC 架構、ES6 編寫、UI 簡潔,且因應現在的前後端分離趨勢,與前端框架 React、Angular、and Vue.js 做整合,讓我們可以更便利的開發應用。

那麼我們就開始在 Nuxt 專案使用 CKEditor 5 吧,首先選擇編輯器類型(這裡使用 Classic editor),可以透過兩種方式安裝:

Adding a plugin to a build

如果我們想要直接使用 Classic editor 配置好的功能,不需額外擴充,此方法可以快速簡易的建置,首先安裝套件:

npm install --save \
  @ckeditor/ckeditor5-vue2 \
    @ckeditor/ckeditor5-**build**-classic

接著在元件內加入編輯器

<template>
    <div>
        <ckeditor :editor="editor" v-model="editorData"></ckeditor>
    </div>
</template>

<script>
import CKEditor from '@ckeditor/ckeditor5-vue2';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

export default {
    name: 'Editor',
    components: {
        ckeditor: CKEditor.component
    },
    data() {
        return {
            editor: ClassicEditor,
            editorData: '<div>Hello World!</div>'
        };
    }
};
</script>

這樣就完成了,是不是很簡單呢!

但如果我們想擴充功能,像是新增下底線 @ckeditor/ckeditor5-basic-styles/src/underline,專案會直接報錯:

Uncaught CKEditorError: ckeditor-duplicated-modules

原因是 @ckeditor/ckeditor5-**build**-classic 為包裝好的內容,試著進到 node_modules/@ckeditor/ckeditor5-build-classic/package.json 可以看到相依套件已經安裝進去:

因此 CKeditor 在初始化時會因為模組重複執行導致錯誤,可以改用以下方法

Adding a plugin to an editor

客製化配置所有功能,步驟相對複雜,首先安裝基本套件:

npm install --save \
  @ckeditor/ckeditor5-vue2 \
    @ckeditor/ckeditor5-**editor**-classic \
  @ckeditor/ckeditor5-dev-webpack-plugin \
  @ckeditor/ckeditor5-dev-utils \
    @ckeditor/ckeditor5-theme-lark \
    postcss@8 \
  postcss-loader@4 \
  raw-loader@4

重點步驟:需手動設定 webpack,這一步漏掉會直接報錯

const path = require('path');
const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const { styles } = require('@ckeditor/ckeditor5-dev-utils');

export default {
    build: {
        transpile: [ /ckeditor5-[^/\\]+[/\\]src[/\\].+\.js$/ ],
        plugins: [
            // Only with ssr: false
            new CKEditorWebpackPlugin({
                // See https://ckeditor.com/docs/ckeditor5/latest/features/ui-language.html
                language: 'zh',
                additionalLanguages: 'all',
                addMainLanguageTranslationsToAllAssets: true
            })
        ],
        // If you don't add postcss, the CKEditor css will not work.
        postcss: styles.getPostCssConfig({
            themeImporter: {
                themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
            },
            minify: true
        }),
        extend(config) {
            // If you do not exclude and use raw-loader to load svg, the following errors will be caused.
            // Cannot read property 'getAttribute' of null
            const svgRule = config.module.rules.find(item => {
                return /svg/.test(item.test);
            });
            svgRule.exclude = [ path.join(__dirname, 'node_modules', '@ckeditor') ];
            // add svg to load raw-loader
            config.module.rules.push({
                test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
                use: [ 'raw-loader' ]
            });
        }
    }
}

webpack 設定說明:

  • 語言設定:這裡設為繁體中文('zh')
  • 必須在 ssr: false 條件下才能運作,否則會報錯誤 window is not defined,跟 [CKEditorWebpackPlugin] Error: No translation has been found for the XX language
  • 排除 @ckeditor svg,並使用 raw-loader 讀取 svg 內容,否則會拋 cannot read property 'getAttribute' of null 錯誤
  • 使用 PostCSS 轉換 css 代碼,否則會 css 樣式會讀取不到

接著來試著安裝編輯器功能,範例安裝 基本樣式 / 字級 / 字體

npm install --save \
    @ckeditor/ckeditor5-essentials \
    @ckeditor/ckeditor5-font \
    @ckeditor/ckeditor5-paragraph \

💡 所有 ckeditor 所有套件版本必須相同,否則會發生錯誤(@ckeditor/ckeditor5-dev-* 跟 @ckeditor/ckeditor5-vue2 除外)

基礎設定介紹:

  • placeholder:編輯器佔位符
  • plugins:編輯器應用功能
  • toolbar:工具列配置,也可以加入分隔符號 |
  • 其他:各功能的相關設定請見官方文件
<template>
    <div>
        <ckeditor :editor="editor" :config="editorConfig" v-model="editorData"></ckeditor>
    </div>
</template>

<script>
import CKEditor from '@ckeditor/ckeditor5-vue2';
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import FontFamily from '@ckeditor/ckeditor5-font/src/fontfamily';
import FontSize from '@ckeditor/ckeditor5-font/src/fontsize';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';

export default {
    name: 'Editor',
    components: {
        ckeditor: CKEditor.component
    },
    data() {
        return {
            editor: ClassicEditor,
            editorData: '',
            editorConfig: {
                placeholder: '請輸入內容',
                plugins: [ Essentials, FontFamily, FontSize, Paragraph ],
                toolbar: {
                    items: [ 'fontSize', 'fontFamily', '|' ],
                    shouldNotGroupWhenFull: true
                },
                fontSize: {
                    options: [ 12, 16, 18, 20, 24, 32, 40, 48 ],
                    supportAllValues: true
                }
            }
        };
    }
};
</script>

這樣就可以成功看到畫面囉 🫶

💡 是否覺得功能安裝跟配置有點麻煩呢?官方貼心的提供 online-builder ,可以先挑選功能並配置好 toolbar,確認畫面後再安裝

全域註冊

當專案有很多地方會使用到編輯器,我們也可以全域引入

新增檔案置於 plugins,這裡命名 ckeditor.js

import Vue from 'vue';
import CKEditor from '@ckeditor/ckeditor5-vue2';

Vue.use(CKEditor);

nuxt.config.js 配置

export default {
    plugins: [
        { src: '@/plugins/ckeditor' }
    ]   
}

CSS style

實務應用上會在後台使用編輯器來設計內容,然後將 HTML 內容儲存到資料庫,於前台取回資料並渲染在畫面上,所以會需要配置相關的 CSS,確保前後台樣式一致。

只要複製 Content styles 在專案內,然後在編輯器內容的外層容器加上 ck-content CSS class 就可以囉,範例如下:

<template>
    <div class="ck-content">
        // 編輯器內容
        <div v-html="content"></div>
    </div>
</template>

參考文章:

https://github.com/changemyminds/nuxtjs-integrate-ckeditor5?ref=vuejsexamples.com

https://ithelp.ithome.com.tw/articles/10198816

https://medium.com/@charming_rust_oyster_221/ckeditor-5-文字編輯器-研究心得-519c97f20a4

https://ckeditor.com/docs/ckeditor5/latest/installation/frameworks/vuejs-v2.html

#Nuxt #nuxt.js #Vue #Vue.js #ckeditor #ckeditor 5 #editor







你可能感興趣的文章

[筆記] HTTP 協定

[筆記] HTTP 協定

[Preparation for Interview Basic 1] DOM Element

[Preparation for Interview Basic 1] DOM Element

ModernWeb'21 隨筆

ModernWeb'21 隨筆






留言討論