阿卡不拉阿卡不拉
Vue3
阿卡的博客
Vue3
阿卡的博客
  • Vue3

    • 快速入门

      • 搭建工程 👌
      • 模板语法
      • 响应式基础
      • 响应式常用 API
      • 计算属性
      • 类与样式绑定
      • 条件和列表渲染
      • 事件处理
      • 表单处理
      • 生命周期
      • 侦听器
      • 组件介绍
      • Props
      • 自定义事件
      • 组件v-model
      • 插槽
      • 前端路由介绍
      • KeepAlive内置组件
      • 状态管理库
      • 组件库介绍
    • 深入本质

      • 虚拟DOM本质
      • 模板的本质
      • 组件树和虚拟DOM树
      • 数据拦截的本质
      • 响应式数据的本质
      • 响应式的本质
      • 响应式和组件渲染
      • 实现响应式系统 1
      • 实现响应式系统 2
      • 图解EFFECT
      • 实现响应式系统 3
      • 手写computed
      • 手写watch
      • 指令的本质
      • 插槽的本质
      • v-model的本质
      • setup 语法标签
      • 组件生命周期
      • keepalive 生命周期
      • keepalive的本质
      • key的本质
    • 细节补充

      • 【Vue】属性透传
      • 【Vue】依赖注入
      • 【Vue】组合式函数 👌
      • 【Vue】自定义指令
      • 【Vue】插件
      • 【Vue】Transition
      • 【Vue】TransitionGroup
      • 【Vue】Teleport
      • 【Vue】异步组件
      • 【Vue】Suspense
      • 【Router】路由模式
      • 【Router】路由零碎知识
      • 【Router】路由匹配语法
      • 【Router】路由组件传参
      • 【Router】内置组件和函数
      • 【Router】导航守卫
      • 【Router】过渡特效
      • 【Router】滚动行为
      • 【Router】动态路由
      • 【State】通信方式总结
      • 【State】Pinia 自定义插件
      • 【场景】封装树形组件
      • 【场景】自定义 ref 实现防抖
      • 【场景】懒加载
      • 【场景】虚拟列表
      • 【场景】虚拟列表优化
      • 【第三方库】VueUse
      • 【第三方库】vuedragable
      • 【第三方库】vue-drag-resize
      • 【第三方库】vue-chartjs
      • 【第三方库】vuelidate
      • 【第三方库】vue3-lazyload
      • 【场景】Websocket 聊天室
      • 【Vite】✨ 认识 Vite👌
      • 【Vite】配置文件 👌
      • 【Vite】✨ 依赖预构建 👌
      • 【Vite】构建生产版本 👌
      • 【Vite】环境变量与模式
      • 【Vite】CLI
      • 【Vite】Vite 插件
  • 笔面试

    • HTML

      • HTML 面试题汇总
      • 文档声明
      • 语义化
      • W3C 标准组织
      • SEO
      • iframe
      • 微格式
      • 替换元素
      • 页面可见性
    • CSS

      • CSS 面试题汇总
      • CSS 单位总结
      • 居中方式总结
      • 隐藏元素方式总结
      • 浮动
      • 定位总结
      • BFC
      • CSS 属性计算过程
      • CSS 层叠继承规则总结
      • @import 指令
      • CSS3 calc 函数
      • CSS3 媒体查询
      • 过渡和动画事件
      • 渐进增强和优雅降级
      • CSS3 变形
      • 渐进式渲染
      • CSS 渲染性能优化
      • 层叠上下文
      • CSS3 遮罩
    • JavaScript

      • JavaScript 面试题汇总
      • ✨ let、var、const 的区别
      • JS中的数据类型
      • 包装类型
      • 数据类型的转换
      • 运算符
      • ✨ 原型链
      • ✨ this 指向
      • ✨ 垃圾回收与内存泄漏
      • ✨ 执行栈和执行上下文
      • ✨ 作用域和作用域链
      • ✨ 闭包
      • DOM 事件的注册和移除
      • DOM 事件的传播机制
      • 阻止事件默认行为
      • 递归
      • ✨ 属性描述符
      • class 和构造函数区别
      • 浮点数精度问题
      • 严格模式
      • ✨ 函数防抖和节流
      • ✨ WeakSet 和 WeakMap
      • ✨ 深浅拷贝
      • 函数柯里化
      • Node 事件循环
      • 尺寸和位置
    • 浏览器

      • 浏览器面试题汇总
      • ✨ 浏览器的渲染流程
      • ✨ 资源提示关键词
      • 浏览器的组成部分
      • IndexedDB
      • ✨ File API
      • ✨ 浏览器缓存
      • ✨ 浏览器跨标签页通信
      • Web Worker
    • 网络

      • 网络面试题汇总
      • 五层网络模型 👌
      • 常见请求方法 👌
      • ✨cookie👌
      • 面试题
      • 加密
      • ✨JWT👌
      • ✨ 同源策略及跨域问题 👌
      • 文件上传
      • ✨ 输入 url 地址之后
      • 文件下载
      • ✨ session
      • ✨ TCP
      • ✨ CSRF 攻击
      • ✨XSS 攻击 👌
      • ✨ 网络性能优化
      • 断点续传
      • 域名和 DNS
      • SSL、TLS、HTTPS 的关系
      • ✨ HTTP 各版本差异 👌
      • HTTP 缓存协议
      • ✨ WebSocket
    • 工程化

      • CMJ 和 ESM
      • npx
      • ESLint
    • Vue2

      • Vue 面试题汇总相关
      • 组件通信方式总结
      • 虚拟 DOM
      • v-model
      • 数据响应式原理
      • diff
      • 生命周期详解
      • computed
      • 过滤器
      • 作用域插槽
      • 过度和动画
      • 优化
      • keep-alive
      • 长列表优化
      • 其他 API
      • 模式和环境变量
      • 更多配置
      • 更多命令
      • 嵌套路由
      • 路由切换动画
    • Vue3

      • ✨ Vue3 整体变化 👌
      • ✨ Vue3 响应式变化 👌
      • ✨ nextTick 实现原理 👌
      • 两道代码题 👌
      • Vue 运行机制
      • 渲染器核心功能
      • 事件绑定与更新

