亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

基于vue-simplemde實現圖片拖拽、粘貼功能

2019-11-19 14:01:42
字體:
來源:轉載
供稿:網友

項目使用的是vue框架,需要一個markdown的編輯框,就在npm上找了一下,發現simplemde挺不錯的,由于我比較懶,就順便在npm又搜了一下,找到了vue-simplemde這個 package ,那就開始使用它吧。

但是這個 vue-simplemde 不支持圖片拖拽上傳、粘貼上傳,也不能說是因為這個 vue-simplemde ,因為 vue-simplemde 只是對 simplemde 的基礎上封裝成一個Vue插件。所以最后還是由于 simplemde 沒有提供相關的功能,但是為了用戶體驗考慮,這個功能時必要的,除非不使用markdown編輯器。而去使用富文本編輯器,那樣的話,項目很多的代碼都要進行更改。所以就在網上查了文章,及在github上查了一些代碼。下面將進行分析

拖拽

拖拽的API核心是 drop 這個事件,就是當我們從桌面拖動一個文件到瀏覽器里時,松開的時候,而觸發的事件名。

我們都知道,你隨便拖動一個圖片到瀏覽器里,會直接打開這個圖片,這是因為瀏覽器默認你拖動文件到瀏覽器里時,將打開這個文件,所以,我們需要阻止原生的操作。

我們現在先寫一段代碼,讓其屏蔽掉默認事件

