前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端表单输入框自动填充和覆盖逻辑的实现

前端表单输入框自动填充和覆盖逻辑的实现

原创
作者头像
喵喵侠
发布2024-06-20 19:35:43
2733
发布2024-06-20 19:35:43
举报

目录

前言

你好,我是喵喵侠。在Web开发中,动态表单的联动操作,是非常常见的需求,尤其是在需要实现复杂逻辑时,更是不可或缺。正好我在工作中,好几次遇到了输入框内容需要被填充的需求,本文将会为你详细介绍这样的需求案例,展示具体实现的思路和实战代码。

需求描述

现在我们来探讨一个具体的需求场景:页面上有一个表单,其中包含一个公司名称输入框(input)和一个所有公司下拉菜单(select),下拉菜单的选项,比方说有腾讯、阿里巴巴、百度和字节跳动。当选中下拉菜单的某个选项时,将该选项的值,会自动填充到输入框中。但如果输入框已经有用户手动输入的值,且该值不在选项列表中,则不覆盖。

更通俗的理解就是,Input 里面有用户手动输入的内容,无论你的选择哪个,都不会覆盖用户原本输入的值,除非他全部删掉,后续的选择才会填充到 Input 里面。如果一开始用户没有输入,则每次的选中都会覆盖上一次的 Input 结果。

其实我接到真实的需求是,有一个地图弹窗,里面有一个百度地图,点击地图任意点位,地图会标点并显示该定位的位置名称,弹窗确定后,这个位置名称会被填充到 Input 输入框中。这里我为了方便理解,把地图弹窗简化成了 Select,核心功能是一样的,掌握了这个方式的实现,类似的都大同小异。

实现思路

我们来拆解下这个需求,把功能点进行拆分如下:

  1. input 为空,select 选中后自动填充;
  2. input 有值,且为用户输入,则 select 选中后不填充;
  3. input 有值,且为上次 select 填充结果,则 select 选中后覆盖填充。

自动填充很好实现,select 的 change 事件进行赋值就好了,难点在于如何判断当前的 input 的值,是用户输入的,还是 select 填充的呢?

对此我有两种解决方案:

方案一:select 选项 label比对

这个方案很好理解,就是每次 select 选中的时候,当 change 事件触发时,判断当前 input 的值,是否能与 select 的 option 选项中的某一项的 label 匹配的上,如果这个 input 值和这一项的 label 完全相等,那么可以视为这个 input 值是来自于上次的 select 选择,否则change 事件不执行覆盖填充操作。

这里有个细节,那就是存在输入的值和 select 值完全相等的情况,不过这个不影响,因为从效果上来看,都是一样的。

方案二:设置根据用户输入行为设置一个 flag 开关

这种方案和方案一的关注点不同,它不关心 option 里面有什么样的 label,而是关注这个 input 内容是不是来自用户的。要想判断其实很简单,只需要监听一下 input 事件就好了。如果 input 事件执行了,且 input 的值不为空,那么可以视为这个 input 的值是来自于用户手动输入,不能select 选中后无法覆盖,否则 select 选中后可以覆盖。

顺便说一下,粘贴文本到 input 输入框,也是可以触发 input 事件的。

具体实现

基于方案一的代码实现

代码语言:vue
复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Element-UI 表单示例</title>
  <!-- 引入Element-UI的CSS和JavaScript -->
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css">
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js"></script>
</head>
<body>
  <div id="app">
    <el-form>
      <el-form-item label="公司名称">
        <el-input v-model="form.companyName" style="width: 200px" placeholder="请输入"></el-input>
      </el-form-item>
      <el-form-item label="选择公司">
        <el-select v-model="form.selectedCompany" @change="handleCompanyChange">
          <el-option
            v-for="item in companies"
            :key="item.value"
            :label="item.label"
            :value="item.label">
          </el-option>
        </el-select>
      </el-form-item>
    </el-form>
  </div>

  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          form: {
            companyName: '',
            selectedCompany: '',
          },
          companies: [
            { value: '腾讯', label: '腾讯' },
            { value: '阿里巴巴', label: '阿里巴巴' },
            { value: '百度', label: '百度' },
            { value: '字节跳动', label: '字节跳动' },
          ],
        };
      },
      methods: {
        handleCompanyChange(value) {
          const isfindCompanyName = this.companies.some(company => company.label == this.form.companyName);
          console.log(isfindCompanyName)
          if (!isfindCompanyName && this.form.companyName) {
            return false
          }
          this.form.companyName = value;
        },
      },
    });
  </script>
</body>
</html>

实现效果如下:

基于方案二的代码实现

代码语言:vue
复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Element-UI 表单示例</title>
  <!-- 引入Element-UI的CSS和JavaScript -->
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css">
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js"></script>
</head>
<body>
  <div id="app">
    <el-form>
      <el-form-item label="公司名称">
        <el-input v-model="form.companyName" style="width: 200px" placeholder="请输入" @input="handleInput"></el-input>
      </el-form-item>
      <el-form-item label="选择公司">
        <el-select v-model="form.selectedCompany" @change="handleCompanyChange">
          <el-option
            v-for="item in companies"
            :key="item.value"
            :label="item.label"
            :value="item.label">
          </el-option>
        </el-select>
      </el-form-item>
    </el-form>
  </div>

  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          form: {
            companyName: '',
            selectedCompany: '',
          },
          companies: [
            { value: '腾讯', label: '腾讯' },
            { value: '阿里巴巴', label: '阿里巴巴' },
            { value: '百度', label: '百度' },
            { value: '字节跳动', label: '字节跳动' },
          ],
          inputFlag: false
        };
      },
      methods: {
        handleInput(value) {
          this.inputFlag = !!value // Vue Cli项目注意是 event.target.value
        },
        handleCompanyChange(value) {
          if (this.inputFlag) {
            return false
          }
          const findCompanyLabel = this.companies.find(item=>item.value == value)?.label
          this.form.companyName = findCompanyLabel
          this.inputFlag = false;
        },
      },
    });
  </script>
</body>
</html>

实现效果也是一样的,这里就不重复放效果图了。

只是注意一点,handleInput方法接受的第一个参数,在 Vue Cli 里面 event 是这个input 的 dom 对象,需要通过 event.target.value获取输入的值,而 上面html 版本的 vue demo 中,第一个参数实际上变成了 value。

总结

虽然这是一个很小的业务功能点,但里面的细节还是有一些的。通过实现公司名称和选择公司选项的联动功能,我们可以大大提升用户填写表单的便捷性和体验。当用户选择公司的时候,自动填充公司名称不仅减少了手动输入的麻烦,还能避免输入错误。这种精细的用户体验设计,虽然看似简单,却能显著提升用户对表单的使用满意度,增强系统的易用性和专业性。做好这些细节的优化,对于整个应用的用户体验都有积极的作用。

如果你有更好的实现思路或看法,欢迎在评论区与我交流。


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 前言
  • 需求描述
  • 实现思路
    • 方案一:select 选项 label比对
      • 方案二:设置根据用户输入行为设置一个 flag 开关
      • 具体实现
        • 基于方案一的代码实现
          • 基于方案二的代码实现
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档