Appearance
wangEditor
wangEditor 是优秀的国产富文本编辑器,下面我们来掌握在项目中集成上这款编辑器。
安装
可以使用 npm 或 yarn 进行安装
yarn add wangeditor
也可以使用 cdn 引入,这会减少打包的文件大小
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/wangeditor@latest/dist/wangEditor.min.js"></script>
组件定义
下面分别介绍 wangEditor 组件的两种定义式式。
TypeScript
然后定义 wangEditorr 的 Vue 组件
<script lang="ts" setup>
import '@wangeditor/editor/dist/css/style.css'
import { onBeforeUnmount, ref, shallowRef, watch } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { IEditorConfig, IDomEditor, IToolbarConfig, createToolbar, DomEditor } from '@wangeditor/editor'
interface IProps {
modelValue?: any
}
const props = withDefaults(defineProps<IProps>(), {
modelValue: '',
})
const emit = defineEmits(['update:modelValue'])
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()
// 内容 HTML
const valueHtml = ref(props.modelValue)
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor == null) return
editor.destroy()
})
const handleCreated = (editor: IDomEditor) => {
editorRef.value = editor
}
watch([valueHtml], (value: any) => {
emit('update:modelValue', editorRef.value?.getHtml())
})
// 创建工具栏
const mode = ref('default')
const toolbarConfig: Partial<IToolbarConfig> = {
excludeKeys: ['group-video', 'undo', 'redo'],
}
const editorConfig: Partial<IEditorConfig> = {
MENU_CONF: {
uploadImage: {
server: '/api/upload/image',
},
},
}
</script>
<template>
<div style="border: 1px solid #ccc">
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
<Editor
style="height: 500px; overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="handleCreated" />
</div>
</template>
<style lang="scss" scoped>
.w-e-full-screen-container {
z-index: 9999;
}
</style>
CDN
有时为了节省打包大小,我们使用 CDN 方式操作。首先在 vue 模板 index.html 中引入静态资源。
<link href="https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css" rel="stylesheet" />
<script src="https://unpkg.com/@wangeditor/editor@latest/dist/index.js"></script>
<script>
var E = window.wangEditor // 全局变量
</script>
然后声明 wangEditor 组件内容如下
<script lang="ts" setup>
import { uploadImage } from '@@/apis/upload'
const { modelValue, height = '300px' } = defineProps<{ modelValue: string; height?: string }>()
const emit = defineEmits(['update:modelValue'])
const editorConfig: Partial<any> = {
MENU_CONF: {
uploadImage: {
async customUpload(file: File, insertFn: any) {
const form = new FormData()
form.append('file', file, file.name)
const response = await uploadImage(form)
insertFn(response.data.url, '', '')
},
},
},
onChange: (editor: any) => {
console.log('html', editor.getHtml())
emit('update:modelValue', editor.getHtml())
},
}
// 工具栏配置
const toolbarConfig: Partial<any> = {}
const win = window as any
nextTick(() => {
// 创建编辑器
const editor = win.wangEditor.createEditor({
selector: '#editor-container',
config: editorConfig,
mode: 'default',
})
editor.setHtml(modelValue)
// 创建工具栏
const toolbar = win.wangEditor.createToolbar({
editor,
selector: '#toolbar-container',
config: toolbarConfig,
mode: 'default',
})
})
</script>
<template>
<div style="border: 1px solid #ccc">
<div id="toolbar-container" class="border-b"></div>
<div id="editor-container" :style="{ height }"></div>
</div>
</template>
<style lang="scss" scoped>
.w-e-full-screen-container {
z-index: 9999;
}
</style>
使用组件
<script setup lang="ts">
import Editor from '@/components/wang/editor.vue'
import { ref } from 'vue';
const content = ref('abc')
</script>
<template>
<div class>
<Editor :config="{ height: 300 }" v-model="content" />
{{ content }}
</div>
</template>
下面对 props 属性进行说明
属性 | 说明 | 默认值 |
---|---|---|
v-model | 编辑器数据 | |
height | 编辑器高度 |
图片上传
下面对图片上传的前后端进行说明。
前台
上面组件上传使用了 @@/apis/upload
是用 axios 封装的。这样可以让上传像其他 api 一样统一处理,比如使用 token。
你自行参数 axios 文档封装就可以了
后台
后台需要返回以下数据结构
data: { url: '图片地址' }