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

基于vue3實現(xiàn)一個簡單的輸入框效果

 更新時間:2024年03月01日 11:28:51   作者:趙小川  
這篇文章主要為大家詳細(xì)介紹了如何使用Vue3實現(xiàn)一個簡單的輸入框,可以實現(xiàn)輸入文字,添加表情等功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

需求背景

需要一個輸入框,可以輸入文字,添加表情,一開始用了富文本編輯器,有點大材小用,所以自己封裝一個輸入框組件。支持輸入文字,選擇表情/插入表情,支持組合鍵換行,使用enter 進(jìn)行提交

效果圖

技術(shù)實現(xiàn)

  • 通過原生textarea實現(xiàn)
  • 通過 v-model 來實現(xiàn) 父子組件的數(shù)據(jù)傳遞,子組件監(jiān)聽數(shù)據(jù)的變化,向外emit('update:modelValue', inputValue),保證父組件能更新綁定的值
  • 每次插入時,需要重新聚焦,更新光標(biāo)位置
  • 通過向外 暴露的 (__insertText),來實現(xiàn)插入表情/文字
  • 通過向外暴露的(_clear) 輸入完畢發(fā)送后,需要clear 掉輸入框的內(nèi)容
  • 通過向外暴露的(__isEmpty) 來判斷是否有內(nèi)容,如果沒內(nèi)容,做按鈕的禁用狀態(tài)(當(dāng)然也可以直接用父組件綁定的值)
  • 父組件通過ref 就可以調(diào)用以上方法,來做操作。比如發(fā)送完數(shù)據(jù),調(diào)clear清空內(nèi)容,如果輸入框沒有內(nèi)容,則調(diào)用isEmpty,做按鈕的一些狀態(tài)

代碼實現(xiàn)(子組件)

/**
 * 自定義文本輸入框組件
 */

import { ref, watch } from 'vue'
import { ElInput } from 'element-plus'

export default defineComponent({
  props: {
    modelValue: {
      type: String,
      default: ''
    }
  },
  emits: ['update:modelValue', 'chatSend'],
  setup(props, { emit, expose }) {
    const { t } = useI18n()
    const editorRef = ref()
    const disabled = ref(false)
    const valueHtml = ref(props.modelValue)
    const currentEvent = ref()
    watch(
      () => valueHtml.value,
      () => {
        emit('update:modelValue', valueHtml.value)
      }
    )

    // 插入元素
    const _insertText = async (msg: string) => {
      const msgLength = msg.length
      const editor = currentEvent.value
      if (editor) {
        const startPos = editor.selectionStart
        valueHtml.value = `${valueHtml.value.substring(0, startPos)}${'' + msg}${valueHtml.value.substring(startPos)}`
        _focus()
        nextTick(() => {
        // 此處是 根據(jù)元素的長度,來設(shè)置光標(biāo)位置
          editor.setSelectionRange(startPos + msgLength, startPos + msgLength)
        })
      }
    }

    // focus
    const _focus = () => {
      editorRef.value && editorRef.value.focus()
    }

    // 清空編輯器
    const _clear = () => {
      editorRef.value && editorRef.value.clear()
    }

    // 是否內(nèi)容為空
    const _isEmpty = () => {
      const str = valueHtml.value.trim().replace(/\n/g, '')
      return str === '' || str.length == 0 || typeof str === 'undefined'
    }

    // 禁用編輯器
    const _disable = () => {
      disabled.value = true
    }

    // 解除禁用編輯器
    const _enable = () => {
      disabled.value = false
    }

    const handleKeyDown = (event: KeyboardEvent) => {
      currentEvent.value = event.target as HTMLInputElement
      // 定義組合鍵 Map
      const shortCutKeys: (keyof KeyboardEvent)[] = ['metaKey', 'altKey', 'ctrlKey', 'shiftKey']
      const isEnterKey = event.code === 'Enter'
      const isShortcutKeys = shortCutKeys.some((item) => event[item])
      if (isEnterKey && isShortcutKeys) {
        // 獲取光標(biāo)位置
        const cursorPosition = currentEvent.value.selectionStart

        // 拆分成兩段文本
        const textBeforeCursor = valueHtml.value.slice(0, cursorPosition)
        const textAfterCursor = valueHtml.value.slice(cursorPosition)

        // 合并為帶有換行符的新文本
        const newText = textBeforeCursor + '\n' + textAfterCursor

        // 更新輸入框的值
        valueHtml.value = newText
        // 文本編輯器的高度發(fā)生變化后
        nextTick(() => {
          // 高度變化 自動滾動到底部
          const editor = editorRef.value.textarea
          editorRef.value.textarea.scrollTop = editor.scrollHeight
          // 設(shè)置光標(biāo)位置為: start 和 end 相同,光標(biāo)會移動到換行符后面的新行首
          currentEvent.value.setSelectionRange(cursorPosition + 1, cursorPosition + 1)
        })
      } else if (event.code === 'Enter') {
        // 阻止掉 Enter 的默認(rèn)換行行為
        event.preventDefault()
        emit('chatSend')
      }
    }
    // 向外暴露方法
    expose({
      _insertText,
      _clear,
      _disable,
      _isEmpty,
      _enable,
      _focus
    })
    return () => (
      <div class="chatEditor">
        <ElInput
          ref={editorRef}
          v-model={valueHtml.value}
          type="textarea"
          disabled={disabled.value}
          onKeydown={handleKeyDown}
        />
      </div>
    )
  }
})

