vue3【实用教程】v-model(原生标签和组件上使用 v-model ,v-model 参数,绑定多个 v-model ,v-model 内置修饰符,自定义 v-model 修饰符等)

v-model 用于实现数据的双向绑定,仅可用于 <input><select><textarea> 和组件。

在原生元素上使用 v-model

单行输入框 input

<input v-model="searchText" />
  • 修改输入框中的内容会触发变量 searchText 同步修改
  • 修改 searchText 的值,也会触发输入框中内容同步修改

在这里插入图片描述

<!-- 组合式 API vue3.4+ -->
<script setup>
let searchText = defineModel({ default: "搜索的关键字" });

let changeSearchText = () => {
  searchText.value = "日出";
};
</script>

<template>
  <input v-model="searchText" />
  <p>searchText的值为:{{ searchText }}</p>
  <button @click="changeSearchText">将 searchText 修改为 “日出”</button>
</template>
<!-- 选项式 API -->
<template>
  <input v-model="searchText" />
  <p>searchText的值为:{{ searchText }}</p>
  <button @click="changeSearchText">将 searchText 修改为 “日出”</button>
</template>

<script>
export default {
  data() {
    return {
      searchText: "搜索的关键字",
    };
  },
  methods: {
    changeSearchText() {
      this.searchText = "日出";
    },
  },
};
</script>

多行输入框 textarea

<textarea v-model="text"></textarea>

在这里插入图片描述

单选 radio

<div>Picked: {{ picked }}</div>

<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>

<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>

在这里插入图片描述

多选 checkbox

单个复选框(布尔值)

<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>

在这里插入图片描述
可以通过 Vue 特有的属性 true-valuefalse-value 改变绑定的值

<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no" />

多个复选框(数组)

const checkedNames = ref([])
<div>Checked names: {{ checkedNames }}</div>

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames" />
<label for="jack">Jack</label>

<input type="checkbox" id="john" value="John" v-model="checkedNames" />
<label for="john">John</label>

<input type="checkbox" id="mike" value="Mike" v-model="checkedNames" />
<label for="mike">Mike</label>

在这里插入图片描述

下拉单选 select

  • 提供一个空值的禁用选项( 避免 iOS 上用户无法选择第一项)

  • 选项的 value 可以是对象

    <option :value="{ number: 123 }">123</option>
    
<div>Selected: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">Please select one</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

在这里插入图片描述

多选 select

绑定数组

<div>Selected: {{ selected }}</div>

<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

按Ctrl 多选
在这里插入图片描述

在子组件上使用 v-model

<CustomInput v-model="searchText" />

相当于以下方式的简写

<CustomInput :modelValue="searchText" @update:modelValue="searchText= $event" />
  • 给子组件传入了名为 modelValue 的 prop
  • 父组件监听了子组件的自定义事件 update:modelValue

【推荐】子组件使用 defineModel() 宏实现 v-model

CustomInput.vue

<!-- 组合式 API vue3.4+ -->
<script setup>
const model = defineModel()
</script>

<template>
	<input v-model="model">
</template>

defineModel() 返回的值是一个 ref

  • 它的 .value 和父组件的 v-model 的值同步
  • 当它被子组件变更时,会触发父组件绑定的值一起更新

defineModel 声明了一个父组件的传值 prop,可以限制其必填,设定其默认值(若子组件设定了默认值,则父组件也需指定默认值,否则父子组件数据不同步!)

// 使 v-model 必填
const model = defineModel({ required: true })
// 提供一个默认值
const model = defineModel({ default: 0 })

子组件使用 value 和 input 事件实现 v-model

CustomInput.vue

<!-- 选项式 API -->
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

子组件使用 computed 实现 v-model

CustomInput.vue

<!-- 选项式 API -->
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  computed: {
    value: {
      get() {
        return this.modelValue
      },
      set(value) {
        this.$emit('update:modelValue', value)
      }
    }
  }
}
</script>

<template>
  <input v-model="value" />
</template>

给 v-model 添加参数

可以自定义传给子组件的 prop名称和监听的自定义事件名,用法如下:

<MyComponent v-model:title="bookTitle" />
  • 给子组件传入了名为 title 的 prop
  • 父组件监听了子组件的自定义事件 update:title

v-model 这种无参数的写法,其实是 v-model:modelValue 的简写。
或者可以理解为 modelValue 是 v-model 的默认参数。

子组件的具体实现方法如下:

MyComponent.vue

<!-- 组合式 API vue3.4+ -->
<script setup>
const title = defineModel('title')
</script>

<template>
  <input type="text" v-model="title" />
</template>
<!-- 选项式 API -->
<script>
export default {
  props: ['title'],
  emits: ['update:title']
}
</script>

<template>
  <input
    type="text"
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>
  • v-model 的参数,需作为 defineModel() 的第一个参数,以字符串的类型传入。

  • 若有更多 prop 选项,需在 v-model 的参数之后

    const title = defineModel('title', { required: true })
    

绑定多个 v-model

vue2 中,每个标签/组件只能绑定一个 v-model
但 vue3 中,因 v-model 可以添加参数,支持绑定多个 v-model

<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>

UserName.vue

<!-- 组合式 API vue3.4+ -->
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
</script>

<template>
  <input type="text" v-model="firstName" />
  <input type="text" v-model="lastName" />
</template>
<!-- 选项式 API -->
<script>
export default {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName']
}
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

v-model 的内置修饰符

.lazy

