vue3输入框生成的时候如何自动获取焦点详解

目录
  • 前言
  • 创建实例演示(创建文件,可忽略)
  • 解决方法
    • 1、方法一
    • 2、方法二
  • 总结

前言

当我们在做vue3的项目的时候,在对一些信息的修改的时候,需要双击或者点击按钮来进行操作,让数据变成输入框来进行修改数据,当输入框失去焦点的时候就进行保存,然而不方便的是,输入框出现的时候不能获取焦点导致用户的体验不好。

创建实例演示(创建文件,可忽略)

首先我们需要一个vue3的项目,如何创建一个vue3的项目,新建一个空的文件夹,cmd打开,输入

1. vue create 项目的名称
举例: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. 选择要用来启动项目的 Vue.js版本(使用箭头键),选择3.x
5. 使用类样式组件语法? 输入N
6. 将 Babel 与 TypeScript 一起使用(现代模式、自动检测的 polyfills、转译 JSX 需要)?输入Y
7. 路由器使用history模式?选择N (这个决定你编译出来的地址是否含有 /#/ 的字样)
8. 选择一个 CSS 预处理器 这里按自己的需求来,这里我选择Sass/SCSS (with dart-sass)
9. 选择一个 linter /格式化程序配置 选择ESLint + Standard config
10. Pick additional lint features 选择Lint on save
11. 您更喜欢将 Babel、ESLint 等的配置放在何处? 选择In dedicated config files,这样好处理
12. 将此保存为将来项目的预设?这里我选择N,看个人的需求了

定义一些简单的页面,我们用到了bootstrap的一些样式需要在public文件夹的index.html添加外部样式的引入<link href=“https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css” rel=“stylesheet”>书写在title标签下即可,在HomeView页面文件书写简单的代码

<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">&times;</span>
          </button>
        </li>
      </template>
    </ul>
  </div>
</template>

JS代码如下

<script lang="ts">
import { defineComponent, reactive, toRefs, ref } from 'vue'

export default defineComponent({
  name: 'HomeView',
  setup() {
    // 元素节点
    const myInput = ref(null)
    // 编辑的索引
    let editIndex = 0
    // 是否获取焦点
    const open = 0
    // 数据
    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
      }
    }
    // 失去焦点
    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>

基础页面搭建好了之后,在终端输入

npm run serve

将项目跑起来,我们会看到三条任务

双击就可以编辑,点击叉号可以删除,复选框和添加的未加上

解决方法

当我们双击进行编辑的时候,会发现输入框不能获取焦点,用户的输入十分不方便,而且当我们想失去焦点的时候,也不许去点击输入框再失去焦点才能取消修改,十分的麻烦。

1、方法一

我们可以添加异步的手法让输入框出现之后再执行获取焦点的手法来解决,具体的解决代码如下

    // 双击修改
    const showEdit = (item, index) => {
      if (open == 0) {
        setTimeout(() => {
          myInput.value[0].focus()
        })
        open = 1
        editIndex = index
        item.isEdit = true
        state.editValue = item.name
      }
    }

通过插入一个延时器来解决问题

2、方法二

熟悉vue2的朋友应该知道$nextTick就可以解决,但在这里vue3需要配合监听使用,还需要ref来选择我们需要操作的元素对象,查阅官网的ref使用方法,和vue2不一样,在vue2中,我们需要给我们需要的元素节点打上ref标签,读取直接使用this.$refs来操作,演示如下

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() 中的行为会在声明周期 mounted 中执行。
    onMounted(() => {
    // 在这里就可以读取到我们需要的元素节点
      console.log('box.value', box.value);
    })
    return {box};
  }
}
</script>

但是,我们的input框是根据state.list每一项的isEdit决定的,也就是说onMounted执行的时候,我们的输入框一直是未打开的,只有当我们双击的时候,才会唤醒我们的输入框,而onMounted只会在页面完全加载的时候执行一次,所以当我们双击的时候,控制台就会打印出null,此时我们是获取不到我们需要的元素节点,也就是代码

