vue3輸入框生成的時(shí)候如何自動(dòng)獲取焦點(diǎn)詳解
前言
當(dāng)我們?cè)谧?code>vue3的項(xiàng)目的時(shí)候,在對(duì)一些信息的修改的時(shí)候,需要雙擊或者點(diǎn)擊按鈕來(lái)進(jìn)行操作,讓數(shù)據(jù)變成輸入框來(lái)進(jìn)行修改數(shù)據(jù),當(dāng)輸入框失去焦點(diǎn)的時(shí)候就進(jìn)行保存,然而不方便的是,輸入框出現(xiàn)的時(shí)候不能獲取焦點(diǎn)導(dǎo)致用戶的體驗(yàn)不好。
創(chuàng)建實(shí)例演示(創(chuàng)建文件,可忽略)
首先我們需要一個(gè)vue3
的項(xiàng)目,如何創(chuàng)建一個(gè)vue3
的項(xiàng)目,新建一個(gè)空的文件夾,cmd
打開,輸入
1. vue create 項(xiàng)目的名稱
舉例:vue create demo
我們選擇自定義,即
2. Manually select features
回車,按需引入自己需要的,按空格即代表選中
3. 舉例:
>(*) Babel
(*) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
(*) CSS Pre-processors
(*) Linter / Formatter
( ) Unit Testing
( ) E2E Testing
回車
4. 選擇要用來(lái)啟動(dòng)項(xiàng)目的 Vue.js版本(使用箭頭鍵),選擇3.x
5. 使用類樣式組件語(yǔ)法? 輸入N
6. 將 Babel 與 TypeScript 一起使用(現(xiàn)代模式、自動(dòng)檢測(cè)的 polyfills、轉(zhuǎn)譯 JSX 需要)?輸入Y
7. 路由器使用history模式?選擇N (這個(gè)決定你編譯出來(lái)的地址是否含有 /#/ 的字樣)
8. 選擇一個(gè) CSS 預(yù)處理器 這里按自己的需求來(lái),這里我選擇Sass/SCSS (with dart-sass)
9. 選擇一個(gè) linter /格式化程序配置 選擇ESLint + Standard config
10. Pick additional lint features 選擇Lint on save
11. 您更喜歡將 Babel、ESLint 等的配置放在何處? 選擇In dedicated config files,這樣好處理
12. 將此保存為將來(lái)項(xiàng)目的預(yù)設(shè)?這里我選擇N,看個(gè)人的需求了
定義一些簡(jiǎn)單的頁(yè)面,我們用到了bootstrap
的一些樣式需要在public
文件夾的index.html
添加外部樣式的引入<link href=“https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css” rel=“stylesheet”>書寫在title
標(biāo)簽下即可,在HomeView
頁(yè)面文件書寫簡(jiǎn)單的代碼
<template> <div class="container"> <ul class="list-group"> <template v-for="(i, index) in list" :key="index"> <li class="list-group-item d-flex justify-content-between" v-if="!i.checked"> <div class="form-group form-check mb-0"> <input type="checkbox" class="form-check-input" /> <label v-if="!i.isEdit" class="form-check-label" @dblclick="showEdit(i, index)"> {{ i.name }} </label> <label v-else class="form-check-label" :for="'i-' + index"> <!-- --> <input type="text" v-model="editValue" @blur="changeEdit" ref="myInput" /></label> </div> <button type="button" class="close" aria-label="Close" @click="remove(index)"> <span aria-hidden="true">×</span> </button> </li> </template> </ul> </div> </template>
JS代碼如下
<script lang="ts"> import { defineComponent, reactive, toRefs, ref } from 'vue' export default defineComponent({ name: 'HomeView', setup() { // 元素節(jié)點(diǎn) const myInput = ref(null) // 編輯的索引 let editIndex = 0 // 是否獲取焦點(diǎn) const open = 0 // 數(shù)據(jù) const state = reactive({ value: '', editValue: '', list: [ { name: '1', checked: false, isEdit: false }, { name: '2', checked: false, isEdit: false }, { name: '3', checked: false, isEdit: false } ] }) // 雙擊修改 const showEdit = (item, index) => { if (open == 0) { open = 1 editIndex = index item.isEdit = true state.editValue = item.name } } // 失去焦點(diǎn) const changeEdit = () => { state.list[editIndex] = { name: state.editValue, checked: false, isEdit: false } open = 0 editIndex = 0 } // 移除 const remove = (index) => { state.list.splice(index, 1) } return { ...toRefs(state), showEdit, changeEdit, remove, myInput } } }) </script>
基礎(chǔ)頁(yè)面搭建好了之后,在終端輸入
npm run serve
將項(xiàng)目跑起來(lái),我們會(huì)看到三條任務(wù)
雙擊就可以編輯,點(diǎn)擊叉號(hào)可以刪除,復(fù)選框和添加的未加上
解決方法
當(dāng)我們雙擊進(jìn)行編輯的時(shí)候,會(huì)發(fā)現(xiàn)輸入框不能獲取焦點(diǎn),用戶的輸入十分不方便,而且當(dāng)我們想失去焦點(diǎn)的時(shí)候,也不許去點(diǎn)擊輸入框再失去焦點(diǎn)才能取消修改,十分的麻煩。
1、方法一
我們可以添加異步的手法讓輸入框出現(xiàn)之后再執(zhí)行獲取焦點(diǎn)的手法來(lái)解決,具體的解決代碼如下
// 雙擊修改 const showEdit = (item, index) => { if (open == 0) { setTimeout(() => { myInput.value[0].focus() }) open = 1 editIndex = index item.isEdit = true state.editValue = item.name } }
通過(guò)插入一個(gè)延時(shí)器來(lái)解決問(wèn)題
2、方法二
熟悉vue2
的朋友應(yīng)該知道$nextTick
就可以解決,但在這里vue3
需要配合監(jiān)聽使用,還需要ref
來(lái)選擇我們需要操作的元素對(duì)象,查閱官網(wǎng)的ref
使用方法,和vue2
不一樣,在vue2
中,我們需要給我們需要的元素節(jié)點(diǎn)打上ref
標(biāo)簽,讀取直接使用this.$refs
來(lái)操作,演示如下
template: <button ref="btn"></button> methods: this.$refs.btn
在vue3
中的使用讀取:
<template> <div ref="box">div</div> </template> <script> // 引入 import { onMounted, ref } from 'vue'; export default { name: 'App', setup() { let box = ref(null); // onMounted() 中的行為會(huì)在聲明周期 mounted 中執(zhí)行。 onMounted(() => { // 在這里就可以讀取到我們需要的元素節(jié)點(diǎn) console.log('box.value', box.value); }) return {box}; } } </script>
但是,我們的input
框是根據(jù)state.list
每一項(xiàng)的isEdit
決定的,也就是說(shuō)onMounted
執(zhí)行的時(shí)候,我們的輸入框一直是未打開的,只有當(dāng)我們雙擊的時(shí)候,才會(huì)喚醒我們的輸入框,而onMounted
只會(huì)在頁(yè)面完全加載的時(shí)候執(zhí)行一次,所以當(dāng)我們雙擊的時(shí)候,控制臺(tái)就會(huì)打印出null
,此時(shí)我們是獲取不到我們需要的元素節(jié)點(diǎn),也就是代碼
// 使用之前記得引入onMounted onMounted(() => { console.log('myInput.value', myInput.value) })
控制臺(tái)打印出的是null
這時(shí)候獲取焦點(diǎn)
onMounted(() => { console.log('myInput.value', myInput.value) myInput.value[0].focus() })
控制臺(tái)就會(huì)報(bào)錯(cuò)
Uncaught TypeError: Cannot read properties of null (reading '0')
at Proxy.showEdit (HomeView.vue?4752:47:1)
at onDblclick (HomeView.vue?475e:67:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:164:1)
at HTMLLabelElement.invoker (runtime-dom.esm-bundler.js?2725:369:1)
如果我們使用onUpdated
,通過(guò)獲取頁(yè)面更新之后就去讓輸入框獲取焦點(diǎn)
// 使用之前記得引入onUpdated onUpdated(() => { console.log('myInput.value', myInput.value) })
我們可以獲取一個(gè)空數(shù)組的代理對(duì)象,而且我們失去焦點(diǎn)就會(huì)報(bào)錯(cuò)
// 代理對(duì)象 Proxy {0: input}[[Handler]]: Object [[Target]]: Array(0) [[IsRevoked]]: false
報(bào)錯(cuò):
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'focus')
at eval (demoView.vue?0f1f:69:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:164:1)
at Array.hook.__weh.hook.__weh (runtime-core.esm-bundler.js?d2dd:2685:1)
at flushPostFlushCbs (runtime-core.esm-bundler.js?d2dd:356:1)
at flushJobs (runtime-core.esm-bundler.js?d2dd:401:1)
我們需要監(jiān)視open
的變化,在使用nextTick
當(dāng)頁(yè)面完全加載的時(shí)候獲取輸入框的元素節(jié)點(diǎn)在使其獲取焦點(diǎn)接口,因?yàn)槲覀冎笆鞘褂?code>let open = 0,我們需要一定的修改,否則watch
的open
會(huì)報(bào)錯(cuò):
No overload matches this call.
The last overload gave the following error.
Argument of type 'number' is not assignable to parameter of type 'object'.
引入:
import { defineComponent, reactive, toRefs, ref, nextTick, watch } from 'vue'
修改open
:
// 是否獲取焦點(diǎn) let open = ref(0)
將后面所用到的所有open
改成open.value
,添加監(jiān)聽代碼:
watch(open, (newValue, oldValue) => { if (newValue == 1) { nextTick(() => { console.log(myInput.value) console.log('--- DOM更新了 ---') myInput.value[0].focus() }) } })
這時(shí)候我們就可以在每次雙擊改變open
,即代碼:open.value = 1
,就會(huì)被監(jiān)聽到,從而使輸入框獲取焦點(diǎn)。
總結(jié)
到此這篇關(guān)于vue3輸入框生成的時(shí)候如何自動(dòng)獲取焦點(diǎn)的文章就介紹到這了,更多相關(guān)vue3輸入框自動(dòng)獲取焦點(diǎn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue與iframe之間的信息交互的實(shí)現(xiàn)
這篇文章主要介紹了vue與iframe之間的信息交互的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04vue項(xiàng)目實(shí)現(xiàn)通過(guò)ip地址訪問(wèn)和localhost訪問(wèn)方式
這篇文章主要介紹了vue項(xiàng)目實(shí)現(xiàn)通過(guò)ip地址訪問(wèn)和localhost訪問(wèn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09vue項(xiàng)目在線上服務(wù)器訪問(wèn)失敗原因分析
這篇文章主要介紹了vue項(xiàng)目在線上服務(wù)器訪問(wèn)失敗原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08vue-router 手勢(shì)滑動(dòng)觸發(fā)返回功能
這篇文章主要介紹了vue-router 手勢(shì)滑動(dòng)觸發(fā)返回功能,文中通過(guò)實(shí)例代碼給大家介紹了vue圖片左右滑動(dòng)及手勢(shì)縮放,需要的朋友可以參考下2018-09-09vue 修改 data 數(shù)據(jù)問(wèn)題并實(shí)時(shí)顯示操作
這篇文章主要介紹了vue 修改 data 數(shù)據(jù)問(wèn)題并實(shí)時(shí)顯示操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09