vue+tiptap ,基于vue的无渲染的富文本编辑器

安装tiptap

官网:
github:https://github.com/ueberdosis/tiptap
演示:https://www.vue365.cn/code_demo.php?id=975

npm install tiptap
npm install tiptap-extensions

该编辑器基于prosemiror,完全可扩展且无渲染。您可以轻松地将自定义节点添加为Vue组件。

基础案例
// 如果点击按钮,页面文本的样式没有改变,查看元素的标签是否已经改变,标签已改变,只是页面的样式没有改变,可以查看示例的css样式,
<template>
  <div class="editor">
    <editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
          <div class="menubar">
            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.bold() }"
              @click="commands.bold"
              title="加粗"
            >
              <!-- <icon name="bold" /> -->
              <i class="iconfont r-bold"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.italic() }"
              @click="commands.italic"
              title="斜体"
            >
              <!-- <icon name="italic" /> -->
              <i class="iconfont r-italic"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.strike() }"
              @click="commands.strike"
            >
              <!-- <icon name="strike" /> -->
              <i class="iconfont r-strike"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.underline() }"
              @click="commands.underline"
              title="下划线"
            >
              <!-- <icon name="underline" /> -->
              <i class="iconfont r-underline"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.code() }"
              @click="commands.code"
              title="代码"
            >
              <!-- <icon name="code" /> -->
              <i class="iconfont r-code"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.paragraph() }"
              @click="commands.paragraph"
            >
              <!-- <icon name="paragraph" /> -->
              <i class="iconfont r-paragraph"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.heading({ level: 1 }) }"
              @click="commands.heading({ level: 1 })"
              title="标题1"
            >
              H1
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.heading({ level: 2 }) }"
              @click="commands.heading({ level: 2 })"
              title="标题2"
            >
              H2
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.heading({ level: 3 }) }"
              @click="commands.heading({ level: 3 })"
              title="标题3"
            >
              H3
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.bullet_list() }"
              @click="commands.bullet_list"
              title="有序列表"
            >
              <!-- <icon name="ul" /> -->
              <i class="iconfont r-ul"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.ordered_list() }"
              @click="commands.ordered_list"
              title="无序列表"
            >
              <!-- <icon name="ol" /> -->
              <i class="iconfont r-ol"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.blockquote() }"
              @click="commands.blockquote"
              title="引用"
            >
              <!-- <icon name="quote" /> -->
              <i class="iconfont r-TextQuote-1"></i>
            </el-button>

            <el-button
              class="menubar__button"
              :class="{ 'is-active': isActive.code_block() }"
              @click="commands.code_block"
              title="代码块"
            >
              <!-- <icon name="code" /> -->
              <i class="iconfont r-code"></i>
            </el-button>

            <el-button
              class="menubar__button"
              @click="commands.horizontal_rule"
              title="基准线"
            >
              <!-- <icon name="hr" /> -->
              <i class="iconfont r-hr"></i>
            </el-button>

            <el-button
              class="menubar__button"
              @click="commands.undo"
              title="恢复"
            >
              <!-- <icon name="undo" /> -->
              <i class="iconfont r-undo"></i>
            </el-button>

            <el-button
              class="menubar__button"
              @click="commands.redo"
              title="重做"
            >
              <!-- <icon name="redo" /> -->
              <i class="iconfont r-redo"></i>
            </el-button>
          </div>
        </editor-menu-bar>

    <editor-content class="editor__content" :editor="editor" />
  </div>
</template>

<script>
import { Editor, EditorContent, EditorMenuBar } from 'tiptap'
import {
  Blockquote,
  CodeBlock,
  HardBreak,
  Heading,
  HorizontalRule,
  OrderedList,
  BulletList,
  ListItem,
  TodoItem,
  TodoList,
  Bold,
  Code,
  Italic,
  Link,
  Strike,
  Underline,
  History
} from 'tiptap-extensions'
export default {
  components: {
    EditorContent,
    EditorMenuBar
  },
  data () {
    return {
      editor: new Editor({
        extensions: [
          new Blockquote(),
          new BulletList(),
          new CodeBlock(),
          new HardBreak(),
          new Heading({ levels: [1, 2, 3] }),
          new HorizontalRule(),
          new ListItem(),
          new OrderedList(),
          new TodoItem(),
          new TodoList(),
          new Link(),
          new Bold(),
          new Code(),
          new Italic(),
          new Strike(),
          new Underline(),
          new History()
        ],
        content: `
          <h2>
            Hi there,
          </h2>
          <p>
            this is a very <em>basic</em> example of tiptap.
          </p>
          <pre><code>body { display: none; }</code></pre>
          <ul>
            <li>
              A regular list
            </li>
            <li>
              With regular items
            </li>
          </ul>
          <blockquote>
            It's amazing 👏
            <br />
            – mom
          </blockquote>
        `
      })
    }
  },
  beforeDestroy () {
    this.editor.destroy()
  }
}
</script>
<style>
.editor__content .ProseMirror pre {
    padding: .7rem 1rem;
    border-radius: 5px;
    background: #000;
    color: #fff;
    font-size: .8rem;
    overflow-x: auto;
}
.editor__content .ProseMirror blockquote {
    border-left: 3px solid rgba(0,0,0,.1);
    color: rgba(0,0,0,.8);
    padding-left: .8rem;
    font-style: italic;
}
.editor__content .ProseMirror p code {
    padding: .2rem .4rem;
    border-radius: 5px;
    font-size: .8rem;
    font-weight: 700;
    background: rgba(0,0,0,.1);
    color: rgba(0,0,0,.8);
}
</style>

图示:
在这里插入图片描述

Vue3 + Element Plus 中可以使用官方推荐的 Wangeditor 或者 Quill 等成熟的富文本编辑器库来实现在项目中添加富文本编辑功能。Element Plus 提供了丰富的组件支持,配合这些编辑器插件可以使内容编辑更直观、易用。 Wangeditor是一个轻量级的富文本编辑器,它基于百度的 ECharts 和 Ace Editor 开发,具有良好的性能和定制性。在 Vue3 中,你可以通过安装 `@wangeditor/editor` 包并将其引入到组件中,然后像操作其他Element Plus组件一样使用它。 Quill 是另一个广泛使用的富文本编辑器,它支持Markdown语法,并提供了一个友好的API。在Vue3中,可以借助`quill-editor`这个包装的Vue插件来进行集成。 使用步骤通常包括: 1. 安装所需库:`npm install wangeditor quill-element-plus` 2. 在组件模板上渲染编辑器组件 3. 配置初始化选项(如主题、语言等) 4. 绑定事件监听器,如内容更改、保存等 ```vue <template> <el-button @click="openEditor">打开编辑器</button> <div v-if="editorVisible"> <wangeditor :value="content" @change="handleContentChange"></wangeditor> </div> </template> <script> import { ref } from 'vue'; import Wangeditor from '@wangeditor/editor'; export default { setup() { const editorVisible = ref(false); const content = ref(''); // 初始化编辑器实例 const initEditor = async () => { const editor = await Wangeditor.create({ el: document.createElement('div'), // 使用一个div作为编辑区域 initialValue: content.value, events: { change: (html) => content.value = html, }, }); this.editor = editor; }; // 显示/隐藏编辑器 const openEditor = () => { editorVisible.value = true; if (!this.editor) { initEditor(); } }; return { editorVisible, openEditor, handleContentChange: (html) => {/* 内容变化处理 */} }; }, }; </script> ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值