SimpleMDE加上文件上传操作

1,092 阅读3分钟

在我们编辑模板通常有两种方式

  • 富文本编辑器
  • markdown SimpleMDE是一个简单,可嵌入且美觀的JS markdown编辑器,除了常规的使用之外,看能不能结合使用场景扩展一下。

我们可以看到掘金的markdown编辑器支持图片拖拽上传, 完成过后上传到了自家的云存储空间,并且生成链接地址自动填写了上去。 是不是十分的方便,下面我们结合一下SimpleMDE来实现一个同样的功能效果。

技术栈选用的uni-app

依赖

"dependencies": {
    "font-awesome": "^4.7.0",
    "github-markdown-css": "^4.0.0",
    "marked": "^2.0.0",
    "simplemde": "^1.11.2"
},

实现思路,建议抽成组件

先看看template部分,很简单,准备一个textarea标签就好啦。
<template>
  <view class="simple-mde" :class="classes">
    <textarea ref="mde"></textarea>
  </view>
</template>
注意要在我们的dom挂载后再实例化我们的SimpleMDE
this.mde = new SimpleMDE({
  ...config,	//可以理解为父组件传进来配置
  initialValue: this.value,	//编辑器框里的内容
  element: this.$refs.mde.$el.querySelector('textarea'),	//el
})
可能el的获取方式有点奇怪,那是因为uni-app编译时会把textarea再包装一层,所以挂载el时要保证是浏览器的textarea标签

来看看我们引用的效果,样式可以根据自己的喜好随意搭配。

可以看到虽然我们没到找对应的drop事件回调,但是SimpleMDE提供了一个可点击load图片的image icon,只是load的是一个空链接,现在我们要做的事就是把我们要使用的图片上传到自己的云存储空间和展示出来。

找下SimpleMDE的源代码,发现点击图片的事件在这里。

/**
 * Action for drawing an img.
 */
function drawImage(editor) {
	var cm = editor.codemirror;
	var stat = getState(cm);
	var options = editor.options;
	var url = "http://";
	if(options.promptURLs) {
		url = prompt(options.promptTexts.image);
		if(!url) {
			return false;
		}
	}
	_replaceSelection(cm, stat.image, options.insertTexts.image, url);
}

来相应的改造一下

function drawImage (editor) {
	let { uploadCallBack } = editor.options
	uni.chooseImage({
	   sizeType: ['compressed'],
	   sourceType: ['album'],
	   success(res){
             console.log(res)
             typeof uploadCallBack == 'function' && uploadCallBack.call(editor, res)
           }
	})
}
通过源码分析editor其实就是当前构造函数的上下文,editor.options就是我们实例化传入的参数和他自己定义的参数,那我们就自定义一个uploadCallBack回调函数在我们的实例化的时候负责接收,同时加上我们的上传操作。(当前是uni-app的上传api,如果是其它技术栈可以定义一个<input type="file" accept="image/*"/>来协助上传)

接收我们定义的上传成功回调

this.mde = new SimpleMDE({
    initialValue: this.value,
    element: this.$refs.mde.$el.querySelector('textarea'),
    autoDownloadFontAwesome: false,
    promptURLs: true,
    uploadCallBack(res) {
      let editor = this
      uniCloud
        .uploadFile({
          filePath: res.tempFilePaths[0],
          cloudPath: `mm_${new Date().getTime()}.jpg`,
        })
        .then((res) => {
          let { fileID } = res
          return uniCloud.getTempFileURL({
            fileList: [fileID],
          })
        })
        .then((res) => {
          let { download_url } = res.fileList[0]
          editor.options.promptTexts['image'] = download_url
          editor.createImageUrl(editor)
        })
    },
  })
把上传的图片存入我们的云存储空间,也可以根据自身的文件服务器执行上传操作,最后把上传成功的有效地址重新赋值editor.options.promptTexts['image'] = download_url

createImageUrl哪来的?

SimpleMDE.prototype.createImageUrl = function(editor){
	var cm = editor.codemirror;
	var stat = getState(cm);
	var options = editor.options;
	var url = "http://";
	if(options.promptURLs) {
		url = options.promptTexts.image;
		if(!url) {
			return false;
		}
	}
	_replaceSelection(cm, stat.image, options.insertTexts.image, url);
}
其实就是我们原来替换的drawImage逻辑,只不过再次执行的时候url = options.promptTexts.image的时候已经不再是一个空链接,而是我们刚刚上传到服务器的真实url。(注意:此时的promptURLs:true是必须的,相关解释可以看:)

github.com/sparksuite/…

再来看看效果

是不是很舒坦?此时就能快乐的编辑图文markdown啦。

此时修改了依赖包源码、下次再安装时被覆盖了咋办?

不用担心,还是有很多方案的,详情可参考 segmentfault.com/q/101000002…

代码地址:github.com/wumaimai/co…