表单处理

表单元素的数据绑定

文本框

下面是一个文本框和数据进行绑定的例子:

<template>
    <input
        type="text"
        :value="textContent"
        @input="(e) => (textContent = e.target.value)"
    />
    <p>你当前输入的内容为:{{ textContent }}</p>
</template>

<script setup>
    import { ref } from "vue";
    const textContent = ref("");
</script>

<style scoped></style>

上面的例子我们让文本库和 ref 数据进行了绑定,用户在输入内容的时候,会去更新 textContent 这个 ref 数据,而 ref 数据的变化又会影响文本框本身的 value 值。这其实就是一个双向绑定的例子。

上面的例子虽然实现了双向绑定,但是写起来比较麻烦,因此 Vue 提供了一个内置的指令 v-model

<template>
    <input type="text" v-model="textContent" />
    <p>你当前输入的内容为:{{ textContent }}</p>
</template>

<script setup>
    import { ref } from "vue";
    const textContent = ref("");
</script>

<style scoped></style>

上面的例子使用了 v-model 来进行双向绑定,textContent 的变化会影响文本框的值,文本框的值也会影响 textContent.

使用 v-model 的好处在于:

  1. 简化了书写
  2. 根据所使用的元素自动的选择对应的属性以及事件组合
    • input 或者 textarea,元素会绑定 input 事件,绑定的值是 value
    • 如果是单选框或者复选框,背后绑定的事件是 change 事件,绑定的值 checked
    • select 下拉列表绑定的也是 change 事件,绑定的值是 value

文本域

文本域就是多行文本,对应的标签为 textarea

<template>
    <textarea cols="30" rows="10" v-model="textContent"></textarea>
    <p>你当前输入的内容为:{{ textContent }}</p>
</template>

<script setup>
    import { ref } from "vue";
    const textContent = ref("");
</script>

<style scoped></style>

复选框

单一的复选框,可以使用 v-model 去绑定一个 ref 类型的布尔值,布尔值为 true 表示选择中,false 表示未选中

<template>
    <input type="checkbox" v-model="checked" />
    <button @click="checked = !checked">切换选中</button>
</template>

<script setup>
    import { ref } from "vue";
    const checked = ref(true);
</script>

<style scoped></style>

在上面的例子中,布尔值 true 是选中,false 是未选中,但是这个真假值是可以自定义:

<template>
    <input
        type="checkbox"
        v-model="checked"
        :true-value="customTrue"
        :false-value="customFalse"
    />
    <button @click="toggle">切换选中</button>
</template>

<script setup>
    import { ref } from "vue";
    const checked = ref("yes");
    // 现在相当于是自定义什么值是选中,什么值是未选中
    // 默认true是选中,false是未选中
    // 现在是yes是选中,no是未选中
    const customTrue = ref("yes");
    const customFalse = ref("no");
    function toggle() {
        checked.value === "yes"
            ? (checked.value = "no")
            : (checked.value = "yes");
    }
</script>

<style scoped></style>

有些时候我们有多个复选框,这个时候,可以将多个复选框绑定到同一个数组或者集合的值:

