装置
npm install vditor -s
援用
导入依赖包
import Vditor from “vditor”;
导入款式
import “vditor/src/assets/scss/index.scss”;
应用示例
export default class Vditor extends Component {constructor(props) {super(props);
this.state = {editValue: ""};
}
componentDidMount = () => {
// 组件挂载实现之后调用 留神肯定要在组件挂载实现之后调用 否则会找不到注入的 DOM
this.createVidtor({value: this.state.editValue});
}
// 创立编辑器 上面会详解
createVidtor = params => {let { value} = params;
value = value ? value : " ";
let that = this;
const vditor = new Vditor("vditor", {
height: 800,
mode: "ir", // 及时渲染模式
placeholder: "React Vditor",
toolbar: [
"emoji",
"headings",
"bold",
"italic",
"strike",
"link",
"|",
"list",
"ordered-list",
"check",
"outdent",
"indent",
"|",
"quote",
"line",
"code",
"inline-code",
"insert-before",
"insert-after",
"|",
"upload",
"table",
"|",
"undo",
"redo",
"|",
"fullscreen",
"edit-mode",
{
name: "more",
toolbar: [
"both",
"code-theme",
"content-theme",
"export",
"outline",
"preview",
"devtools",
"info",
"help"
]
},
"|",
{
hotkey: "⌘-S",
name: "save",
tipPosition: "s",
tip: "保留",
className: "right",
icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/save.svg'/>`,
click() {that.saveDoc();
}
},
{
hotkey: "",
name: "publish",
tipPosition: "s",
tip: "公布文章",
className: "right",
icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/publish.svg'/>`,
click() {that.publishDoc();
}
}
],
after() {vditor.setValue(value);
},
blur() {that.saveDoc();
},
upload: {
accept: "image/*",
multiple: false,
filename(name) {
return name
.replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, "")
.replace(/[\?\\/:|<>\*\[\]\(\)\$%\{\}@~]/g, "")
.replace("/\\s/g", "");
},
handler(files) {function callback(path) {let name = files[0] && files[0].name;
let succFileText = "";
if (vditor && vditor.vditor.currentMode === "wysiwyg") {succFileText += `\n <img alt=${name} src="${path}">`;
} else {succFileText += ` \n![${name}](${path})`;
}
document.execCommand("insertHTML", false, succFileText);
}
that.handleImageUpload(files, callback);
},
url(files) {that.handleImageUpload(files);
}
}
});
this.vditor = vditor;
return vditor;
};
// 首先须要在 render 外面注入 DOM,可自定义注入 DOM 的 ID,初始化编辑器的时候应用自定义的 ID 即可
render() {
<div className="editorWrap">
<div id="vditor" />
</div>
}
}
示例:
性能应用
新建对象
const vditor = new Vditor("vditor", ...option);
新建对象时第一个参数 ID,要对应上再 render 外面注入的 ID
option 参数
tip:只列举一下罕用参数,其余的参数请参照官网 API
参数 | 阐明 |
---|---|
height | 配置编辑器高度 |
mode | 编辑器模式 wysiwyg:所见即所得 2 ir: 及时渲染 sv:分屏模式 |
placeholder | 占位符 |
toolbar | 工具栏 |
Tip:如果要自定义工具栏的话,肯定要加上默认的工具栏,不然只展现自定义的了
默认工具栏
tip:此为源码外面 copy 不必更改可间接应用,官网已定义好了快捷键和性能
toolbar: [
"emoji",
"headings",
"bold",
"italic",
"strike",
"link",
"|",
"list",
"ordered-list",
"check",
"outdent",
"indent",
"|",
"quote",
"line",
"code",
"inline-code",
"insert-before",
"insert-after",
"|",
"upload",
"record",
"table",
"|",
"undo",
"redo",
"|",
"fullscreen",
"edit-mode",
{
name: "more",
toolbar: [
"both",
"code-theme",
"content-theme",
"export",
"outline",
"preview",
"devtools",
"info",
"help",
],
}]
对应工具栏展现:
自定义按钮
let that = this;
const vditor = new Vditor("vditor", {
toolbar: [
{
hotkey: "⌘-S",
name: "save",
tipPosition: "s",
tip: "保留",
className: "right",
icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/save.svg'/>`,
click() {that.saveDoc();
}
},
{
hotkey: "",
name: "publish",
tipPosition: "s",
tip: "公布文章",
className: "right",
icon: `<img style="height: 16px" src='https://img.58cdn.com.cn/escstatic/docs/imgUpload/idocs/publish.svg'/>`,
click() {that.publishDoc();
}
}
]
});
//tip:在调用本类封装的办法时提前把 this 赋值给其余办法内的变量,在 Vditor 外部扭转了 this 指向
参数 | 阐明 |
---|---|
hotkey | 热键配置 |
name | 性能辨别(唯一性) |
tip | 悬浮提醒 |
className | UI 展现 right 靠右 |
icon | 按钮图标 |
click | 点击事件 |
示例:
获取值
saveDoc = () => {
// 在初始化时曾经把 vditor 赋值到 this 对象上 可间接通过 getValue 办法获取以后编辑器的值
let mdValue = this.vditor && this.vditor.getValue();
// 获取完值业务保留就行 这里不再具体写自己的保留办法了
...
}
赋值
let {value} = params;
value = value ? value : " ";
// 如果是空值的话 最好给一个空格 免得编辑器初始化时报错
const vditor = new Vditor("vditor", {
// value: value,
after() {vditor.setValue(value);
}
});
//tip:虽说官网也提供 value 间接赋值 然而在 React 外面不失效,就须要在 after 外面去调用 setValue 来实现赋值
自定义图片上传
const vditor = new Vditor("vditor", {
upload: {
accept: "image/*",
multiple: false,
filename(name) {
return name
.replace(/[^(a-zA-Z0-9\u4e00-\u9fa5\.)]/g, "")
.replace(/[\?\\/:|<>\*\[\]\(\)\$%\{\}@~]/g, "")
.replace("/\\s/g", "");
},
handler(files) {function callback(path) {let name = files[0] && files[0].name;
let succFileText = "";
if (vditor && vditor.vditor.currentMode === "wysiwyg") {succFileText += `\n <img alt=${name} src="${path}">`;
} else {succFileText += ` \n![${name}](${path})`;
}
document.execCommand("insertHTML", false, succFileText);
}
that.handleImageUpload(files, callback);
},
url(files, callback) {that.handleImageUpload(files, callback);
}
}
});
// 此接口外面调用的是本人的图片上传 业务方自行实现
handleImageUpload = (file, callback) => {const reader = new FileReader();
let formdata = new FormData();
formdata.append("files", file[0]);
reader.onload = () => {
// setTimeout 模仿异步上传图片
// 当异步上传获取图片地址后,执行 callback 回调(参数为 imageUrl 字符串),即可将图片地址写入 markdown
new Promise(resolve => {
this.props.dispatch({
type: "docManager/imageUpload",
payload: {resolve, username: myInfo.userId, formdata}
});
}).then(res => {
let imgurl = res.result.path;
callback(imgurl);
});
};
reader.readAsDataURL(file[0]);
};
参数 | 阐明 |
---|---|
accept | 接管文件类型(我这边只做了图片上传) |
multiple | 是否多选 |
filename | 格式化文件名 |
handler | 点击数触发办法 |
url | 配置此办法时可实现图片粘贴并上传 |
图片粘贴时读取的文件
上传实现后接口返回的 CDN 地址
上传实现后处理
handler(files) {function callback(path) {let name = files[0] && files[0].name;
let succFileText = "";
// 上传实现获取以后编辑器模式 依据不同模式拼接不同的展现标签
if (vditor && vditor.vditor.currentMode === "wysiwyg") {succFileText += `\n <img alt=${name} src="${path}">`;
} else {succFileText += ` \n![${name}](${path})`;
}
// 拼接完直接插入到鼠标选中地位
document.execCommand("insertHTML", false, succFileText);
}
that.handleImageUpload(files, callback);
}
总结
以上是自己在接入 vditor 编辑器是的一些应用总结,如果您还有什么更高级的定制玩法,可留言。