## 簡介
TinyMCE Vue 是官方提供的 TinyMCE 富文本編輯器的 Vue 組件封裝,支持 Vue 2 和 Vue 3。它讓你可以在 Vue 項目中快速集成強大的富文本編輯能力,支持多種插件、主題和自定義擴展,適用于博客、內容管理、后臺系統等多種場景。
主要特性:
- 📦 簡單集成,支持 v-model 雙向綁定
- 🧩 豐富的編輯器插件與工具欄自定義
- 🌏 多語言支持,輕松切換中文等本地化
- 🎨 支持自定義皮膚和內容樣式
- 🔌 支持圖片上傳、表格、代碼塊、媒體等高級功能
- ? 性能優秀,適配移動端和桌面端
## 安裝依賴
```bash
# 安裝 tinymce-vue
npm install @tinymce/tinymce-vue
# 或者使用 yarn
yarn add @tinymce/tinymce-vue
```
## 基本使用示例
### 創建基礎編輯器組件
```vue
<template>
<div class="editor-container">
<h2>基礎編輯器</h2>
<Editor v-model="content" :init="initConfig" @onInit="onEditorInit" />
</div>
</template>
<script setup>
import { ref } from "vue";
import Editor from "@tinymce/tinymce-vue";
const content = ref("<p>這是初始內容</p>");
const initConfig = {
height: 300,
menubar: false,
plugins: [
"advlist",
"autolink",
"lists",
"link",
"image",
"charmap",
"preview",
"anchor",
"searchreplace",
"visualblocks",
"code",
"fullscreen",
"insertdatetime",
"media",
"table",
"code",
"help",
"wordcount",
],
toolbar:
"undo redo | blocks | " +
"bold italic forecolor | alignleft aligncenter " +
"alignright alignjustify | bullist numlist outdent indent | " +
"removeformat | help",
content_style:
"body { font-family:Helvetica,Arial,sans-serif; font-size:14px }",
};
const onEditorInit = (editor) => {
console.log("編輯器初始化完成", editor);
};
</script>
<style scoped>
.editor-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
</style>
```
注意:上面代碼無法編輯,需要注冊申請 apikey,具體參考官網
```vue
<template>
<Editor api-key="your-api-key" />
</template>
```
## 高級功能示例
```vue
<template>
<div class="advanced-editor">
<h2>高級編輯器</h2>
<Editor
v-model="advancedContent"
:init="advancedConfig"
@onChange="onContentChange"
/>
</div>
</template>
<script setup>
import { ref } from "vue";
import Editor from "@tinymce/tinymce-vue";
const advancedContent = ref("");
const advancedConfig = {
height: 400,
menubar: true,
plugins: [
"advlist",
"autolink",
"lists",
"link",
"image",
"charmap",
"preview",
"anchor",
"searchreplace",
"visualblocks",
"code",
"fullscreen",
"insertdatetime",
"media",
"table",
"paste",
"help",
"wordcount",
"emoticons",
"codesample",
],
toolbar: [
"undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify",
"bullist numlist outdent indent | removeformat | help | image media table | emoticons codesample",
],
content_style: `
body {?
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;?
font-size: 14px;?
line-height: 1.6;
}
.mce-content-body { max-width: 100%; }
`,
// 自定義樣式
style_formats: [
{ title: "標題 1", format: "h1" },
{ title: "標題 2", format: "h2" },
{ title: "標題 3", format: "h3" },
{ title: "代碼", inline: "code" },
{ title: "引用", block: "blockquote" },
],
// 圖片上傳配置
images_upload_url: "/api/upload",
images_upload_handler: (blobInfo, progress) => {
return new Promise((resolve, reject) => {
// 模擬上傳
setTimeout(() => {
resolve("https://via.placeholder.com/300x200");
}, 1000);
});
},
};
const onContentChange = (event) => {
console.log("內容變化:", event.target.getContent());
};
</script>
```
## 常用配置選項
### 基礎配置
```javascript
const basicConfig = {
// 編輯器高度
height: 300,
? // 是否顯示菜單欄
menubar: false,
? // 啟用的插件
plugins: [
"advlist",
"autolink",
"lists",
"link",
"image",
"charmap",
"preview",
"anchor",
"searchreplace",
"visualblocks",
"code",
"fullscreen",
"insertdatetime",
"media",
"table",
"code",
"help",
"wordcount",
],
? // 工具欄配置
toolbar:
"undo redo | formatselect | bold italic | " +
"alignleft aligncenter alignright alignjustify | " +
"bullist numlist outdent indent | removeformat | help",
? // 內容樣式
content_style: "body { font-family: Arial, sans-serif; font-size: 14px; }",
? // 語言設置
language: "zh_CN",
? // 主題
skin: "oxide",
? // 占位符文本
placeholder: "請輸入內容...",
};
```
### 高級配置
```javascript
const advancedConfig = {
// 自定義樣式格式
style_formats: [
{ title: "標題 1", format: "h1" },
{ title: "標題 2", format: "h2" },
{ title: "代碼", inline: "code" },
{ title: "引用", block: "blockquote" },
],
? // 自定義按鈕
setup: (editor) => {
editor.ui.registry.addButton("custombutton", {
text: "自定義按鈕",
onAction: () => {
editor.insertContent("<p>這是自定義按鈕插入的內容</p>");
},
});
},
? // 圖片上傳
images_upload_handler: (blobInfo, progress) => {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append("file", blobInfo.blob(), blobInfo.filename());
? ? ? fetch("/api/upload", {
method: "POST",
body: formData,
})
.then((response) => response.json())
.then((result) => resolve(result.url))
.catch((error) => reject(error));
});
},
? // 內容驗證
setup: (editor) => {
editor.on("change", () => {
const content = editor.getContent();
if (content.length > 1000) {
editor.notificationManager.warn("內容過長,請精簡");
}
});
},
};
```
## 事件處理
```javascript
// 編輯器事件
const editorEvents = {
onInit: (editor) => {
console.log("編輯器初始化完成");
},
? onChange: (event) => {
console.log("內容變化:", event.target.getContent());
},
? onBlur: (event) => {
console.log("編輯器失去焦點");
},
? onFocus: (event) => {
console.log("編輯器獲得焦點");
},
? onKeyUp: (event) => {
console.log("按鍵釋放:", event.keyCode);
},
};
```
## 自定義插件
### 插入當前時間插件
```javascript
// 注冊插入時間插件
tinymce.PluginManager.add("inserttime", function (editor) {
editor.ui.registry.addButton("inserttime", {
text: "插入時間",
tooltip: "插入當前時間",
onAction: function () {
const now = new Date();
const timeString = now.toLocaleString("zh-CN");
editor.insertContent(`<span class="timestamp">${timeString}</span>`);
},
});
? // 添加到工具欄
editor.ui.registry.addMenuItem("inserttime", {
text: "插入時間",
onAction: function () {
const now = new Date();
const timeString = now.toLocaleString("zh-CN");
editor.insertContent(`<span class="timestamp">${timeString}</span>`);
},
});
});
// 使用配置
const config = {
plugins: "inserttime",
toolbar: "inserttime",
content_style: `
.timestamp {
background-color: #f0f0f0;
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
color: #666;
}
`,
};
```
### 代碼高亮插件
```javascript
// 代碼高亮插件
tinymce.PluginManager.add("codehighlight", function (editor) {
// 添加代碼高亮按鈕
editor.ui.registry.addButton("codehighlight", {
text: "代碼高亮",
tooltip: "插入代碼塊",
onAction: function () {
editor.windowManager.open({
title: "插入代碼",
body: {
type: "panel",
items: [
{
type: "input",
name: "code",
label: "代碼內容",
placeholder: "請輸入代碼...",
},
{
type: "selectbox",
name: "language",
label: "編程語言",
items: [
{ value: "javascript", text: "JavaScript" },
{ value: "html", text: "HTML" },
{ value: "css", text: "CSS" },
{ value: "python", text: "Python" },
{ value: "java", text: "Java" },
],
},
],
},
buttons: [
{
type: "submit",
text: "插入",
},
{
type: "cancel",
text: "取消",
},
],
onSubmit: function (api) {
const data = api.getData();
const code = data.code;
const language = data.language;
? ? ? ? ? editor.insertContent(`
<pre class="code-block" data-language="${language}">
<code class="language-${language}">${editor.dom.encode(
code
)}</code>
</pre>
`);
api.close();
},
});
},
});
? // 添加到菜單
editor.ui.registry.addMenuItem("codehighlight", {
text: "代碼高亮",
onAction: function () {
// 同上的對話框邏輯
},
});
});
// 使用配置
const config = {
plugins: "codehighlight",
toolbar: "codehighlight",
content_style: `
.code-block {
background-color: #f5f5f5;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
margin: 10px 0;
font-family: 'Courier New', monospace;
font-size: 13px;
line-height: 1.4;
overflow-x: auto;
}
.code-block code {
background: none;
padding: 0;
}
`,
};
```
## 注意事項
1. **API Key**: 生產環境需要申請 TinyMCE API Key
2. **CDN**: 建議使用 CDN 加速加載
3. **國際化**: 需要下載對應的語言包
4. **主題**: 可以自定義主題樣式
5. **插件**: 按需加載插件以提高性能