// 使用之前记得引入onMounted
onMounted(() => {
   console.log('myInput.value', myInput.value)
})

控制台打印出的是null

这时候获取焦点

onMounted(() => {
   console.log('myInput.value', myInput.value)
    myInput.value[0].focus()
})

控制台就会报错

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,通过获取页面更新之后就去让输入框获取焦点

// 使用之前记得引入onUpdated
onUpdated(() => {
   console.log('myInput.value', myInput.value)
})

我们可以获取一个空数组的代理对象,而且我们失去焦点就会报错

// 代理对象
Proxy {0: input}[[Handler]]: Object
	[[Target]]: Array(0)
	[[IsRevoked]]: false

报错:

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)

我们需要监视open的变化,在使用nextTick当页面完全加载的时候获取输入框的元素节点在使其获取焦点接口,因为我们之前是使用let open = 0,我们需要一定的修改,否则watchopen会报错:

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

    // 是否获取焦点
    let open = ref(0)

将后面所用到的所有open改成open.value,添加监听代码:

    watch(open, (newValue, oldValue) => {
      if (newValue == 1) {
        nextTick(() => {
          console.log(myInput.value)
          console.log('--- DOM更新了 ---')
          myInput.value[0].focus()
        })
      }
    })

这时候我们就可以在每次双击改变open,即代码:open.value = 1,就会被监听到,从而使输入框获取焦点。

总结

