• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

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

    來源:懂視網 責編:小采 時間:2020-11-27 22:16:54
    文檔

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

    基于vue-simplemde實現圖片拖拽、粘貼功能:項目使用的是vue框架,需要一個markdown的編輯框,就在npm上找了一下,發現simplemde挺不錯的,由于我比較懶,就順便在npm又搜了一下,找到了vue-simplemde這個 package ,那就開始使用它吧。 但是這個 vue-simplemde 不支持圖片拖拽上傳、粘貼
    推薦度:
    導讀基于vue-simplemde實現圖片拖拽、粘貼功能:項目使用的是vue框架,需要一個markdown的編輯框,就在npm上找了一下,發現simplemde挺不錯的,由于我比較懶,就順便在npm又搜了一下,找到了vue-simplemde這個 package ,那就開始使用它吧。 但是這個 vue-simplemde 不支持圖片拖拽上傳、粘貼

    項目使用的是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地址。

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

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

    基于vue-simplemde實現圖片拖拽、粘貼功能:項目使用的是vue框架,需要一個markdown的編輯框,就在npm上找了一下,發現simplemde挺不錯的,由于我比較懶,就順便在npm又搜了一下,找到了vue-simplemde這個 package ,那就開始使用它吧。 但是這個 vue-simplemde 不支持圖片拖拽上傳、粘貼
    推薦度:
    標簽: 圖片 功能 VUE
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 亚洲国产精品久久久久婷婷软件| 国产亚洲精品线观看动态图| 国产精品高清免费网站| 亚洲精品成人片在线观看精品字幕 | 日韩精品区一区二区三VR| 国产香蕉国产精品偷在线| 精品久久久久久无码中文野结衣| 国产成人精品高清在线观看93| 亚洲国产精品成人久久蜜臀| 国产精品五月天强力打造| 国产AV午夜精品一区二区三区 | 无码国产乱人伦偷精品视频| 久久精品视频91| 国产日韩精品无码区免费专区国产| 国内精品免费在线观看| 99热门精品一区二区三区无码| 尤物国精品午夜福利视频| 日韩精品一区二区三区在线观看| 国内精品久久久久国产盗摄 | 久久国产精品99精品国产987| 久久国产精品99精品国产| 无码欧精品亚洲日韩一区| 在线精品国产一区二区三区| 青青热久久国产久精品| 国产精品极品| 99精品福利国产在线| 欧美精品/日韩精品/国产精品| 国产成人精品手机在线观看| 久久精品中文字幕无码绿巨人| 无码精品人妻一区二区三区免费看 | 999国产精品色在线播放| 精品999在线| 久久亚洲精品中文字幕三区| 精品久久久久久久久中文字幕| 国产精品视频一区二区三区| 国内精品免费视频精选在线观看| 久久精品国产99国产电影网| 国产精品久久自在自线观看| 国产成人精品免费视频大全麻豆| 91麻豆国产福利精品| 99免费精品视频|