1. 基本概念
1.1 v-bind
- 单向数据绑定
- 从父组件向子组件传递数据
- 简写形式为
:
1.2 v-model
- 双向数据绑定
- 父子组件数据同步
- 本质是 v-bind 和 v-on 的语法糖
2. 基础用法对比
2.1 表单元素绑定
<!-- v-bind 示例 -->
<template>
<input :value="text" @input="text = $event.target.value" />
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
<!-- v-model 示例 -->
<template>
<input v-model="text" />
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
2.2 组件属性绑定
<!-- v-bind 方式 -->
<template>
<CustomInput
:value="searchText"
@input="searchText = $event"
/>
</template>
<!-- v-model 方式 -->
<template>
<CustomInput v-model="searchText" />
</template>
3. 主要区别
3.1 数据流向
<!-- v-bind: 单向数据流 -->
<ChildComponent
:title="pageTitle" <!-- 数据只能从父组件流向子组件 -->
/>
<!-- v-model: 双向数据流 -->
<ChildComponent
v-model="pageTitle" <!-- 数据可以双向同步 -->
/>
3.2 实现原理
<!-- v-bind 原理 -->
<ChildComponent :value="value" />
<!-- v-model 原理(等价于) -->
<ChildComponent
:modelValue="value"
@update:modelValue="value = $event"
/>
3.3 自定义组件实现对比
<!-- 使用 v-bind 的组件 -->
<template>
<div>
<input
:value="value"
@input="$emit('input', $event.target.value)"
/>
</div>
</template>
<script setup>
defineProps(['value'])
defineEmits(['input'])
</script>
<!-- 使用 v-model 的组件 -->
<template>
<div>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</div>
</template>
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
4. 使用场景对比
4.1 适合使用 v-bind 的场景
<!-- 1. 纯展示数据 -->
<template>
<div :class="className">
<h1 :title="headerTitle">{{ title }}</h1>
<img :src="imageUrl" :alt="imageAlt" />
</div>
</template>
<!-- 2. 传递回调函数 -->
<template>
<button :onClick="handleClick">点击</button>
</template>
<!-- 3. 动态属性 -->
<template>
<div :[dynamicProp]="value"></div>
</template>
4.2 适合使用 v-model 的场景
<!-- 1. 表单控件 -->
<template>
<input v-model="username" />
<textarea v-model="description"></textarea>
<select v-model="selected">
<option value="">请选择</option>
</select>
</template>
<!-- 2. 自定义组件的数据同步 -->
<template>
<CustomInput v-model="searchText" />
<ColorPicker v-model="themeColor" />
<DatePicker v-model="selectedDate" />
</template>
<!-- 3. 多个数据的双向绑定 -->
<template>
<UserForm
v-model:firstName="user.firstName"
v-model:lastName="user.lastName"
/>
</template>
5. 性能考虑
5.1 v-bind
- 单向数据流,性能开销较小
- 适合大量数据的展示场景
- 不会触发额外的更新事件
5.2 v-model
- 双向绑定,需要监听变化
- 涉及父子组件的数据同步
- 可能触发多次更新
6. 最佳实践
-
选择原则
- 仅需展示数据时使用 v-bind
- 需要数据同步时使用 v-model
- 考虑性能影响选择合适的方式
-
代码可维护性
- v-bind 更直观,易于追踪数据流向
- v-model 代码更简洁,但需要注意数据追踪
-
性能优化
- 合理使用计算属性
- 避免不必要的双向绑定
- 大量数据展示场景优先使用 v-bind