window.addEventListener("drop", e => { e = e || event if (e.target.className === 'CodeMirror-scroll') { // 如果進入到編輯器的話,將阻止默認事件 e.preventDefault() }}, false)

CodeMirror-scroll 這個Class就是 simplemde 編輯框的Class名稱。

現在我們拖拽文件到這個編輯框,然后松掉,不會出現任何反應。如果在編輯框之外的地方,還是會繼續觸發默認事件。

下面就是獲取 simplemde 方法,給他 drop 事件處理方法。

// 假設頁面一共有三個編輯窗口,所以需要循環監聽事件[ this.$refs.simplemde1, this.$refs.simplemde2, this.$refs.simplemde3].map(({simplemde}) => { simplemde.codemirror.on('drop', (editor, e) => { if (!(e.dataTransfer && e.dataTransfer.files)) {  // 彈窗說明,此瀏覽器不支持此操作  return } let dataList = e.dataTransfer.files let imageFiles = [] // 要上傳的文件實例數組 // 循環,是因為可能會同時拖動幾個圖片文件 for (let i = 0; i < dataList.length; i++) { // 如果不是圖片,則彈窗警告 僅支持拖拽圖片文件  if (dataList[i].type.indexOf('image') === -1) {  // 下面的continue,作用是,如果用戶同時拖動2個圖片和一個文檔,那么文檔不給于上傳,圖片照常上傳。  continue  }  imageFiles.push(dataList[i]) // 先把當前的文件push進數組里,等for循環結束之后,統一上傳。 } // uploadImagesFile方法是上傳圖片的方法 // simplemde.codemirror的作用是用于區分當前的圖片上傳是處于哪個編輯框 this.uploadImagesFile(simplemde.codemirror, imageFiles) // 因為已經有了下面這段代碼,所以上面的屏蔽默認事件代碼就不用寫了 e.preventDefault() })})

詐一看,代碼好像有點多,那是因為注釋的原因,下面是沒有注釋的代碼。你可以根據下面的代碼,有自己的見解和理解:

[ this.$refs.simplemde1, this.$refs.simplemde2, this.$refs.simplemde3].map(({simplemde}) => { simplemde.codemirror.on('drop', (editor, e) => { if (!(e.dataTransfer && e.dataTransfer.files)) {  return } let dataList = e.dataTransfer.files let imageFiles = [] for (let i = 0; i < dataList.length; i++) {  if (dataList[i].type.indexOf('image') === -1) {  continue  }  imageFiles.push(dataList[i]) } this.uploadImagesFile(simplemde.codemirror, imageFiles) e.preventDefault() })})

粘貼

粘貼的API是 paste 方法,這個不像上面一樣,粘貼不需要禁止默認事件,因為我們可以看到,你復制一個圖片,到瀏覽器里按下 ctrl+v 的時候,是不會發生任何變化的,所以沒用必要禁止默認事件。

下面是代碼:

simplemde.codemirror.on('paste', (editor, e) => { // 粘貼圖片的觸發函數 if (!(e.clipboardData && e.clipboardData.items)) { // 彈窗說明,此瀏覽器不支持此操作 return } try { let dataList = e.clipboardData.items if (dataList[0].kind === 'file' && dataList[0].getAsFile().type.indexOf('image') !== -1) {  this.uploadImagesFile(simplemde.codemirror, [dataList[0].getAsFile()]) } } catch (e) { // 彈窗說明,只能粘貼圖片 }})

之所以這里寫上 try...catch 方法,是因為如果你粘貼的時候,如果是一個文件, items 將是空的,而在下面的if循環里,使用 dataList[0].kind 。也就是 e.clipboardData.items[0].kind 。當 item 為空時,還去訪問一個不存的 kind 屬性時,就會報錯了。所以這里需要使用 try...catch 方法進行判斷。

dataList[0].getAsFile().type.indexOf('image') !== -1 這個句話是判斷,粘貼的東西確認是圖片,而不是其他東西。

if 里的上傳圖片,不一樣的地方是 [dataList[0].getAsFile()] ,因為為了統一格式,方便 uploadImagesFile 函數進行處理,我加上了 [] ,使之成為數組。 dataList[0].getAsFile() 就是獲取文件實例了。

上傳

上傳就有一點麻煩了:

uploadImagesFile (simplemde, files) { // 把每個文件實例使用FormData進行包裝一下,然后返回一個數組 let params = files.map(file => { let param = new FormData() param.append('file', file, file.name) return param }) let makeRequest = params => { return this.$http.post('/Api/upload', params) } let requests = params.map(makeRequest) this.$http.spread = callback => { return arr => {  return callback.apply(null, arr) } } // 服務端返回的格式是{state: Boolean, data: String} // state為false時,data就是返回的錯誤信息 // state為true時,data是圖片上傳后url地址,這個地址是針對網站的絕對路徑。如下: // /static/upload/2cfd6a50-3d30-11e8-b351-0d25ce9162a3.png Promise.all(requests) .then(this.$http.spread((...resps) => {  for (let i = 0; i < resps.length; i++) {  let {state, data} = resps[i].data  if (!state) {   // 彈窗顯示data的錯誤信息   continue  }  let url = `![](${location.origin + data})` // 拼接成markdown語法  let content = simplemde.getValue()  simplemde.setValue(content + url + '/n') // 和編輯框之前的內容進行拼接  } }))}

因為我是把 axiox 封裝成vue插件來使用,這樣會導致, this.$http 是實例化后的,而不是他本身。 axios 維護者說的解決方案是,重新引入 axios 包,來使用。但是我覺得沒有必要。 axios.all 內部是 Promise.all 。 axios.spread 實現代碼比較少,就直接拿過來,重新賦值給 axios 就好了

所以上面有段代碼是

Promise.all(requests) .then(this.$http.spread((...resps) => { // code })

把這段代碼翻譯一下就是

axios.all(requests) .then(axios.spread((...resps) => { // code })

關于這個問題,請看下官方的解釋:axios-all-is-not-a-function-inside-vue-component 。也可以看下 axios 的代碼: axios.js#L45-L48

這個問題,暫時就不深究了,我們回到剛剛的話題上。

上面我說到當state為true時,data是文件相對于網站的絕對路徑,如: /static/upload/2cfd6a50-3d30-11e8-b351-0d25ce9162a3.png

如果我們需要進行拼接一下,所以就有了 ![](${location.origin + data}) 這段代碼進行拼接。最后的兩行是獲取指的獲取之前的內容,然后在追加url地址。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩专区在线观看| 日韩电影大全免费观看2023年上| 欧美激情第1页| 中文字幕成人精品久久不卡| 伊人久久久久久久久久| 91精品久久久久久久久青青| 日韩av在线免费| 国产午夜精品一区理论片飘花| 久久午夜a级毛片| 精品日本美女福利在线观看| 亚洲第一中文字幕| 欧美一级高清免费播放| 欧美成人午夜剧场免费观看| 久久最新资源网| 色狠狠久久aa北条麻妃| 久久综合国产精品台湾中文娱乐网| 亚洲欧美成人在线| 久久精品美女视频网站| 日韩欧美在线免费观看| 91福利视频网| 日韩成人中文电影| 欧美人在线视频| 亚洲国产毛片完整版| 国产亚洲欧洲高清一区| 亚洲精品中文字幕av| 97超碰色婷婷| 日韩欧美精品网站| 欧美国产乱视频| 久久久亚洲影院| 国产精品九九久久久久久久| 久久亚洲私人国产精品va| 精品国产精品三级精品av网址| 日韩亚洲精品电影| 久久艳片www.17c.com| 欧美成人一区在线| 精品国产精品三级精品av网址| 欧美成年人视频网站| 欧美激情喷水视频| 欧美理论电影在线观看| 亚洲女成人图区| 国产91在线播放精品91| 久久久www成人免费精品张筱雨| 欧洲成人性视频| 91在线网站视频| 国产精品久久久久久久美男| 国产国产精品人在线视| 色偷偷888欧美精品久久久| 欧美高清无遮挡| 91精品成人久久| 亚洲最大中文字幕| 岛国av一区二区三区| 日韩福利视频在线观看| 自拍偷拍亚洲区| 亚洲色图25p| 韩国精品美女www爽爽爽视频| 国产精品99免视看9| 亚洲va欧美va国产综合剧情| 国产精品男女猛烈高潮激情| 国精产品一区一区三区有限在线| 91网站在线看| 国产欧美一区二区三区久久人妖| 国产91精品最新在线播放| 91色琪琪电影亚洲精品久久| 成人中文字幕+乱码+中文字幕| 亚洲视频在线免费观看| 国产丝袜视频一区| 亚洲福利在线播放| 久久精品国产96久久久香蕉| 亚洲人免费视频| 日韩成人在线电影网| 国产精品入口夜色视频大尺度| 日韩精品高清在线| 欧美激情国产精品| 91探花福利精品国产自产在线| 中文字幕欧美在线| 日韩亚洲欧美中文高清在线| 日韩国产精品视频| 亚洲视频欧洲视频| 精品中文字幕乱| 久久久久99精品久久久久| 欧美剧在线观看| 日韩精品福利在线| 成人国产在线视频| 亚洲一区二区自拍| 日韩在线视频免费观看| 国产精品久久久亚洲| 51久久精品夜色国产麻豆| 亚洲性线免费观看视频成熟| 亚洲香蕉伊综合在人在线视看| 亚洲色图18p| 亚洲a在线播放| 欧美精品在线免费| 尤物yw午夜国产精品视频明星| 亚洲高清久久久久久| 久久久久久有精品国产| 日韩在线免费观看视频| 亚洲日韩第一页| 国产精品久久久久久久久久免费| 性色av香蕉一区二区| 中文字幕日韩免费视频| 欧美激情2020午夜免费观看| 精品福利在线观看| 亚洲r级在线观看| 亚洲精品97久久| 国产视频精品xxxx| 中文字幕亚洲情99在线| 亚洲精品色婷婷福利天堂| 中文在线资源观看视频网站免费不卡| 日本电影亚洲天堂| 欧美精品第一页在线播放| 秋霞成人午夜鲁丝一区二区三区| 日韩精品免费看| 久久久国产一区| 欧美精品一区二区免费| 亚洲天堂久久av| 全亚洲最色的网站在线观看| 日韩在线激情视频| 日韩小视频在线观看| 久久久久久网站| 欧美激情在线播放| 国产精品第2页| 国产精品永久免费| 日韩在线欧美在线| 亚洲美女视频网| 欧美成人一二三| 亚洲天堂男人天堂| 欧美极品少妇xxxxⅹ免费视频| 欧美富婆性猛交| 国产成人精品日本亚洲| 欧美亚洲伦理www| 欧美不卡视频一区发布| 国产视频丨精品|在线观看| 97av在线视频| 欧美午夜片欧美片在线观看| 欧美巨大黑人极品精男| 亚洲精选在线观看| 91在线网站视频| 欧美性xxxxx极品娇小| 欧美日韩性生活视频| 国产日韩在线免费| 亚洲黄页网在线观看| 国产一区二区视频在线观看| 最近2019年手机中文字幕| 欧美中文在线观看| 国产精品一区二区久久国产| 亚洲aⅴ日韩av电影在线观看| 欧美色另类天堂2015| 国产在线高清精品| 大桥未久av一区二区三区| 国产精品久久久久久亚洲调教| 欧美激情久久久久久| 日韩在线观看网站| 国产精品久久久久久久9999| 日韩精品视频在线观看免费| 成人av电影天堂| 欧美激情国产高清| 亚洲国产精品va在线看黑人动漫| 成人精品视频在线| 欧美电影免费观看大全| 91九色精品视频| 国自产精品手机在线观看视频| 韩曰欧美视频免费观看| 91免费视频国产| 国产精品视频一|