代碼實現(xiàn)(父組件調(diào)用)

輸入框組件

<base-editor
        ref="chatEditorRef"
        v-model="inputText"
        @chat-send="sendText"
 ></base-editor>

工具欄組件

<ChatTools :chat-tools-list="newChatToolsList" @get-emoji="getToolsMsg" />

當(dāng)我們點擊工具欄組件,就會獲取到工具欄的文字/表情/或者插入的xxx ,此時根據(jù)引用,調(diào)用輸入框的暴露出的_insertText方法,直接就插入進(jìn)去

const getToolsMsg = async (msg: string) => {
  chatEditorRef.value._insertText(msg)
}

其他方法調(diào)用

_isEmpty(): 未輸入,按鈕是禁用狀態(tài)

 <el-button :disabled="chatEditorRef?._isEmpty()" type="primary" @click="sendText">

當(dāng)然你也可以直接使用綁定的輸入框的變量去判斷

<el-button :disabled="!inputText" @click="sendText">

_clear(): 提交完請求,清空輸入框

chatEditorRef.value._clear()

關(guān)于插入的問題

光標(biāo)位置的獲取,根據(jù)元素插入位置,光標(biāo)換行,支持快捷鍵等??梢詤⒖忌弦黄恼拢?a href="http://chabaoo.cn/javascript/316756c60.htm" target="_blank">vue3通過組合鍵實現(xiàn)換行操作的示例詳解

總結(jié)

  • 原生其實也可以實現(xiàn),沒必要用一個很重的富文本編輯器
  • 做表情插入,或者其他插入,都是工具欄,和輸入框組件的關(guān)系是兄弟組件的關(guān)系,兄弟組件之間,怎么做數(shù)據(jù)傳遞,事件傳遞,怎么設(shè)計?

(1) 父組件作為中介

(2)事件總線通過訂閱/發(fā)布做消息通知

(3)倉庫vuex/pina

事件總線還是能不用就不用,因為全局性的東西,用著爽,后面復(fù)雜了,就亂了。而且 事件總線是發(fā)布訂閱,你還得注意銷毀,存?zhèn)}庫 又不太合適,子組件自己暴露出方法,讓其他組件調(diào)用,感覺目前是最簡單的方式了。

到此這篇關(guān)于基于vue3實現(xiàn)一個簡單的輸入框效果的文章就介紹到這了,更多相關(guān)vue3輸入框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue中使用Cesium加載shp文件、wms服務(wù)、WMTS服務(wù)問題

    vue中使用Cesium加載shp文件、wms服務(wù)、WMTS服務(wù)問題

    這篇文章主要介紹了vue中使用Cesium加載shp文件、wms服務(wù)、WMTS服務(wù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vite+vue3+element-plus項目搭建的方法步驟

    vite+vue3+element-plus項目搭建的方法步驟

    因為vue3出了一段時間了,element也出了基于vue3.x版本的element-plus,vite打包聽說很快,嘗試一下,感興趣的可以了解一下
    2021-06-06
  • Vue基礎(chǔ)popover彈出框編寫及bug問題分析

    Vue基礎(chǔ)popover彈出框編寫及bug問題分析

    這篇文章主要為大家介紹了Vue基礎(chǔ)popover彈出框編寫及bug問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • vite中的glob-import批量導(dǎo)入的實現(xiàn)

    vite中的glob-import批量導(dǎo)入的實現(xiàn)

    本文主要介紹了vite中的glob-import批量導(dǎo)入的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • vue項目從node8.x升級到12.x后的問題解決

    vue項目從node8.x升級到12.x后的問題解決

    這篇文章主要介紹了vue項目從node8.x升級到12.x后的問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 如何通過Vue3+Element?Plus自定義彈出框組件

    如何通過Vue3+Element?Plus自定義彈出框組件

    這篇文章主要給大家介紹了關(guān)于如何通過Vue3+Element?Plus自定義彈出框組件的相關(guān)資料,彈窗是前端開發(fā)中的一種常見需求,文中通過代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-05-05
  • vue-router鉤子函數(shù)實現(xiàn)路由守衛(wèi)

    vue-router鉤子函數(shù)實現(xiàn)路由守衛(wèi)

    這篇文章主要介紹了vue-router鉤子函數(shù)實現(xiàn)路由守衛(wèi),對vue感興趣的同學(xué),可以參考下
    2021-04-04
  • Vue3配置axios跨域?qū)崿F(xiàn)過程解析

    Vue3配置axios跨域?qū)崿F(xiàn)過程解析

    這篇文章主要介紹了Vue3配置axios跨域?qū)崿F(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • vue3配置代理實現(xiàn)axios請求本地接口返回PG庫數(shù)據(jù)

    vue3配置代理實現(xiàn)axios請求本地接口返回PG庫數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了vue3配置代理實現(xiàn)axios請求本地接口返回PG庫數(shù)據(jù)的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-03-03
  • Vue中如何使用mock模擬數(shù)據(jù)

    Vue中如何使用mock模擬數(shù)據(jù)

    這篇文章主要介紹了Vue中如何使用mock模擬數(shù)據(jù),具有很好的價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06

最新評論