pasteImg

by imys

HTML

<div id="app">
  <div contenteditable class="paste-accept" ref="accept" @paste="onPaste"></div>
  <textarea @keydown="onKeydown" ref="input" v-model="pasteImg"></textarea>
  <div v-if="pasteImg"><img :src="pasteImg"></div>
</div>

CSS

.paste-accept {
  position: fixed;
  top: -100px;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
}

textarea {
  width: 500px;
  height: 100px;
  border: 1px solid #ddd;
  overflow: hidden;
}

JavaScript

// paste.js 对 safari 图片粘贴兼容的实现
// 注:contentediable 图片粘贴在 safari 不存在兼容问题,只是针对 textarea
// 原理:通过 Keydown(粘贴是在keyup后才发生) 监听 Ctrl+v,设置隐藏的 contenteditable 元素获取焦点来接受图片复制
new Vue({
	el: '#app',
  data: {
  	pasteImg: ''
  },
  methods: {
  	onKeydown(e) {
      // hook Ctrl+v
    	if(e.ctrlKey && e.keyCode === 86) {
        console.log('hook Ctrl+v')
      	this.$refs.accept.focus()
      }
    },
  	onPaste(e) {
    	const evt = e.originalEvent || e
      const clipboard = evt.clipboardData
      
      if (clipboard.items) {
      	// 正常处理
      	const item = clipboard.items[0]
        const url = window.URL.createObjectURL(item.getAsFile())
        this.showPaste(url)
        return
      }
      // 以下用于兼容 safari,safari 会直接生成一个 img 元素
    	const img = e.target.querySelector('img')
      if(!img) return
      this.showPaste(img.src)
      img.remove()
    },
    showPaste(url) {
      this.pasteImg = url
      this.$nextTick(() => {
      	this.$refs.input.focus()
      })
    }
  }
})