欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于vue-simplemde實(shí)現(xiàn)圖片拖拽、粘貼功能

 更新時(shí)間:2018年04月12日 14:00:28   作者:BlackHole1  
這篇文章主要介紹了基于vue-simplemde實(shí)現(xiàn)圖片拖拽、粘貼功能,需要的朋友可以參考下

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

但是這個(gè) vue-simplemde 不支持圖片拖拽上傳、粘貼上傳,也不能說(shuō)是因?yàn)檫@個(gè) vue-simplemde ,因?yàn)?vue-simplemde 只是對(duì) simplemde 的基礎(chǔ)上封裝成一個(gè)Vue插件。所以最后還是由于 simplemde 沒(méi)有提供相關(guān)的功能,但是為了用戶體驗(yàn)考慮,這個(gè)功能時(shí)必要的,除非不使用markdown編輯器。而去使用富文本編輯器,那樣的話,項(xiàng)目很多的代碼都要進(jìn)行更改。所以就在網(wǎng)上查了文章,及在github上查了一些代碼。下面將進(jìn)行分析

拖拽

拖拽的API核心是 drop 這個(gè)事件,就是當(dāng)我們從桌面拖動(dòng)一個(gè)文件到瀏覽器里時(shí),松開的時(shí)候,而觸發(fā)的事件名。

我們都知道,你隨便拖動(dòng)一個(gè)圖片到瀏覽器里,會(huì)直接打開這個(gè)圖片,這是因?yàn)闉g覽器默認(rèn)你拖動(dòng)文件到瀏覽器里時(shí),將打開這個(gè)文件,所以,我們需要阻止原生的操作。

我們現(xiàn)在先寫一段代碼,讓其屏蔽掉默認(rèn)事件

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

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

現(xiàn)在我們拖拽文件到這個(gè)編輯框,然后松掉,不會(huì)出現(xiàn)任何反應(yīng)。如果在編輯框之外的地方,還是會(huì)繼續(xù)觸發(fā)默認(rèn)事件。

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

// 假設(shè)頁(yè)面一共有三個(gè)編輯窗口,所以需要循環(huán)監(jiān)聽事件
[ this.$refs.simplemde1,
 this.$refs.simplemde2,
 this.$refs.simplemde3
].map(({simplemde}) => {
 simplemde.codemirror.on('drop', (editor, e) => {
 if (!(e.dataTransfer && e.dataTransfer.files)) {
  // 彈窗說(shuō)明,此瀏覽器不支持此操作
  return
 }

 let dataList = e.dataTransfer.files
 let imageFiles = [] // 要上傳的文件實(shí)例數(shù)組

 // 循環(huán),是因?yàn)榭赡軙?huì)同時(shí)拖動(dòng)幾個(gè)圖片文件
 for (let i = 0; i < dataList.length; i++) {
 // 如果不是圖片,則彈窗警告 僅支持拖拽圖片文件
  if (dataList[i].type.indexOf('image') === -1) {
  // 下面的continue,作用是,如果用戶同時(shí)拖動(dòng)2個(gè)圖片和一個(gè)文檔,那么文檔不給于上傳,圖片照常上傳。
  continue
  }
  imageFiles.push(dataList[i]) // 先把當(dāng)前的文件push進(jìn)數(shù)組里,等f(wàn)or循環(huán)結(jié)束之后,統(tǒng)一上傳。
 }
 // uploadImagesFile方法是上傳圖片的方法
 // simplemde.codemirror的作用是用于區(qū)分當(dāng)前的圖片上傳是處于哪個(gè)編輯框
 this.uploadImagesFile(simplemde.codemirror, imageFiles)
 // 因?yàn)橐呀?jīng)有了下面這段代碼,所以上面的屏蔽默認(rèn)事件代碼就不用寫了
 e.preventDefault()
 })
})

詐一看,代碼好像有點(diǎn)多,那是因?yàn)樽⑨尩脑颍旅媸菦](méi)有注釋的代碼。你可以根據(jù)下面的代碼,有自己的見(jiàn)解和理解:

[ 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 方法,這個(gè)不像上面一樣,粘貼不需要禁止默認(rèn)事件,因?yàn)槲覀兛梢钥吹?,你?fù)制一個(gè)圖片,到瀏覽器里按下 ctrl+v 的時(shí)候,是不會(huì)發(fā)生任何變化的,所以沒(méi)用必要禁止默認(rèn)事件。

下面是代碼:

simplemde.codemirror.on('paste', (editor, e) => { // 粘貼圖片的觸發(fā)函數(shù)
 if (!(e.clipboardData && e.clipboardData.items)) {
 // 彈窗說(shuō)明,此瀏覽器不支持此操作
 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) {
 // 彈窗說(shuō)明,只能粘貼圖片
 }
})

之所以這里寫上 try...catch 方法,是因?yàn)槿绻阏迟N的時(shí)候,如果是一個(gè)文件, items 將是空的,而在下面的if循環(huán)里,使用 dataList[0].kind 。也就是 e.clipboardData.items[0].kind 。當(dāng) item 為空時(shí),還去訪問(wèn)一個(gè)不存的 kind 屬性時(shí),就會(huì)報(bào)錯(cuò)了。所以這里需要使用 try...catch 方法進(jìn)行判斷。

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

