v-model 的使用
1. v-model 的基本使用
1.1 v-model 是一个语法糖
<template>
<input :value="text" @input="event => text = event.target.value" />
<input v-model="text" /> <!-- 这一行的意思和上一行是一样的 -->
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
1.2 checkbox 复选框的使用
<template>
<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>
</template>
<script setup>
import { ref } from 'vue'
const checkedNames = ref([])
</script>
注意这里的 checkedNames
只能是数组, 相应的结果就是选中的 input
所对应的 value
所构成的数组. 如果是其他类型, 则会被转换为 true/false
1.3 radio 单选框的使用
<template>
<div>Checked names: {{ checkedNames }}</div>
<input type="radio" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="radio" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="radio" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
</template>
<script setup>
import { ref } from 'vue'
const checkedNames = ref('')
</script>
这里的 checkNames
为空字符串, 相应的结果就是选中的 input
所对应的 value
, 如果 checkNames
对应的是其他的类型, 其结果也是一样的
1.4 select 选择器的使用
<script setup>
import { ref } from 'vue'
const selected = ref('')
</script>
<template>
<span> Selected: {{ selected }}</span>
<select v-model="selected">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</template>
为 selected
赋予 <option disabled value="">Please select one</option>
相同的值可以使得 <select>
在初始的时候默认显示这个不会被选中的 <option>
1.5 修饰符
.lazy
: 一般情况下,v-model
会在input
事件触发后更新数据, 而在使用.lazy
修饰符进行修饰后, 其会在change
事件触发后再更新(change
事件触发的前提是失去焦点).number
: 用户的输入会自动转换为number
类型.trim
: 去除开始和结束两边的空白
2. 对组件使用 v-model 以及 v-model 的实现
2.1 实现效果
在父组件中定义一个变量 componentText
, 且父组件会将 componentText
传递给两个子组件通过 input
进行展示. 而子组件也可以在 input
中对值进行修改, 这个修改会传递到父组件上, 使得父组件对 componentText
进行修改, 然后再次作用到子组件上
最终的效果就是: 两个 input
中的值始终保持一致
2.2 具体实现--父子组件间的传值
2.2.1 App 组件
<!-- 父组件 -->
<template>
v-model: <CustomInput v-model:mv="componentText" />
<!-- 可以通过参数指定传递给子组件的变量名 -->
<!-- 如果没有指定变量名, 则默认变量名为 modelValue -->
<hr />
v-model 的 :valueName + @definedEvent 实现:
<CustomInput :mv="componentText" @update:mv="(newValue) => (componentText = newValue)" />
</template>
<script lang="ts" setup>
import CustomInput from './CustomInput.vue'
import { ref } from 'vue'
const componentText = ref('')
</script>
2.2.2 custom-input 组件
<!-- 子组件 -->
<template>
<input :value="mv" @input="handleUpdate" />
</template>
<script lang="ts" setup>
defineProps(['mv'])
// 定义 update:mv 事件(如果不使用 v-model, 则事件名可以自定义, 不一定要是 update:xxx 形式)
const emit = defineEmits(['update:mv'])
const handleUpdate = (event: Event) => {
emit('update:mv', (event.target as HTMLInputElement).value)
}
</script>
currentTarget
和 target
的区别
currentTarget
: 指向的是所绑定事件的元素target
: 指向的是触发事件的元素