延迟触发数据的更新

  • v-model 默认会在每次 input 事件后更新数据 (IME 拼字阶段的状态例外)
  • .lazy 会将数据更新延迟到每次 change 事件后
<!-- 在 "change" 事件后同步更新而不是 "input" 事件-->
<input v-model.lazy="msg" />

.number

将用户输入自动转换为数字

<input v-model.number="age" />
  • 如果值无法被 parseFloat() 处理,那么将返回原始值
  • 输入框有 type=“number” 时会自动启用 .number 修饰符

.trim

自动去除用户输入内容中两端的空格

<input v-model.trim="msg" />

自定义 v-model 的修饰符

v-model 无参数时

.capitalize 为例:自动将第一个字母转为大写

<MyComponent v-model.capitalize="myText" />

具体实现详见注释

MyComponent.vue

<!-- 组合式 API vue3.4+ -->
<script setup>
const [model, modifiers] = defineModel({
  // 在set选项中,添加自定义修饰符的处理逻辑
  set(value) {
    // 判断 modifiers 中是否存在自定义的 capitalize 修饰符
    if (modifiers.capitalize) {
      // 当存在自定义的 capitalize 修饰符时,将第一个字母转为大写
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    // 返回按修饰符定义处理过的值
    return value
  }
})
</script>

<template>
  <input type="text" v-model="model" />
</template>
<!-- 选项式 API -->
<script>
export default {
  props: {
    modelValue: String,
    // 新增了名 modelModifiers 的 prop,用于获取自定义的修饰符
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  methods: {
    emitValue(e) {
      // 获取到原始值
      let value = e.target.value
      // 判断 modelModifiers 中是否存在自定义的 capitalize 修饰符
      if (this.modelModifiers.capitalize) {
        // 当存在自定义的 capitalize 修饰符时,将第一个字母转为大写
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      // 触发自定义事件,将按修饰符定义处理过的值,传给父组件
      this.$emit('update:modelValue', value)
    }
  }
}
</script>

<template>
  <input type="text" :value="modelValue" @input="emitValue" />
</template>

v-model 有参数时

<MyComponent v-model:title.capitalize="myText">

MyComponent.vue

<!-- 组合式 API vue3.4+ -->
<script setup>
const [title, titleModifiers] = defineModel({
  // 在set选项中,添加自定义修饰符的处理逻辑
  set(value) {
    // 判断 modifiers 中是否存在自定义的 capitalize 修饰符
    if (titleModifiers.capitalize) {
      // 当存在自定义的 capitalize 修饰符时,将第一个字母转为大写
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    // 返回按修饰符定义处理过的值
    return value
  }
})
</script>

<template>
  <input type="text" v-model="title" />
</template>
  <!-- 选项式 API -->
  props: ['title', 'titleModifiers'],
  emits: ['update:title'],

绑定多个带参数且自定义不同修饰符的 v-model 时

<UserName
  v-model:first-name.capitalize="first"
  v-model:last-name.uppercase="last"
/>

UserName.vue

// 组合式 API vue3.4+
const [firstName, firstNameModifiers] = defineModel({
  // 在set选项中,添加自定义修饰符的处理逻辑
  set(value) {
    if (firstNameModifiers.capitalize) {
      // 当存在自定义的 capitalize 修饰符时,将第一个字母转为大写
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    // 返回按修饰符定义处理过的值
    return value
  }
})

const [lastName, lastNameModifiers] = defineModel({
  // 在set选项中,添加自定义修饰符的处理逻辑
  set(value) {
    if (lastNameModifiers.uppercase) {
      // 当存在自定义的 uppercase 修饰符时,所有字母大写
      return value.toUpperCase()
    }
    // 返回按修饰符定义处理过的值
    return value
  }
})
  // 选项式 API
  props: {
    firstName: String,
    lastName: String,
    firstNameModifiers: {
      default: () => ({})
    },
    lastNameModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:firstName', 'update:lastName'],
  • 40
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Vue3中,可以通过使用多个v-model来实现父子组件之间的双向数据绑定。通过在父组件使用v-model指令并传递子组件的属性名,实现对子组件属性的修改和监听。在子组件中,通过接收props并使用$emit方法来触发父组件的更新事件。这样就可以实现多个v-model绑定。 例如,在Vue3中可以这样使用多个v-model绑定: ```html <template> <div> <test v-model:num1="num1" v-model:num2="num2"/> </div> </template> <script> import { ref } from 'vue'; export default { setup() { const num1 = ref(1); const num2 = ref(1); return { num1, num2 }; } } </script> <test> <div @click="incrNum1">{{ num1 }}</div> <div @click="incrNum2">{{ num2 }}</div> </test> ``` 在这个例子中,父组件使用v-model指令将num1和num2属性与子组件的num1和num2属性进行绑定。在子组件中,通过点击事件触发incrNum1和incrNum2方法,这两个方法通过$emit('update:num1', this.num1 + 1)和$emit('update:num2', this.num2 + 2)来更新父组件的num1和num2属性。 这样,当在子组件中点击对应的div时,父组件的num1和num2属性会更新,并且更新的值会同步到子组件中展示出来。这就实现了多个v-model绑定。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue3.0深入v-model以及使用多个v-model](https://blog.csdn.net/weixin_43845137/article/details/123534181)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [VUE3 之 多个 v-model 绑定及 v-model 修饰符使用](https://blog.csdn.net/u011181989/article/details/122705587)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朝阳39

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值