自定義功能鍵 - daniel-qa/Vue GitHub Wiki

  • 點擊的處理
$elem.on('click', () => {
  const html = `
    <ol style="margin: 10px 0; padding-left: 30px;">
      <li>第一步:準備工作</li>
      <li>第二步:執行操作</li>
      <li>第三步:驗證結果</li>
    </ol>
  `
  editor.cmd.do('insertHTML', html)
  vm.$Message && vm.$Message.success('計數器已插入')
})

🔧 工作原理

  • 1 .initMyEditor 設定預設工具欄
// editorTools.js 第 219-235 行
editor.config.menus = [
  'bold',
  'italic',
  'underline',
  'textDot',
  'indent',
  'link',
  'list',
  'quote',
  'image',
  'video',
  'audio',
  'table',
  'canvas',
  'formula',
  'undo'
]

這時工具欄有 15 個按鈕。

  • 2 .你的 TestComponent 註冊自定義按鈕
// TestComponent.vue
registerCustomMenus(editor) {
  const { $ } = E
  const vm = this
 
  // 定義自定義按鈕
  class CustomCounter {
    constructor(editor) {
      this.editor = editor
      const $elem = $(
        '<div class="w-e-menu" title="插入步驟計數器">' +
        '<i class="w-e-icon-list-ul"></i>' +
        '</div>'
      )
      this.$elem = $elem
      this.type = 'click'
      this._active = false
 
      $elem.on('click', () => {
        // ... 點擊邏輯
      })
    }
    onClick() {}
  }
 
  // 註冊到 wangEditor
  editor.menus.extend('customCounter', CustomCounter)
}

這時 customCounter 已經註冊到 wangEditor,但還沒出現在工具欄。

  • 3 .push() 將自定義按鈕加入工具欄
// TestComponent.vue
this.$editorTools.initMyEditor(editor, this)  // 設定預設 15 個按鈕
this.registerCustomMenus(editor)              // 註冊 customCounter
editor.config.menus.push('customCounter')     // 加入工具欄

執行順序:

initMyEditor 設定 editor.config.menus = ['bold', 'italic', ..., 'undo']
registerCustomMenus 註冊 customCounter 類別
push('customCounter') 將 'customCounter' 加到陣列最後

結果:

editor.config.menus = [
  'bold',
  'italic',
  'underline',
  'textDot',
  'indent',
  'link',
  'list',
  'quote',
  'image',
  'video',
  'audio',
  'table',
  'canvas',
  'formula',
  'undo',
  'customCounter'  // ← 新增在最右邊
]

  • 1 .使用標準配置

這個是自定的預設

// 使用與「新增學校試題」相同的配置
this.$editorTools.initMyEditor(editor, this)
  • 2 .加上自定義功能鍵
// 註冊自定義菜單
this.registerCustomMenus(editor)
 
// 在工具欄最右邊加入自定義按鈕
editor.config.menus.push('customCounter')
  • 3 .內容監聽
editor.config.onchange = (html) => {
  this.editorContent = html
}

每次編輯器內容變化時,會自動更新 this.editorContent。


<template>
  <div class="editor-wrapper">
    <div class="editor-header">
      <h3>🧪 編輯器測試區</h3>
      <p class="subtitle">使用自定義按鈕增強編輯功能</p>
    </div>
    <div class="editor-container">
      <div ref="testEditor" class="editor-content"></div>
    </div>
    <div class="editor-footer">
      <button @click="getEditorContent" class="btn btn-primary">
        📄 獲取內容
      </button>
      <button @click="clearEditor" class="btn btn-secondary">
        🗑️ 清空編輯器
      </button>
    </div>
  </div>
</template>

<script>
import E from 'wangeditor'

