亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue3+elementUI實(shí)現(xiàn)懸浮多行文本輸入框效果

 更新時(shí)間:2023年10月26日 14:01:41   作者:菜雞dede畫界面  
這篇文章主要為大家詳細(xì)介紹了vue3如何引用elementUI實(shí)現(xiàn)懸浮文本輸入框效果,以便實(shí)現(xiàn)多行文本輸入,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

一、組件功能描述

點(diǎn)擊常規(guī)輸入框 可以調(diào)出懸浮大文本域輸入框,支持多行文本輸入、支持從excel復(fù)制粘貼輸入并自動(dòng)切分為符合參數(shù)的逗號(hào)拼接字符串。

組件圖例

二、組件參數(shù)說(shuō)明

1.props(屬性)

參數(shù)名參數(shù)類型必填默認(rèn)值說(shuō)明
inputPrefixString申請(qǐng)單號(hào):外部輸入框 提示文本
inputPlaceholderstring請(qǐng)輸入單號(hào)外部輸入框 占位文本Placeholder
popoverWidthnumber300如果需要結(jié)合 界面適應(yīng)寬度的話,配合hook useGetElementWidthByClassName(className),參數(shù)class 是對(duì)應(yīng)元素基坑的類名
showTextLengthnumber15基礎(chǔ)文本框展示的字符個(gè)數(shù)
useTextProcessbooleantrue開啟文本處理 , true : 判斷長(zhǎng)度限制 切割 \r \n 字符串 ,false :不做處理
overLengthnumber10多行文本框最大上限,默認(rèn)上限為 10個(gè)
textInputLengthnumber10多行文本框顯示行數(shù) 上限為 10個(gè)
inputInnerPlaceholderstring每行填寫一條申請(qǐng)單號(hào)懸浮輸入框 占位文本
modelValuestring自定義V-model 綁定變量

2.Emits(拋出事件)

事件名事件參數(shù)說(shuō)明
update:modelValuetextValue自定義V-model 拋出事件

3.Expose(對(duì)外暴露事件)

外部組件需要通過(guò) $refs 來(lái)進(jìn)行調(diào)用的方法

4.是否支持屬性透?jìng)?/p>

不支持屬性與事件透?jìng)髦烈蕾嚱M件

三、組件代碼

<template>
  <el-popover
    :visible="state.visible"
    placement="bottom-start"
    :width="props.popoverWidth"
  >
    <div>
      <el-input
        ref="inputTextAreaRef"
        v-model="textValue"
        type="textarea"
        :placeholder="inputInnerPlaceholder"
        resize="none"
        :autosize="{ minRows: props.textInputLength + 1, maxRows: props.textInputLength + 1 }"
        clearable
        class="textInputArea"
        @blur="blurInputTextArea"
        @input="showErrorTip = false"
        @clear="showErrorTip = false"
      />
      <div class="input-textarea-bottom-btn">
        <div>
          <p v-if="showErrorTip" class="over-length-error-tip">
            超出最大行數(shù)限制{{ props.overLength }}行
          </p>
        </div>
      </div>
    </div>
    <template #reference>
      <el-input
        ref="inputRef"
        v-model="omitText"
        class="base-input"
        :placeholder="props.inputPlaceholder"
        style="cursor: pointer"
        @focus="showLevitateWindow"
      >
        <template #prefix>
          {{ props.inputPrefix }}
        </template>
      </el-input>
    </template>
  </el-popover>
</template>
<script setup lang="ts">
import { computed } from 'vue'

const props = withDefaults(
  defineProps<{
    modelValue:string
    inputPrefix?: string
    inputPlaceholder?: string
    popoverWidth?: number
    showTextLength?:number
    useTextProcess?:boolean
    overLength?:number
    textInputLength?:number
    inputInnerPlaceholder?:string
    }>(),
  {
    inputPrefix: '申請(qǐng)單號(hào):', // 外部輸入框 提示文本
    inputPlaceholder: '請(qǐng)輸入單號(hào)', // 外部輸入框 占位文本
    inputInnerPlaceholder: '每行填寫一條申請(qǐng)單號(hào)', // 懸浮輸入框 占位文本
    popoverWidth: 300, // 如果需要結(jié)合 界面適應(yīng)寬度的話,配合hook useGetElementWidthByClassName(className),參數(shù)class 是對(duì)應(yīng)元素基坑的類名
    showTextLength: 15, // 基礎(chǔ)文本框展示的字符個(gè)數(shù)
    overLength: 10, // 多行文本框最大上限,默認(rèn)上限為 10個(gè)
    textInputLength: 10, // 多行文本框顯示行數(shù) 上限為 10個(gè)
    useTextProcess: true // 開啟文本處理 , 判斷長(zhǎng)度限制 切割 \r \n 字符串
  }
)