<template>
    <div v-for="(item, index) in arr" :key="index">
        <label for="item.id">{{ item.title }}</label>
        <input
            type="checkbox"
            v-model="hobby"
            :id="item.id"
            :value="item.value"
        />
    </div>
    <p>{{ message }}</p>
</template>

<script setup>
    import { ref, computed } from "vue";
    const hobby = ref([]);
    const arr = ref([
        { id: "swim", title: "游泳", value: "游个泳" },
        { id: "run", title: "跑步", value: "跑个步" },
        { id: "game", title: "游戏", value: "玩个游戏" },
        { id: "music", title: "音乐", value: "听个音乐" },
        { id: "movie", title: "电影", value: "看个电影" },
    ]);
    const message = computed(() => {
        // 根据 hobby 的值进行二次计算
        if (hobby.value.length === 0) return "请选择爱好";
        else return `您选择了${hobby.value.join("、")}`;
    });
</script>

<style scoped></style>

在上面的例子中,checkbox 所绑定的数据不再是一个布尔值,而是一个数组(集合),那么当该复选框被选中的时候,该复选框所对应的值就会被加入到数组里面。复选框是否被选中取决于复选框对应的值是否存在与绑定的数组(集合)中。

单选框

<template>
    <label for="male">男</label>
    <input type="radio" id="male" v-model="gender" value="男" />
    <label for="female">女</label>
    <input type="radio" id="female" v-model="gender" value="女" />
    <label for="secret">保密</label>
    <input type="radio" id="secret" v-model="gender" value="保密" />
</template>

<script setup>
    import { ref } from "vue";
    const gender = ref("保密");
    setTimeout(() => {
        gender.value = "男";
    }, 3000);
</script>

<style scoped></style>

上面的例子演示了单选框如何进行双向绑定,哪一个单选框被选中取决于 gender 的值和哪一个单选框对应的值相同。

下拉列表

下拉列表在进行双向绑定的时候,v-model 是写在 select 标签上面:

<template>
    <!-- 下拉列表列表是单选的话,v-model 绑定的值是一个字符串,这个字符串是 option 的 value 值 -->
    <select v-model="hometown1">
        <option value="" disabled>请选择</option>
        <option
            v-for="(item, index) in hometownList"
            :key="index"
            :value="item.key"
        >
            {{ item.value }}
        </option>
    </select>
    <p>您选择的家乡为:{{ hometown1 }}</p>
    <!-- 如果下拉列表是多选的话,v-model 绑定的值是一个数组,这个数组是 option 的 value 值组成的数组 -->
    <select v-model="hometown2" multiple>
        <option value="" disabled>请选择</option>
        <option
            v-for="(item, index) in hometownList"
            :key="index"
            :value="item.key"
        >
            {{ item.value }}
        </option>
    </select>
    <p>您选择的家乡为:{{ hometown2 }}</p>
</template>

<script setup>
    import { ref } from "vue";
    const hometown1 = ref("");
    const hometown2 = ref([]);
    const hometownList = ref([
        { key: "成都", value: "成都" },
        { key: "帝都", value: "北京" },
        { key: "魔都", value: "上海" },
        { key: "妖都", value: "广州" },
        { key: "陪都", value: "重庆" },
    ]);
</script>

<style scoped></style>

注意下拉列表根据是单选还是多选,v-model 所绑定的值的类型不一样,单选绑定字符串,多选绑定数组。

表单相关修饰符

  • lazy:默认情况下,v-model 会在每次 input 事件触发时就更新数据,lazy 修饰符可以改为 change 事件触发后才更新数据
  • number:将用户输入的内容从字符串转为 number 类型
  • trim:去除输入的内容的两端的空格
<template>
    <!-- lazy修饰符演示 -->
    <input type="text" v-model.lazy="mess1" />
    <p>你输入的是:{{ mess1 }}</p>
    <p>类型为{{ typeof mess1 }}</p>
    <p>长度为{{ mess1.length }}</p>

    <!-- number修饰符演示 -->
    <input type="text" v-model.number="mess2" />
    <p>你输入的是:{{ mess2 }}</p>
    <p>类型为{{ typeof mess2 }}</p>
    <p>长度为{{ mess2.length }}</p>

    <!-- trim修饰符演示 -->
    <input type="text" v-model.trim="mess3" />
    <p>你输入的是:{{ mess3 }}</p>
    <p>类型为{{ typeof mess3 }}</p>
    <p>长度为{{ mess3.length }}</p>
</template>

<script setup>
    import { ref } from "vue";
    const mess1 = ref("");
    const mess2 = ref("");
    const mess3 = ref("");
</script>

<style scoped></style>
最近更新:: 2025/7/9 07:29
Contributors: AK
Prev
事件处理
Next
生命周期