vue知识点(2)
表单输入绑定
表单输入绑定是通过 v-model
指令实现的。可以用于各种表单元素,如 <input>
、<textarea>
、<select>
等。
文本输入框
<template>
<input v-model="text" placeholder="请输入文本" />
<div>{{ text }}</div>
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
多行文本输入框
<template>
<textarea v-model="text" placeholder="请输入多行文本" ></textarea>
<div>{{ text }}</div>
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
复选框
单个复选框绑定布尔值
<template>
<input type="checkbox" v-model="isChecked" />
<label>是否同意:{{ isChecked }}</label>
</template>
<script setup>
import { ref } from 'vue'
const isChecked = ref(false)
</script>
多个复选框绑定数组
<template>
<input type="checkbox" v-model="selectedFruits" value="苹果" />
<label>苹果</label>
<input type="checkbox" v-model="selectedFruits" value="香蕉" />
<label>香蕉</label>
<input type="checkbox" v-model="selectedFruits" value="橙子" />
<label>橙子</label>
<div>
<p>你选中的水果是:{{ selectedFruits }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedFruits = ref([])
</script>
单选框
<template>
<input type="radio" v-model="selectedFruit" value="苹果" />
<label>苹果</label>
<input type="radio" v-model="selectedFruit" value="香蕉" />
<label>香蕉</label>
<input type="radio" v-model="selectedFruit" value="橙子" />
<label>橙子</label>
<div>
<p>你选中的水果是:{{ selectedFruit }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedFruit = ref('')
</script>
下拉选择框
单选
<template>
<select v-model="selectedFruit">
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="橙子">橙子</option>
</select>
<div>
<p>你选中的水果是:{{ selectedFruit }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedFruit = ref('')
</script>
多选
<template>
//multiple启用多选功能,按住 Ctrl 或 Command 键点击选项即可多选。
<select v-model="selectedFruits" multiple>
<option value="苹果">苹果</option>
<option value="香蕉">香蕉</option>
<option value="橙子">橙子</option>
</select>
<p>你选中的水果是:{{ selectedFruits }}</p>
</template>
<script setup>
import { ref } from 'vue'
const selectedFruits = ref([])
</script>
修饰符
Vue 为 v-model
提供了一些修饰符,用于控制数据的更新行为。
.lazy
默认情况下,v-model 会在 input 事件触发时同步数据。使用 .lazy 修饰符后,数据会在 change 事件触发时同步(通常在输入框失去焦点时)。
//在 "change" 事件后同步更新而不是 "input"
<input v-model.lazy="message" placeholder="请输入内容">
.number
将用户输入的值自动转换为数字类型。
//number 修饰符会在输入框有 type="number" 时自动启用
<input v-model.number="age" type="number" placeholder="请输入年龄">
.trim
自动去除用户输入内容的首尾空白字符。
<input v-model.trim="message" placeholder="请输入内容">
自定义组件的 v-model
//自定义输入组件
<template>
<div>
<CustomInput v-model="message"></CustomInput>
<p>输入的内容是:{{ message }}</p>
</div>
</template>
<script setup>
import CustomInput from '../components/CustomInput.vue'
import { ref } from 'vue'
const message = ref('')
</script>
//在 CustomInput.vue 中
<template>
<input
:value="modelValue"
//事件监听器,用于监听输入框的输入事件。通过 $emit 方法向上级组件发送一个名为 update:modelValue 的自定义事件,并将输入框当前的值 ($event.target.value) 作为参数传递出去。
@input="$emit('update:modelValue', $event.target.value)"
placeholder="请输入内容"
/>
</template>
<script setup>
//用于定义组件接收的属性。
defineProps(['modelValue'])
//用于定义组件可以触发的自定义事件。
defineEmits(['update:modelValue'])
</script>
侦听器
用于监听数据变化并执行特定的逻辑。使用 watch
函数监听一个特定的数据属性,并在该属性发生变化时执行回调函数。
<template>
<div>
<input v-model="message" placeholder="请输入内容" />
<p>新值:{{ updatedMessage }}</p>
<p>旧值:{{ oldMessage }}</p>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
const message = ref('')
const updatedMessage = ref('')
const oldMessage = ref('')
//用于监听 message 数据的变化,当 message 数据发生变化时,会触发回调函数。
watch(message, (newVal, oldVal) => {
updatedMessage.value = newVal
oldMessage.value = oldVal
})
</script>
watch
的第一个参数可以是不同形式的“数据源”:它可以是一个 ref
(包括计算属性)、一个响应式对象、一个 getter
函数、或多个数据源组成的数组。
<template>
<div>
<button @click="handleClick">点击++</button>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
const x = ref(0)
const y = ref(0)
const handleClick = () => {
x.value++
y.value++
}
// 单个 ref
watch(x, (newX) => {
console.log(`x is ${newX}`)
})
// getter 函数
watch(
() => x.value + y.value,
(sum) => {
console.log(`sum of x + y is: ${sum}`)
}
)
// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
console.log(`x is ${newX} and y is ${newY}`)
})
</script>
但是,不能直接侦听响应式对象的属性值
const obj = reactive({ count: 0 })
// 错误,因为 watch() 得到的参数是一个 number
watch(obj.count, (count) => {
console.log(`Count is: ${count}`)
})
应该用一个返回该属性的 getter 函数
// 提供一个 getter 函数
watch(
() => obj.count,
(count) => {
console.log(`Count is: ${count}`)
}
)
深层侦听器
直接给 watch()
传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发。
<template>
<div>
<button @click="handleClick">点击++</button>
</div>
</template>
<script setup>
import { ref, watch, reactive } from 'vue'
const obj = reactive({ count: 0, name: '张三' })
const handleClick = () => {
obj.count++
}
watch(obj, (newValue, oldValue) => {
// 在嵌套的属性变更时触发
// 注意:`newValue` 此处和 `oldValue` 是相等的
// 因为它们是同一个对象!
console.log(newValue, oldValue)
})
</script>
显式地加上 deep
选项,强制转成深层侦听器
<template>
<div>
<button @click="handleClick">点击</button>
</div>
</template>
<script setup>
import { ref, watch, reactive } from 'vue'
const state = reactive({
someObject: {
count: 0,
name: '张三',
info: {
address: '张家口',
},
},
})
const handleClick = () => {
// 如果整个对象被替换,`newValue` 和 `oldValue` 是不相等的
state.someObject = {
count: 1,
name: '王五',
}
// 如果只修改对象的属性,`newValue` 此处和 `oldValue` 是相等的
// 只有加上 `deep: true` 才会改变 address 的值
state.someObject.info = {
address: '王家口',
}
}
watch(
() => state.someObject,
(newValue, oldValue) => {
// 注意:`newValue` 此处和 `oldValue` 是相等的
// *除非* state.someObject 被整个替换了,`newValue` 和 `oldValue` 才会不相等
console.log(newValue, oldValue)
},
{ deep: true }
)
</script>
即时回调的侦听器
默认情况下,侦听器只有在监听的数据发生变化时才会触发。如果希望侦听器在初始化时立即执行一次,可以使用 immediate
选项。
<template>
<div>
<button @click="handleClick">点击</button>
</div>
</template>
<script setup>
import { ref, watch, reactive } from 'vue'
const source = ref(0)
const handleClick = () => {
source.value++
}
watch(
source,
(newValue, oldValue) => {
// 立即执行,且当 `source` 改变时再次执行
console.log(newValue, oldValue)
if (newValue === 1) {
source.value = 0
}
},
{ immediate: true }
)
</script>
watchEffect
用于自动追踪依赖并执行副作用的函数。它类似于 watch,但更加简洁,适合用于不需要显式指定监听数据,而是自动追踪回调函数中使用的响应式数据的场景。
在回调函数中自动追踪所有使用的响应式数据。当这些数据发生变化时,回调函数会重新执行。
<template>
<div>
<button @click="handleClick">点击</button>
</div>
</template>
<script setup>
import { ref, watchEffect } from 'vue'
const source = ref(0)
const handleClick = () => {
source.value++
}
watchEffect(() => {
console.log(source.value)
})
</script>
停止侦听器
同步语句创建的侦听器,会自动绑定到宿主组件实例上,并且会在宿主组件卸载时自动停止。
如果用异步回调创建一个侦听器,那么它不会绑定到当前组件上,你必须手动停止它,以防内存泄漏。
<template>
<div>
<button @click="handleClick">点击</button>
</div>
</template>
<script setup>
import { ref, watchEffect } from 'vue'
const source = ref(0)
const handleClick = () => {
source.value++
}
let stop = null
stop = watchEffect(() => {
console.log(source.value)
if (source.value === 5) {
stop()
console.log('侦听已停止')
}
})
// 5 秒后停止侦听
setTimeout(() => {
stop()
console.log('侦听已停止')
}, 5000)
</script>