const emits = defineEmits(['update:modelValue'])

const inputTextAreaRef = ref<HTMLElement | null> (null)
const inputRef = ref<HTMLElement | null> (null)
const showErrorTip = ref<boolean> (false)
const state = reactive({
  visible: false
})

const omitText = computed(() => {
  return textValue.value.length > props.showTextLength ? textValue.value.substring(0, props.showTextLength) + '……' : textValue.value
})

const textValue = ref(props.modelValue)
watchEffect(() => {
  textValue.value = props.modelValue
})

// 聚焦的時(shí)候 展示懸浮輸入框
function showLevitateWindow () {
  if (state.visible) {
    inputTextAreaRef.value?.focus()
    return
  }
  // 處理數(shù)據(jù),如果包含  , 需要拆開
  const localValue = textValue.value
  if (localValue.indexOf(',') > -1) {
    textValue.value = localValue.split(',').join('\n')
    emits('update:modelValue', textValue.value)
  }
  state.visible = true
  nextTick(() => {
    inputTextAreaRef.value?.focus()
  })
}

// 懸浮輸入失去焦點(diǎn) 傳輸數(shù)據(jù)給父組件
function blurInputTextArea () {
  if (props.useTextProcess) {
    const { overLength, val } = textProcessing(textValue.value)
    // textValue.value = val
    if (!overLength) { // 沒(méi)有超長(zhǎng)的 傳遞給父組件
      console.log('emit的數(shù)據(jù)', val)
      emits('update:modelValue', val)
      state.visible = false
    } else {
      showErrorTip.value = true // 展示錯(cuò)誤信息
    }
  } else {
    emits('update:modelValue', textValue.value)
    state.visible = false
  }
}
// 文本處理方法,切割 \r \n 字符串
const textProcessing : (val: string) => { val:string, overLength:boolean } = (val) => {
  const splitText = val.split(/\r?\n/).filter(i => i !== '')
  const overLength = splitText.length > props.overLength // 最大長(zhǎng)度
  return {
    val: splitText.join(','),
    overLength
  }
}
</script>
<style scoped lang="scss">
.input-textarea-bottom-btn{
  margin-top: 5px;
  display: flex;
  justify-content: space-between;
  align-content: center;
  .over-length-error-tip{
    color:#f56c6c;
    font-size: 12px;
    line-height: 24px;
  }
}
/* 隱藏瀏覽器默認(rèn)滾動(dòng)條 */
.textInputArea ::-webkit-scrollbar {
  width: 6px; /* 寬度 */
  height: 6px; /* 高度 */
}

/* 滾動(dòng)條滑塊 */
.textInputArea ::-webkit-scrollbar-thumb {
  background: #969696; /* 滑塊顏色 */
  border-radius: 3px; /* 滑塊圓角 */
}

/* 滾動(dòng)條軌道 */
.textInputArea ::-webkit-scrollbar-track {
  background: #f0f0f0; /* 軌道顏色 */
  border-radius: 3px; /* 軌道圓角 */
}

/* 鼠標(biāo)懸停在滾動(dòng)條上時(shí)的滑塊樣式 */
.textInputArea ::-webkit-scrollbar-thumb:hover {
  background: #656565;
}
</style>

附帶 Hook 函數(shù)

import { ref, onMounted, onBeforeUnmount } from 'vue'
/**
 * @description 根據(jù)className 獲取懸浮輸入框的基礎(chǔ)輸入框?qū)挾?
 * @param className - 基礎(chǔ)元素類名 string,默認(rèn) levitateBaseInput
 * @param paddingWidth - 邊距寬度 number,默認(rèn) 12
 * */
export default function useGetElementWidthByClassName (className = 'levitateBaseInput', paddingWidth = 12) {
  const elementWidth = ref(0)
  function getElementsClientWidth () {
    setTimeout(() => {
      const ele = document.getElementsByClassName(className)
      if (ele[0]) {
        elementWidth.value = ele[0].clientWidth - paddingWidth
      } else elementWidth.value = 0
    }, 400)
  }
  onMounted(() => {
    window.addEventListener('resize', getElementsClientWidth)
    getElementsClientWidth()
  })
  onBeforeUnmount(() => {
    window.removeEventListener('resize', getElementsClientWidth)
  })
  return elementWidth
}

