vue3 实现选择输入框

这篇具有很好参考价值的文章主要介绍了vue3 实现选择输入框。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

vue3 实现选择输入框 (带数据选择功能的输入框),这里用的vue3+nuxt(组件直接用)

  • 没有数据时显示弹框,可选择数据;
  • 如果要用自己输入的数据,输入完毕直接按回车即可(输入时按回车直接绑定输入框中的值给父组件的变量)

MyInput.vue:

<template>
  <div class="main">
    <div v-show="inputing || selecting" class="popover" ref="popover" @mousemove="mouseMove" @mouseleave="mouseLeave" :style="'width:' + width + 'px'">
      <div v-for="item in visibleList" @click="handleSelect(item)" class="item" :key="item.value">
        {{ item.label }}
      </div>
    </div>
    <input ref="input" class="input" v-model="tempValue" @focus="handleFocus" @input="handleInput(tempValue)"
      @blur="handleBlur" @keydown="handleEnter" :style="'width:' + width + 'px'" />
  </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
// props
const props = defineProps({
  value: {	// 绑定的值
    type: [String, Number],
    required: true
  },
  list: {	// 选择的数据
    type: Array,
    required: true
  },
  width: {	// 输入框宽度
    type: [String, Number],
    default: 120,
  },
  enterCreate: {  // 是否启用在输入框回车时创建值
    type: Boolean,
    default: true
  }
})

// emit
const emit = defineEmits(['update:value'])	// 双向绑定更新父组件中的变量

const map = {}; // 将list转换成map方便查询

// data
let selecting = ref(false); // 选择状态
let inputing = ref(false); // 编辑状态
let visibleList = ref([]); // 展示的数据
let tempValue = ref('');  // 输入框绑定的值

// ref
let input = ref(null);
let popover = ref(null);

// 初始化操作
(() => {
  // list转化为map 加快查询速度 
  props.list.forEach((item) => {
    map[item.value] = item.label;
  })
  // 初始化输入框展示数据
  tempValue.value = map[props.value] ? map[props.value] : props.value;
})()

// 挂载页面
onMounted(() => {
  addEventListener('scroll', callback, true)
  addEventListener('resize', callback, true)
})

// 卸载页面
onUnmounted(() => {
  removeEventListener('scroll', callback)
  removeEventListener('resize', callback)
})

// 事件监听回调函数
let callback = () => {
  requestAnimationFrame(updatePopoverPosition)
}

// 更新popover位置
let updatePopoverPosition = async () => {
  if (!popover.value && !input.value) {
    return;
  }

  // 等待dom渲染完
  await nextTick()
  // 窗口高度
  let windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
  // 输入框在屏幕中的绝对高度(到屏幕顶部)
  let inputHeight = input.value.getBoundingClientRect().top;
  // 输入框屏幕中绝对高度 + 选择弹框本身高度 + 输入框本身高度 不超出屏幕就在输入框下方显示
  if (inputHeight + popover.value.clientHeight + input.value.clientHeight < windowHeight) {
    popover.value.style.top = inputHeight + input.value.clientHeight + 3 + 'px'; // 输入框下面
    popover.value.style.left = input.value.getBoundingClientRect().left + 'px';
  }
  // 超出了屏幕就在输入框上方显示
  else {
    popover.value.style.top = inputHeight - 3 - popover.value.clientHeight + 'px';
    popover.value.style.left = input.value.getBoundingClientRect().left + 'px';
  }
}

// 输入数据时,更新过滤数据
let handleInput = (val) => {
  inputing.value = true;
  if (!val) {
    visibleList.value = props.list; // 没有值直接显示全部
  } else {
    visibleList.value = props.list.filter(item => {
      return item.label.toString().includes(val) // || item.value.toString().includes(val.toUpperCase());
    })
  }
  updatePopoverPosition();
};

// 输入框失去焦点
let handleBlur = () => {
  inputing.value = false;
};

// 输入框获取焦点
let handleFocus = () => {
  handleInput(tempValue.value)
};
// 选择数据,更新输入框显示值及组件绑定的值
let handleSelect = (item) => {
  tempValue.value = item.label ? item.label : item.value;
  emit('update:value', item.value)
  selecting.value = false;
};

// 鼠标进入下拉框
let mouseMove = () => {
  selecting.value = true;
};

// 鼠标移出下拉框
let mouseLeave = () => {
  selecting.value = false;
}

// 键盘按下Enter
let handleEnter = (e) => {
  if (e.keyCode === 13 && props.enterCreate) { // 回车键 且 启用
    emit('update:value', tempValue.value)
    selecting.value = false;
    inputing.value = false;
    input.value.blur(); // 失去焦点
  }
}
</script>
<style lang="scss" scoped>
.main {
  position: relative;

  // 输入框样式
  .input {
    border: 1px solid #c4c4c4;
    border-radius: 3px;
    padding: 3px 10px;
    outline: none;
    font-size: 12px;
    line-height: 30px;
    height: 30px;
    box-sizing: border-box;

    &:focus {
      border-color: rgb(21, 187, 187);
    }
  }

  // popover样式
  .popover {
    white-space: normal;
    margin-top: 10px;
    padding: 10px 0;
    border: 1px solid #c4c4c4;
    border-radius: 5px;
    box-shadow: #a0a0a0 0px 0px 6px;
    max-height: 200px;
    display: flex;
    flex-direction: column;
    min-height: 30px;
    background: #ffff;
    overflow: auto;
    z-index: 2023;
    position: fixed;
    font-size: 12px;
    margin: 0 auto;
    min-width: 100px;
    width: fit-content;

    .item {
      line-height: 20px;
      min-height: 20px;
      padding: 3px 10px;
      word-break: keep-all;
    }

    .item:hover {
      cursor: pointer;
      background: rgba(89, 183, 238, 0.4);
    }
  }

  .popover::-webkit-scrollbar {
    width: 5px;
    height: 10%
  }

  .popover::-webkit-scrollbar-track {
    background-color: #f1f1f1;
    border-radius: 10px;

  }

  /* 滚动条的滑轨背景颜色 */
  .popover::-webkit-scrollbar-thumb {
    background-color: #b2b4c0;
    border-radius: 10px;
  }
}
</style>

