「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」
掘金新版的富文本采用的是字节跳动开源的富文本插件 ByteMD
公司项目中的富文本编辑器一直采用的是vue-quill-editor, 大体功能ok,主要是样式过于丑陋,在不断的需求要求中,渐渐无法满足当前的项目整体情况了,在掘金写文章的页面里,了解到了这款富文本插件 ByteMD
代码
html
在vue组件中的
<Editor class="byte-editor"
:locale="zhHans"
:value="value"
:plugins="plugins"
@change="handleChange"
:uploadImages="(files) => uploadImages(files)" />
复制代码
属性 | 描述 |
---|---|
zhHans | 中文依赖包 |
value | 组件双向绑定需要在data声明的值 |
plugins | 组件需要扩展的插件集合 |
handleChange | value发生改变的方法回调,我们可以在这里做一些文本上的处理 |
uploadImages | 图片上传,当有图片等资源时,我们可以上传到服务器后,转换成url预览,或者转出base64(不建议) |
模块引入
bytemd这款md编辑器,已经采用模块化的方式引入,相应的依赖我们需要单独引入
需要引入的插件有gfm、breaks、frontmatter、mediumZoom、highlight、math、mermaid、footnotes、zhHans、gfmLocale、mathLocale、mermaidLocale;
import 'bytemd/dist/index.min.css';
import { Editor } from '@bytemd/vue';
复制代码
主要方法
uploadImages
图片资源要么转出base64,要么上传到服务器中,这里我们推荐上传到服务器上。
图片转成base64后,相应的文本信息比较原图片大小,会变大,存储在数据库中,会影响到数据获取速度,体验差。
// 上传图片
async upload(files) {
const formData = new FormData();
formData.append('file', files);
// 这里替换成自己的上传地址,
const res = await axios.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return res.data;
},
// 上传完图片后拿到相应的服务器地址
async uploadImages(files) {
const imgs = [];
for (const file of files) {
const key = await this.upload(file);
imgs.push({
title: key.name,
url: key.url,
});
}
return imgs;
},
复制代码
我们通过异步上传图片后,拿到相应的服务器地址url,返回整个img的数组集合,这样在富文本中,可以正常的进行图片预览了;
我们将value传入后端,保存在数据库中。
升华
html转md
我复制文本的时候,在富文本里始终是无格式的text,但是复制到掘金的富文本就是带格式的markdown,
然后我把文章复制到typora
里去,也是带有格式的,只不过格式有细微错误;应该是markdown语法的问题
纳闷之后,我猜想应该是掘金在复制文本的时候,做了markdown格式转换;
打开控制台
在Network可以看到,当复制文本的时候,会调用一下接口
原来在后台进行了html转markdown
但是我怎么转呢;于是又一顿百度,
问了后端同事,大都是不了解,只有从前端出发
在github找了一款html转markdown Turndown
import TurndownService from 'turndown';
文档里用的require,在这里用 import;
我们通过监听粘贴事件,来调用TurndownService方法;
这里我们对符合text/html文本的就可以转成markdown;
/**
* 粘贴
*/
async pasteTxt(ev) {
ev.preventDefault();
const data = ev.clipboardData.items;
for (let i = 0; i < data.length; i += 1) {
if ((data[i].kind === 'string') && (data[i].type.match('^text/html'))) {
// Drag data item is HTML
const h = await new Promise(t => data[i].getAsString(e => t(e)));
const param = {
text: h,
}
console.log('markdown', h)
const turndownService = new TurndownService()
this.value = turndownService.turndown(h)
}
}
},
复制代码
以上就是我在vue中使用byteMd编辑器的过程
思考:
对于上传图片,我们是直接放在服务器中,当文本编辑的时候,如何删除该图片的时候,删除相应的服务器图片呢?