四、組件使用例子

<HomeSearchItem ref="inputElementRef" prop="MultiAccounts" class="levitateBaseInput">
  <levitate-multiple-input
    v-model="queryParams.MultiAccounts"
    :popover-width="levitateWidth"
    input-prefix="多賬戶查詢:"
    input-placeholder=""
    input-inner-placeholder="每行輸入一個(gè)賬戶,最多20行,Meta賬戶可不加act_前綴"
    :over-length="20"
  />
</HomeSearchItem>

const queryParams = reactive({
    MultiAccounts:''
})
const levitateWidth = useGetElementWidthByClassName()

五、其他注意事項(xiàng)

1、本組件主要是用于解決從Excel 復(fù)制粘貼多行文本,并需要單行截取的問(wèn)題。

2、props中的popoverWidth是用于設(shè)置彈出層的寬度,在搭配外層formItem使用時(shí)候,可以使用配套hook函數(shù)useGetElementWidthByClassName(默認(rèn)獲取類名為levitateBaseInput的元素的寬度,可以通過(guò)參數(shù)修改)獲取外層寬度使彈出層寬度匹配外層輸入框,否則使用固定寬度300。

3、組件設(shè)計(jì):在點(diǎn)擊外層輸入框的時(shí)候,當(dāng)懸浮框沒(méi)有展開的時(shí)候,則顯示懸浮框并自動(dòng)focus到大文本域輸入框(如果v-model的數(shù)據(jù)包含 , 則需要進(jìn)行拆分并加入\n 確??梢栽谖谋居蜉斎肟蛘7中姓故荆?,當(dāng)懸浮框是展開的狀態(tài)則默認(rèn)focus文本域輸入框防止失去焦點(diǎn)(再次點(diǎn)擊外層小輸入框的時(shí)候,防止丟失焦點(diǎn))。當(dāng)文本域失去焦點(diǎn)則進(jìn)行文本處理,見(jiàn)第四點(diǎn)。

/*
 <el-popover
  :visible="state.visible">
  …………………省略其他代碼…………………
  </el-popover>
*/  
// 聚焦的時(shí)候 展示懸浮輸入框
function showLevitateWindow () {
  if (state.visible) {
    inputTextAreaRef.value?.focus()
    return
  }
  // 處理數(shù)據(jù),如果包含  , 需要拆開, localValue  為v-model傳入數(shù)據(jù)的本地副本
  const localValue = textValue.value
  if (localValue.indexOf(',') > -1) {
    textValue.value = localValue.split(',').join('\n')
    emits('update:modelValue', textValue.value)
  }
  state.visible = true
  // 在懸浮輸入框展示后立刻聚焦
  nextTick(() => {
    inputTextAreaRef.value?.focus()
  })
}

4、有關(guān)文本處理的方法,props中的useTextProcess是文本處理配置,如果設(shè)置為true,即對(duì)輸入的多行文本進(jìn)行文本處理 切割 \r \n 字符串并返回切割后拼接  ,  后的字符串;如果是false則不對(duì)文本處理。會(huì)在懸浮框失去焦點(diǎn)的時(shí)候觸發(fā)blurInputTextArea 方法進(jìn)而在useTextProcess為true的情況下調(diào)用textProcessing 方法進(jìn)行處理。當(dāng)前版本在false的情況下不處理超長(zhǎng)情況。

在true的情況如果文本超出行數(shù)限制,則會(huì)將showErrorTip.value = true // 展示錯(cuò)誤信息,

// 懸浮輸入失去焦點(diǎn) 傳輸數(shù)據(jù)給父組件。
function blurInputTextArea () {
  if (props.useTextProcess) {
    const { overLength, val } = textProcessing(textValue.value)
    // textValue.value = val
    if (!overLength) { // 沒(méi)有超長(zhǎng)的 傳遞給父組件
      console.log('emit的數(shù)據(jù)', val)
      emits('update:modelValue', val)
      state.visible = false
    } else {
      showErrorTip.value = true // 展示錯(cuò)誤信息
    }
  } else {
    emits('update:modelValue', textValue.value)
    state.visible = false
  }
}
// 文本處理方法,切割 \r \n 字符串
const textProcessing : (val: string) => { val:string, overLength:boolean } = (val) => {
  const splitText = val.split(/\r?\n/).filter(i => i !== '')
  const overLength = splitText.length > props.overLength // 最大長(zhǎng)度
  return {
    val: splitText.join(','),
    overLength
  }
}

以上就是vue3+elementUI實(shí)現(xiàn)懸浮多行文本輸入框效果的詳細(xì)內(nèi)容,更多關(guān)于vue3 elementUI懸浮文本輸入框的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue3?源碼解讀之副作用函數(shù)與依賴收集

    Vue3?源碼解讀之副作用函數(shù)與依賴收集

    本文深入分析了副作用的實(shí)現(xiàn)以及執(zhí)行時(shí)機(jī),并詳細(xì)分析了用于存儲(chǔ)副作用函數(shù)的targetMap的數(shù)據(jù)結(jié)構(gòu)及其實(shí)現(xiàn)原理,還深入分析了依賴收集track函數(shù)以及派發(fā)更新 trigger 函數(shù)的實(shí)現(xiàn),需要的朋友可以參考下
    2022-08-08
  • VUE3安裝element?ui失敗的原因以及解決辦法

    VUE3安裝element?ui失敗的原因以及解決辦法

    這篇文章主要給大家介紹了關(guān)于VUE3安裝element?ui失敗的原因以及解決的相關(guān)資料,很多朋友升級(jí)使用Vue3了,但在安裝element?ui失敗出錯(cuò)了,這里給大家總結(jié)下,需要的朋友可以參考下
    2023-09-09
  • nuxt 服務(wù)器渲染動(dòng)態(tài)設(shè)置 title和seo關(guān)鍵字的操作

    nuxt 服務(wù)器渲染動(dòng)態(tài)設(shè)置 title和seo關(guān)鍵字的操作

    這篇文章主要介紹了nuxt 服務(wù)器渲染動(dòng)態(tài)設(shè)置 title和seo關(guān)鍵字的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • Vant的Tabbar標(biāo)簽欄引入自定義圖標(biāo)方式

    Vant的Tabbar標(biāo)簽欄引入自定義圖標(biāo)方式

    這篇文章主要介紹了Vant的Tabbar標(biāo)簽欄引入自定義圖標(biāo)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue.js實(shí)現(xiàn)全屏背景圖片滑動(dòng)切換特效

    Vue.js實(shí)現(xiàn)全屏背景圖片滑動(dòng)切換特效

    本文主要介紹了Vue.js實(shí)現(xiàn)全屏背景圖片滑動(dòng)切換特效,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-01-01
  • Vue自定義指令的使用實(shí)例介紹

    Vue自定義指令的使用實(shí)例介紹

    作為使用Vue的開發(fā)者,我們對(duì)Vue指令一定不陌生,諸如v-model、v-on、等,同時(shí)Vue也為開發(fā)者提供了自定義指令的api,熟練的使用自定義指令可以極大的提高了我們編寫代碼的效率,讓我們可以節(jié)省時(shí)間開心的摸魚
    2023-04-04
  • Vue3和Vue2的響應(yīng)式原理

    Vue3和Vue2的響應(yīng)式原理

    這篇文章我們將探討Vue3框架的優(yōu)秀特性、使用原理、周邊生態(tài)和實(shí)戰(zhàn)應(yīng)用,系統(tǒng)的學(xué)習(xí)Vue生態(tài)體系,希望和大家共同成長(zhǎng),我們一起探討下Vue3和Vue2的響應(yīng)式原理,那究竟什么是“響應(yīng)式”,接下來(lái)跟著小編一起來(lái)學(xué)習(xí)吧
    2023-05-05
  • Vue.js學(xué)習(xí)筆記之 helloworld

    Vue.js學(xué)習(xí)筆記之 helloworld

    vue是法語(yǔ)中視圖的意思,Vue.js是一個(gè)輕巧、高性能、可組件化的MVVM庫(kù),同時(shí)擁有非常容易上手的API。有需要的小伙伴可以參考下
    2016-08-08
  • vue的@change的用法及操作代碼

    vue的@change的用法及操作代碼

    @change 是 Vue.js 中用于監(jiān)聽表單元素值變化的事件處理器,這篇文章主要介紹了vue的@change的用法,需要的朋友可以參考下
    2023-10-10
  • 在vue中使用防抖和節(jié)流,防止重復(fù)點(diǎn)擊或重復(fù)上拉加載實(shí)例

    在vue中使用防抖和節(jié)流,防止重復(fù)點(diǎn)擊或重復(fù)上拉加載實(shí)例

    今天小編就為大家分享一篇在vue中使用防抖和節(jié)流,防止重復(fù)點(diǎn)擊或重復(fù)上拉加載實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11

最新評(píng)論