父组件调用
test.vue文章来源地址https://www.toymoban.com/news/detail-713186.html

<template>
    <div>
        测试值:{{ value }}
        <MyInput v-model:value="value" :list="list" :enterCreate="true"></MyInput>
    </div>
</template>
<script setup>
import { ref, reactive } from 'vue';

const list = reactive([
    { label: 'AA', value: 11 },
    { label: 'BB', value: 22 },
    { label: 'CC', value: 33 },
    { label: 'DD', value: 44 },
    { label: 'EE', value: 55 },
    { label: 'FF', value: 66 },
    { label: 'HH', value: 77 },
    { label: 'II', value: 88 },
    { label: 'JJ', value: 99 },
]);
const map = {};
let value = ref('11')
</script>

到了这里,关于vue3 实现选择输入框的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端Vue自定义支付密码输入键盘Keyboard和支付设置输入框Input

    前端Vue自定义支付密码输入键盘Keyboard和支付设置输入框Input, 阅读全文下载完整代码请关注微信公众号: 前端组件开发 效果图如下: 使用方法 HTML代码实现部分

    2024年02月10日
    浏览(52)
  • 【踩坑笔记】vue3 element-plus el-input 无法输入问题

    原因是 el-form 的 v-model=\\\"loginForm\\\" ref=\\\"loginForm\\\" 在vue3中值不能相同 把ref去掉或者改名即可 这是js的代码( 对象记得用reactive,不然也会无法输入 ) 这个是可以输入的 这是无法输入的 就改了个ref

    2024年02月11日
    浏览(55)
  • vue去掉所有输入框两边空格,封装指令去空格,支持Vue2和Vue3,ElementUI Input去空格

    就是页面很多表单输入框,期望在提交的时候,都要把用户两边的空格去掉 ❌使用 vue 的指令 .trim 去掉空格 中间会输入不了空格, 比如我想输入 你好啊 中国 , 这中间的空格输入不了,只能变成 你好啊中国 ❌在提交的时候使用 trim() 方法去两边空格 需要一个个字段的添加,

    2024年02月14日
    浏览(49)
  • 前端vue uni-app基于原生input组件的增强简单通用实用输入框

    随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身。通过组件化开发,可以有效实现单独开发,单独维护,而且他们之间可以随

    2024年02月04日
    浏览(45)
  • js监听input输入事件及使用防抖封装函数处理的实现

    循序渐进: 1.实现input框的输入监听事件: 2.防抖函数 防抖函数的目的:为了限制函数的执行频率而出现,优化解决函数触发频率过高导致延迟及假死卡顿等bug的出现。大多用在查询和提交功能上。 设置时间内多次点击或者输入只会执行最后一次点击或者输入; 代码: 3.i

    2024年02月12日
    浏览(40)
  • Vue实现多个input输入,光标自动聚焦到下一个input

    遇到一个需求,需要实现和移动端短信输入一样,输入内容后,光标会进入下一个输入框 需要用到2个事件  keydown事件发生在键盘的键被按下的时候 keyup  事件在按键被释放的时候触发

    2024年02月20日
    浏览(38)
  • 前端技术Html,Css,JavaScript,Vue3

    1.基本标签 2.文本格式化 3.链接 4.图片 5.无序列表 6.有序列表 7.表格 8.表单 1.选择器 2.文本和字体 3.链接 4.隐藏 5.定位position 6.浮动 7.对齐 8.图像 1.输出 2.函数 3.常用事件 4.DOM 5.改变Html 6.DOM 元素 (节点) 尾部创建新的 HTML 元素 (节点) - appendChild() 头部创建新的 HTML 元素 (节点)

    2024年02月13日
    浏览(50)
  • vue3 antd项目实战——Form表单的提交与校验【v-model双向绑定input输入框、form表单数据,动态校验规则】

    本文依旧沿用 ant design vue 组件库和 ts 语言🔥🔥更多内容见Ant Design Vue官方文档 🔥🔥 vue3 antd项目实战——Form表单【后台管理系统 v-model数据的双向绑定,input输入框、Radio单选框的嵌套使用】 在上期文章中,我们完成了 UI界面的渲染 (渲染效果如下图),本期文章将带着大

    2023年04月22日
    浏览(84)
  • Vue3+Vite连接高德地图JS API——地图显示、输入搜索

    1、进入高德地图API官网(https://lbs.amap.com/): 2、注册登录。 3、进入控制台。 4、点击“应用管理”,点击“我的应用”,创建新应用。 5、添加Key,服务平台选择“Web端(JS API)”,白名单不要填写,勾选阅读并同意。 点击提交后,就能看到Key已经生成,记住这里的Key和安

    2024年01月17日
    浏览(44)
  • 【前端技术】Vue3 01:初识 Vue.js

    Vue 可以说是非常流行了,至少在国内是这样,他是个轻量级的 JavaScript 框架,非常适合构建大型和中小型的 Web 应用程序,如果想和前端打交道,应该绕不过这个框架吧。 目录 1 Vue.js 介绍 2  IDE 选择 2.1 vscode 2.2 WebStorm 2.3 Eclipse 3  创建 Vue 应用 3.1 本地脚手架创建 ① 安装

    2024年02月02日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包