富文本方案
注意
富文本 我用的方案就是 wangeditor
安装
bash
npm i @wangeditor/editor @wangeditor/editor-for-vue@next -S
自己封装组件
- components/Wangeditor.vue
这里特别注意 就是 只能在 onMounted 里面初始化富文本,父组件传递进来 上传图片点击不了
vue
<template>
<div style="border: 1px solid #ccc">
<!-- 工具栏 -->
<Toolbar
:editor="editorRef"
:defaultConfig="toolbarConfig"
style="border-bottom: 1px solid #ccc"
/>
<!-- 编辑器 -->
<Editor
v-model="valueHtml"
:defaultConfig="editorConfig"
@onChange="handleChange"
@onCreated="handleCreated"
@onDestroyed="handleDestroyed"
@onFocus="handleFocus"
@onBlur="handleBlur"
@customAlert="customAlert"
@customPaste="customPaste"
style="height: 500px"
/>
<div>
<button @click="getHtml">获取 html</button>
</div>
</div>
</template>
<script setup>
import { Boot } from "@wangeditor/editor";
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef();
// 内容 HTML
const valueHtml = ref("");
// 模拟 ajax 异步获取内容
onMounted(() => {
setTimeout(() => {
valueHtml.value = "<p>模拟 Ajax 异步设置内容</p>";
}, 1500);
});
// 编辑器配置
const editorConfig = {
debug: true,
placeholder: "请输入内容...",
MENU_CONF: {
uploadImage: {
server: "/api/upload",
headers: { Authorization: "5656" },
"tenant-id": "1",
fieldName: "file",
customInsert(res, insertFn) {
if (res.code == 0) {
let url = res.data.url; // 图片 src ,必须
let alert = "图片"; // 图片描述文字,非必须
let href = ""; // 图片的链接,非必须
insertFn(url, alert, href);
}
},
},
},
};
// 测试:注册 button menu
class MyButtonMenu {
constructor() {
(this.title = "menu1"), (this.tag = "button");
}
getValue() {
return "";
}
isActive() {
return false;
}
isDisabled() {
return false;
}
exec(editor) {
console.log(editor);
alert("menu1 exec");
}
}
const menuConf = {
key: "my-menu-1", // menu key ,唯一。注册之后,需通过 toolbarKeys 配置到工具栏
factory() {
return new MyButtonMenu();
},
};
Boot.registerMenu(menuConf);
// 工具栏配置
const toolbarConfig = {
// toolbarKeys: [
// 'headerSelect',
// 'bold',
// 'my-menu-1', // 一些常用的菜单 key
// 'bold', // 加粗
// 'italic', // 斜体
// 'through', // 删除线
// 'underline', // 下划线
// 'bulletedList', // 无序列表
// 'numberedList', // 有序列表
// 'color', // 文字颜色
// 'fontSize', // 字体大小
// 'lineHeight', // 行高
// 'uploadImage', // 上传图片
// 'delIndent', // 缩进
// 'indent', // 增进
// 'deleteImage', //删除图片
// 'divider', // 分割线
// 'justifyCenter', // 居中对齐
// 'justifyJustify', // 两端对齐
// 'justifyLeft', // 左对齐
// 'justifyRight', // 右对齐
// 'undo', // 撤销
// 'redo', // 重做
// 'clearStyle' // 清除格式
// ],
// excludeKeys: [],
insertKeys: {
index: 0,
keys: "my-menu-1",
},
};
// 编辑器回调函数
const handleCreated = (editor) => {
console.log("created", editor);
editorRef.value = editor; // 记录 editor 实例,重要!
// window.editor = editor // 临时测试使用,用完删除
};
const handleChange = (editor) => {
console.log("change:", editor.children);
};
const handleDestroyed = (editor) => {
console.log("destroyed", editor);
};
const handleFocus = (editor) => {
console.log("focus", editor);
};
const handleBlur = (editor) => {
console.log("blur", editor);
};
const customAlert = (info, type) => {
alert(`【自定义提示】${type} - ${info}`);
};
const customPaste = (editor, event, callback) => {
console.log("ClipboardEvent 粘贴事件对象", event);
// 自定义插入内容
editor.insertText("xxx");
// 返回值(注意,vue 事件的返回值,不能用 return)
callback(false); // 返回 false ,阻止默认粘贴行为
// callback(true) // 返回 true ,继续默认的粘贴行为
};
// 及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
// 销毁,并移除 editor
editor.destroy();
});
const getHtml = () => {
const editor = editorRef.value;
if (editor == null) return;
console.log(editor.getHtml());
};
defineExpose({
getHtml,
});
</script>
<style lang="scss" scoped></style>
父组件调用
vue
<template>
<WangEdior ref="wangeditor"></WangEdior>
<el-button type="primary" @click="handleclick">获取富文本数据</el-button>
</template>
<script setup>
// 富文本编辑器
const wangeditor = ref(null);
const handleclick = () => {
wangeditor.value.getHtml();
};
</script>