if 里的上傳圖片,不一樣的地方是 [dataList[0].getAsFile()] ,因?yàn)闉榱私y(tǒng)一格式,方便 uploadImagesFile 函數(shù)進(jìn)行處理,我加上了 [] ,使之成為數(shù)組。 dataList[0].getAsFile() 就是獲取文件實(shí)例了。

上傳

上傳就有一點(diǎn)麻煩了:

uploadImagesFile (simplemde, files) {
 // 把每個(gè)文件實(shí)例使用FormData進(jìn)行包裝一下,然后返回一個(gè)數(shù)組
 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)
 }
 }

 // 服務(wù)端返回的格式是{state: Boolean, data: String}
 // state為false時(shí),data就是返回的錯(cuò)誤信息
 // state為true時(shí),data是圖片上傳后url地址,這個(gè)地址是針對(duì)網(wǎng)站的絕對(duì)路徑。如下:
 // /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的錯(cuò)誤信息
   continue
  }
  let url = `![](${location.origin + data})` // 拼接成markdown語(yǔ)法
  let content = simplemde.getValue()
  simplemde.setValue(content + url + '\n') // 和編輯框之前的內(nèi)容進(jìn)行拼接
  }
 }))
}

因?yàn)槲沂前?axiox 封裝成vue插件來(lái)使用,這樣會(huì)導(dǎo)致, this.$http 是實(shí)例化后的,而不是他本身。 axios 維護(hù)者說(shuō)的解決方案是,重新引入 axios 包,來(lái)使用。但是我覺(jué)得沒(méi)有必要。 axios.all 內(nèi)部是 Promise.all 。 axios.spread 實(shí)現(xiàn)代碼比較少,就直接拿過(guò)來(lái),重新賦值給 axios 就好了

所以上面有段代碼是

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

把這段代碼翻譯一下就是

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

關(guān)于這個(gè)問(wèn)題,請(qǐng)看下官方的解釋:axios-all-is-not-a-function-inside-vue-component 。也可以看下 axios 的代碼: axios.js#L45-L48

這個(gè)問(wèn)題,暫時(shí)就不深究了,我們回到剛剛的話題上。

上面我說(shuō)到當(dāng)state為true時(shí),data是文件相對(duì)于網(wǎng)站的絕對(duì)路徑,如: /static/upload/2cfd6a50-3d30-11e8-b351-0d25ce9162a3.png

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

相關(guān)文章

  • 淺析vue.js數(shù)組的變異方法

    淺析vue.js數(shù)組的變異方法

    本篇文章給大家分享了vue.js數(shù)組的變異方法的相關(guān)內(nèi)容,有興趣的朋友跟著學(xué)習(xí)參考下。
    2018-06-06
  • Vue2的路由和異步請(qǐng)求方式

    Vue2的路由和異步請(qǐng)求方式

    這篇文章主要介紹了Vue2的路由和異步請(qǐng)求方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Vue插件使用方法詳情分享

    Vue插件使用方法詳情分享

    這篇文章主要介紹了Vue插件使用方法詳情分享,使用插件之前顯示定義,下文通過(guò)js插件定義展開詳細(xì)文章介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • vue+express生成token方式

    vue+express生成token方式

    這篇文章主要介紹了vue+express生成token方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • vue如何引用其他組件(css和js)

    vue如何引用其他組件(css和js)

    本篇文章主要介紹了vue如何引用其他組件(css和js) ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • vue的keep-alive中使用EventBus的方法

    vue的keep-alive中使用EventBus的方法

    keep-alive是Vue提供的一個(gè)抽象組件,用來(lái)對(duì)組件進(jìn)行緩存,從而節(jié)省性能,由于是一個(gè)抽象組件,所以在頁(yè)面渲染完畢后不會(huì)被渲染成一個(gè)DOM元素。這篇文章主要介紹了vue的keep-alive中使用EventBus的方法,需要的朋友可以參考下
    2019-04-04
  • npm install卡在“sill idealTree buildDeps“問(wèn)題的兩種解決方法

    npm install卡在“sill idealTree buildDeps“問(wèn)題的兩種解

    本文主要介紹了npm install卡在“sill idealTree buildDeps“問(wèn)題的兩種解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • 使用 JSON.stringify() 列化一個(gè)Error

    使用 JSON.stringify() 列化一個(gè)Error

    這篇文章主要介紹了使用 JSON.stringify() 列化一個(gè)Error,需要的朋友可以參考下
    2023-10-10
  • vue 中常見(jiàn)的時(shí)間格式轉(zhuǎn)換

    vue 中常見(jiàn)的時(shí)間格式轉(zhuǎn)換

    這篇文章主要介紹了vue 中常見(jiàn)的時(shí)間格式轉(zhuǎn)換,需要的朋友可以參考下
    2022-05-05
  • vue實(shí)現(xiàn)接口封裝的實(shí)現(xiàn)示例

    vue實(shí)現(xiàn)接口封裝的實(shí)現(xiàn)示例

    本文主要介紹了vue實(shí)現(xiàn)接口封裝的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11

最新評(píng)論