到此这篇关于vue3输入框生成的时候如何自动获取焦点的文章就介绍到这了,更多相关vue3输入框自动获取焦点内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue 自定义指令自动获取文本框焦点的方法

    HTML: <p><b v-show="show">{{tag}}</b><input v-focus v-model="tag" :hidden="show" type="text"></p> js: 官方例子: directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } } 我的

  • vue中监听input框获取焦点及失去焦点的问题

    目录 一.背景 二.首先是正宗的监听事件的写法 1.html代码 2.JS部分 三.为什么上次监听焦点事件失败呢 1.不好用的原因 2.新增指令的方法 一.背景 博主之前在用vue的获取焦点,失去焦点的时候,出现了@blur和@focus无效的情况.当时百思不得其解.今天又在写vue页面的时候,突然@blur和@focus又好用了.emmmm,看来这部分值得一战. 二.首先是正宗的监听事件的写法 1.html代码 //这是html的输入框.定义了一个获取焦点,失去焦点的方法 <input pla

  • vue3输入框生成的时候如何自动获取焦点详解

    目录 前言 创建实例演示(创建文件,可忽略) 解决方法 1.方法一 2.方法二 总结 前言 当我们在做vue3的项目的时候,在对一些信息的修改的时候,需要双击或者点击按钮来进行操作,让数据变成输入框来进行修改数据,当输入框失去焦点的时候就进行保存,然而不方便的是,输入框出现的时候不能获取焦点导致用户的体验不好. 创建实例演示(创建文件,可忽略) 首先我们需要一个vue3的项目,如何创建一个vue3的项目,新建一个空的文件夹,cmd打开,输入 1. vue create 项目的名称举例:vue c

  • 使用Vite+Vue3+Vant全家桶快速构建项目步骤详解

    目录 引言 一.vue3全家桶模板介绍 1.版本依赖 2.全家桶内置集成 二.安装 tive-cli 命令行工具 三.生成项目 四.项目体验 引言 随着Vue3 和 Vite 版本的不断更新完善,开发体验有了质的飞跃.因此,越来越多的大厂也逐步拥抱 Vue3. 利用Vite 脚手架工具可以很轻松生成以 Vue3 为模板的项目,但是作为Vue全家桶的 vue-router.vuex.axios等成员,需要自己一个一个去配置.于是便自行开发了本文讲到的 tive-cli 脚手架模板工具,只需短短几个

  • vue3中vue.config.js配置及注释详解

    目录 报错 打包时提示文件过大,配置解决方案,如下 总结 报错 asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).This can impact web performance.entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit

  • WebStorm ES6 语法支持设置&babel使用及自动编译(详解)

    一.语法支持设置 Preferences > Languages & Frameworks > JavaScript 二.Babel安装 1.全局安装 npm install -g babel-cli 2.当前项目,适用于使用不同babel版本的情况 npm install --save-dev babel-cli 三.Babel基本用法 # 转码结果输出到标准输出 babel example.js # 转码结果写入一个文件 # --out-file 或 -o 参数指定输出文件 bab

  • 使用 Opentype.js 生成字体子集的实例代码详解

    字体子集是将字体文件中部分多余的字符删除,来减小文件大小,从而在 Web 端使用或嵌入到其他应用或系统中,在网上可以找到不少这方面的工具. Opentype.js是一套可以支持浏览器环境和 Node.js 环境的开源 OpenType 字体读写库,利用这个库可以很轻松实现浏览器环境和 Node.js 环境的字体子集功能. 在浏览器环境创建字体子集工具 首先创建一个简单的 HTML界面,包括一个选取字体文件按钮,一个输入框用于输入保留的字符,和一个保存下载按钮. HTML <!DOCTYPE ht

  • python2利用wxpython生成投影界面工具的图文详解

    本投影界面工具的功能: 准备好.prj投影文件,将输入文件夹内的WGS84经纬度坐标shp文件,投影为平面文件,成果自动命名为prj_***并新建在输入文件夹同一路径下. 下一步目标: 利用pyinstaller或其他打包库生成exe文件,目前停滞在python2语法.arcpy打包出错相关问题上. 参考文献: <Using Py2exe with Arcpy- It can be done easily!> <如何使用py2exe打包arcpy脚本?> GUI界面示意图 投影文件

  • 基于Python实现自动扫雷详解

    目录 准备 实现思路 窗体截取 雷块分割 雷块识别 扫雷算法实现 用Python+OpenCV实现了自动扫雷,突破世界记录,我们先来看一下效果吧. 中级 - 0.74秒 3BV/S=60.81 相信许多人很早就知道有扫雷这么一款经典的游(显卡测试)戏(软件),更是有不少人曾听说过中国雷圣,也是中国扫雷第一.世界综合排名第二的郭蔚嘉的顶顶大名.扫雷作为一款在Windows9x时代就已经诞生的经典游戏,从过去到现在依然都有着它独特的魅力:快节奏高精准的鼠标操作要求.快速的反应能力.刷新纪录的快感,这

  • C语言实现生成新春福字的示例详解

    目录 主要代码 字面量以及数据结构 定义一个回调函数,刷新福字 应用初始化程序 主程序 效果展示 快新年了,支付宝扫福活动又开始了,每次都要百度找福,这次不想找了,自己写一个程序生成各种字体的福字. 主要代码 字面量以及数据结构 #define FONT_DISPLAY "福" // g_fu_label中的每一个控件都是一个福字 static GtkWidget *g_fu_label[3][3]; // 记录所有的字体family typedef struct { int n_fa

  • Springboot @Configuration与自动配置详解

    不知道大家第一次搭SpringBoot环境的时候,有没有觉得非常简单.无须各种的配置文件,无须各种繁杂的pom坐标,一个main方法,就能run起来了.与其他框架整合也贼方便,使用EnableXXXXX注解就可以搞起来了! 所以今天来讲讲SpringBoot是如何实现自动配置的~ @SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot需要运行这个类的main方法来启动SpringBoot应用: 先看

  • vue3中的透传attributes教程示例详解

    目录 引言 绑定样式 对象 数组 透传的attributes 透传 attributes 之样式绑定 透传 attributes 之事件绑定 特殊1:组件嵌套 特殊2:禁用透传attributes 特殊3:在 javascript 中访问透传的attributes 总结 引言 最近两年都是在使用 react 进行项目开发,看技术博客都是针对 react 和 javaScript 高级方面的,对 vue 的知识基本上遗忘的差不多了.最近开始慢慢回顾 vue 的知识以及对新的语法进行学习,为后面的计

随机推荐