# Vue+Vite+Larvel+Inertia 引入 TinyMCE 編輯器 2022-12-14 ###### tags: `Vue` `Laravel` `JS` `TS` `tinymce` `前端心得` `重構` --- 現在連文章的開場都可以去找 AI 來做閱讀說明惹... .... 如果您要在 Vue.js 的應用程式中使用 TinyMCE 編輯器,您需要先安裝 TinyMCE 的 NPM 包。一旦安裝完成,您就可以在應用程式中引入 TinyMCE,並使用 Vue.js 的組件和指令來設置和操作 TinyMCE。 在引入 TinyMCE 時,您需要注意以下幾點: 在應用程式的入口文件(通常是 main.js)中引入 TinyMCE,並設置相關的配置選項,例如工具欄和插件。 在 Vue.js 組件中使用 v-tinymce 指令,將 TinyMCE 添加到組件的模板中。 使用 Vue.js 的 reactive 數據綁定,將組件的數據與 TinyMCE 編輯器的內容保持同步。 另外,在引入 TinyMCE 時,您需要注意 public 和 views 資料夾。這兩個資料夾通常用於存儲應用程式的靜態資源,例如圖片、樣式表和 JavaScript 文件。在引入 TinyMCE 時,如果您需要引用這些靜態資源,您就需要正確指定它們的路徑。例如,如果您要在 TinyMCE 的工具欄中使用一個自定義的圖片按鈕,您就需要在工具欄配置中指定該按鈕的圖片文件路徑。 ![](https://i.imgur.com/uPqp0Si.png) --- ## 注意 import 順序 最新版的 `"tinymce":"^6.3.1"`, `"tinymcv-vue":"^5.0.0"`, 以及 `"tinymce-i18n":"^22.12.4"` 要引入 幾個天坑也要引入: ``` import tinymce from 'tinymce/tinymce'; //tinymce默认hidden,核心組件不引入不會顯示 import 'tinymce/themes/silver'; // 主题文件 import 'tinymce/skins/ui/oxide/skin.css'; // 外觀要引入, 核心組件沒引入顯示不出來 import Editor from '@tinymce/tinymce-vue'; // 核心組件 // import 'tinymce/themes/silver'; // 主题文件 import 'tinymce/models/dom'; // tinymce v6 核心組件必要引入 import 'tinymce/icons/default'; // Icon 引入後顯示對應 Icon import '@/components/adminPage/tinymce/langs/cn.js'; // 中文語言包 import '@/components/adminPage/tinymce/langs/en.js'; // 英文語言包 import 'tinymce/models/dom'; // 必要引入 // tinymce 組件可以按自己需要的進行引入 ``` ---- ## 圖片縮放功能組件, content css 相關設定 用 import 的方式引入相關組組件後, 假如有用到 image 組件的話~ ``` import 'tinymce/plugins/image'; // 插入上傳圖片組件 ``` 必須要引入下列組件, 並且要轉成字串 ``` /* Import content css - will be built into css file */ import contentUiCss from 'tinymce/skins/ui/oxide/content.css'; // 圖片縮放功能寫在 iframe 位置 // import contentCss from 'tinymce/skins/content/default/content.css'; // 圖片縮放功能之二, 假如某些情況下會爆版, 可以替換其他的 cotent.css 或是不引入 ``` 接著要去設定相關的 skin 和 content_css 以及 content_style ``` skin: false, content_css: false, //内容区域css样式 content_style: contentUiCss.toString(), // 使用字串方式引入 css // content_style: contentUiCss.toString() + '\n' + contentCss.toString(), ``` 相關設定可以參考官方文件(官方是用 wepack 範例)以及 stackoveflow~ https://stackoverflow.com/questions/67425439/tinymce-vue-integration-selfhosted --- ## 定義 props, 設置 init, 隱藏廣告, tinymce logo 選項, 置換語系方法 可以用先宣告一個 `init = reactive({...})` 然後在 Vue onMounted() 的階段去執行 `init` ### 定義 `props`: ``` const props = defineProps({ value: { type: String, default: '' }, baseUrl: { type: String, default: '' }, disabled: { type: Boolean, default: false }, plugins: { type: [String, Array], default: 'code lists image media table wordcount preview' // 插件需要import进来 // default: 'wordcount visualchars visualblocks toc textpattern template tabfocus spellchecker searchreplace save quickbars print preview paste pagebreak noneditable nonbreaking media insertdatetime importcss imagetools image hr help fullscreen fullpage directionality codesample code charmap link code table lists advlist anchor autolink autoresize autosave' }, toolbar: { type: [String, Array], default: 'undo redo | formatselect | bold italic underline strikethrough forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent blockquote | lists image media table | codesample code removeformat preview' // default: // "formats undo redo paste print fontsizeselect fontselect template fullpage|wordcount ltr rtl visualchars visualblocks toc spellchecker searchreplace|save preview pagebreak nonbreaking|media image|outdent indent aligncenter alignleft alignright alignjustify lineheight underline quicklink h2 h3 blockquote numlist bullist table removeformat forecolor backcolor bold italic strikethrough hr charmap link insertdatetime|subscript superscript cut codesample code |anchor preview fullscreen|help", }, objId: { type: Object, default: {} } }); ``` ### 設置 `init`: ``` const init = reactive({ // width: '100%', min_height: 240, height: 500, // 自動聚焦 auto_focus: true, skeletonScreen: true, plugins: props.plugins, // 如果有設定 props.xxxx, 要記得先 定義 props toolbar: props.toolbar, ... 其他需要的設定 balabala 這裡可以不用設定 language 和 language_url ... }); ... 定義需要的配置 ... // 组件掛載完成 onMounted(() => { tinymce.init({}); }); ``` ### 隱藏廣告 ``` branding: false, // 隐藏菜单栏, tinymce logo menubar: true, // 是否显示頂部状态栏 promotion: false, // 把菜單欄的 upgrade 按鈕移除 statusbar: true, // 底部資訊列 ``` ### 置換語系方法 可以寫一隻有關共用組件、語言(language)和主題的存放相關, `globalStore` 的 js 檔案 需要用到 pinia 的 defineStore 所以要引入 pinia ``` import { GlobalStore } from "@/stores/index"; ``` ``` // 主要是下面這段定義 language 的地方, 以及 actions:{ updateLanguage} export const GlobalStore = defineStore({ // id: 必须的,在所有 Store 中唯一 id: "GlobalState", // state: 返回对象的函数 state: () => ({ // element组件大小 assemblySize: "default", // language language: 'cn', // themeConfig themeConfig: { // 默认 primary 主题颜色 primary: "#409eff", // 是否开启深色模式 isDark: false } }), getters: {}, actions: { // setAssemblySizeSize setAssemblySizeSize(assemblySize) { this.assemblySize = assemblySize; }, // updateLanguage updateLanguage(language) { this.language = language; }, // setThemeConfig setThemeConfig(themeConfig) { this.themeConfig = themeConfig; } }, }) ``` 接著在 `tinymce/index` 做個 `v-if` ``` <div class="tinymce-box textarea" v-if="renewTextArea"> <editor v-model="textContent" :init="init" :disabled="disabled" /> </div> ``` 記得 import `ref` `reactive` `watch` `nexttick` 等相關 vue 組件 ``` import { ref, reactive, watch, nextTick } from 'vue'; ``` 確定好 globalStore 有引入後 ↓ ### 設置 中英語系配置 可以去 [tinymce 官網載需要的語系](https://www.tiny.cloud/docs/tinymce/6/ui-localization/#language)~ 在 tinymce 底下有 langs 的資料夾, 可以放入所需要的語系 英文 在 tinymce6 內是預設, 如果去 console.log `init.language` 出來會發現 空值, 當然也可以自己設置 en.js 不過有點麻煩 ![](https://i.imgur.com/P3NhB8Z.png) 這邊以 'cn' 為例子, 如果是 cn 相關的設定 `cn.js` 的檔名 `cn` 可以置換, 例如原本官網載下來的應該是 `zh-Hans` 的檔名(Chinese China) ---- 或是可以參考 github 上大神的 repo: 有很多語系轉成 unicode 設定 ↓ https://github.com/pradosoft/tinymce-langs 或是參考其他人的寫法(很棒的 vue3範例) ↓ https://github.com/jzfai/vue3-admin-plus ---- 回來 langs 相關設定~ 點進去 `cn.js` 後可以發現有: ``` // 這邊的 'cn' 可以跟著檔名調整, 如果原檔名是 zh-Hans 的話, 這邊會是 zh-Hans tinymce.addI18n('cn', { "Redo": "\u91cd\u505a", "Undo": "\u64a4\u9500", "Cut": "\u526a\u5207", "Copy": "\u590d\u5236", ..... 上百個定義 I18n... .... ``` 然後記得引到 tinymce/index 內 ``` // 這邊的 'cn' 可以跟著檔名調整, 如果原檔名是 zh-Hans 的話, 這邊會是 zh-Hans import '@/components/adminPage/tinymce/langs/cn.js'; // 簡體中文語言包 ``` ## 接著配置語系切換選項 ``` // element 中英語系配置 if (globalStore.language = 'cn') { init.language = 'cn'; console.log(init.language); } // 監聽 globalStore.language, 讓文字編輯器啟動語言切換 watch(() => globalStore.language, () => { renewTextArea.value = false; init.language = globalStore.language; nextTick(() => { renewTextArea.value = true; }); }); ``` 測試一下~ ![](https://i.imgur.com/ZuWhyO3.png) ![](https://i.imgur.com/pyblMhk.png) 完成~~~ ---- Reference: https://ithelp.ithome.com.tw/articles/10282475 https://juejin.cn/post/7027016714021765127 https://juejin.cn/post/7027018159123071006