export default {
  name: 'TestComponent',
  data() {
    return {
      editor: null,
      editorContent: ''
    }
  },
  mounted() {
    this.initEditor()
  },
  beforeDestroy() {
    if (this.editor) {
      this.editor.destroy()
    }
  },
  methods: {
    initEditor() {
      const editor = new E(this.$refs.testEditor)
      
      // 編輯器配置
      editor.config.height = 400
      editor.config.uploadImgShowBase64 = true
      editor.config.placeholder = '在此輸入內容...'
      
      // 監聽內容變化
      editor.config.onchange = (html) => {
        this.editorContent = html
      }
      
      // 使用標準配置(包含公式、影片、音訊、畫板等)
      this.$editorTools.initMyEditor(editor, this)
      
      // 註冊自定義菜單
      this.registerCustomMenus(editor)
      
      // 在工具欄最右邊加入自定義按鈕
      editor.config.menus.push('customCounter')
      
      editor.create()
      this.editor = editor
      
      // 設置初始內容
      editor.txt.html('<p>🧪 測試編輯器 - 工具欄最右邊有「插入步驟計數器」按鈕</p>')
    },

    /**
     * 註冊所有自定義菜單
     */
    registerCustomMenus(editor) {
      const { $ } = E
      const vm = this

      // 計數器按鈕 - 插入有序列表
      class CustomCounter {
        constructor(editor) {
          this.editor = editor
          const $elem = $(
            '<div class="w-e-menu" title="插入步驟計數器">' +
            '<span style="font-size: 14px; font-weight: bold;">ㄅㄆ</span>' +
            '</div>'
          )
          this.$elem = $elem
          this.type = 'click'
          this._active = false

          $elem.on('click', () => {
            const html = `
              <ol style="margin: 10px 0; padding-left: 30px;">
                <li>第一步:準備工作</li>
                <li>第二步:執行操作</li>
                <li>第三步:驗證結果</li>
              </ol>
            `
            editor.cmd.do('insertHTML', html)
            vm.$Message && vm.$Message.success('計數器已插入')
          })
        }
        onClick() {}
      }

      // 註冊自定義菜單
      editor.menus.extend('customCounter', CustomCounter)
    },

    /**
     * 獲取編輯器內容
     */
    getEditorContent() {
      if (!this.editor) return
      
      const html = this.editor.txt.html()
      const text = this.editor.txt.text()
      
      console.log('HTML 內容:', html)
      console.log('文字內容:', text)
      
      this.$Message && this.$Message.info('內容已輸出到控制台')
    },

    /**
     * 清空編輯器
     */
    clearEditor() {
      if (!this.editor) return
      
      this.$Modal.confirm({
        title: '提示',
        content: '確定要清空編輯器嗎?',
        onOk: () => {
          this.editor.txt.clear()
          this.$Message && this.$Message.success('編輯器已清空')
        },
        onCancel: () => {}
      })
    }
  }
}
</script>

<style scoped>
.editor-wrapper {
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  margin-bottom: 20px;
}

.editor-header {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 20px;
  margin-bottom: 0;
}

.editor-header h3 {
  margin: 0 0 5px 0;
  font-size: 18px;
  font-weight: 600;
}

.subtitle {
  margin: 0;
  font-size: 13px;
  opacity: 0.9;
}

.editor-container {
  padding: 20px;
  border-bottom: 1px solid #f0f0f0;
}

.editor-content {
  min-height: 400px;
  background: #fafafa;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 15px;
}

.editor-footer {
  display: flex;
  gap: 10px;
  padding: 15px 20px;
  background: #f9f9f9;
  justify-content: flex-end;
}

.btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  gap: 6px;
}

.btn-primary {
  background: #667eea;
  color: white;
}

.btn-primary:hover {
  background: #5568d3;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}

.btn-secondary {
  background: #e9ecef;
  color: #495057;
}

.btn-secondary:hover {
  background: #dee2e6;
  transform: translateY(-2px);
}

/* wangeditor 自定義樣式 */
.w-e-menu {
  cursor: pointer;
  transition: background-color 0.2s;
}

.w-e-menu:hover {
  background-color: #f5f5f5;
}

.w-e-menu.active {
  background-color: #667eea !important;
  color: white;
}
</style>
⚠️ **GitHub.com Fallback** ⚠️