2022-06-06 12:51:15 +08:00

107 lines
2.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="custom-textarea"
ref="textareaRef"
@focus="handleFocus"
@blur="handleBlur"
@input="handleInput()"
v-html="text"
></div>
</template>
<script lang="ts">
import { defineComponent, onUnmounted, ref, watch } from 'vue'
import { pasteCustomClipboardString, pasteExcelClipboardString } from '@/utils/clipboard'
export default defineComponent({
name: 'custom-textarea',
emits: ['updateValue', 'insertExcelData'],
props: {
value: {
type: String,
default: '',
},
contenteditable: {
type: [Boolean, String],
default: false,
},
},
setup(props, { emit }) {
const textareaRef = ref<HTMLElement>()
const text = ref('')
const isFocus = ref(false)
// 自定义v-modal同步数据
// 当文本框聚焦时,不执行数据同步
watch(() => props.value, () => {
if (isFocus.value) return
text.value = props.value
if (textareaRef.value) textareaRef.value.innerHTML = props.value
}, { immediate: true })
const handleInput = () => {
if (!textareaRef.value) return
const text = textareaRef.value.innerHTML
emit('updateValue', text)
}
// 聚焦时更新焦点标记,并监听粘贴事件
const handleFocus = () => {
isFocus.value = true
if (!textareaRef.value) return
textareaRef.value.onpaste = (e: ClipboardEvent) => {
e.preventDefault()
if (!e.clipboardData) return
const clipboardDataFirstItem = e.clipboardData.items[0]
if (clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {
clipboardDataFirstItem.getAsString(text => {
const clipboardData = pasteCustomClipboardString(text)
if (typeof clipboardData === 'object') return
const excelData = pasteExcelClipboardString(text)
if (excelData) {
emit('insertExcelData', excelData)
if (textareaRef.value) textareaRef.value.innerHTML = excelData[0][0]
return
}
emit('updateValue', text)
document.execCommand('insertText', false, text)
})
}
}
}
// 失焦时更新焦点标记,清除粘贴事件监听
const handleBlur = () => {
isFocus.value = false
if (textareaRef.value) textareaRef.value.onpaste = null
}
// 清除粘贴事件监听
onUnmounted(() => {
if (textareaRef.value) textareaRef.value.onpaste = null
})
return {
textareaRef,
handleFocus,
handleInput,
handleBlur,
text,
}
},
})
</script>
<style lang="scss" scoped>
.custom-textarea {
border: 0;
outline: 0;
-webkit-user-modify: read-write-plaintext-only;
-moz-user-modify: read-write-plaintext-only;
}
</style>