Vue3 v-bind 和 v-model 对比

1. 基本概念

1.1 v-bind

  • 单向数据绑定
  • 从父组件向子组件传递数据
  • 简写形式为 :

1.2 v-model

  • 双向数据绑定
  • 父子组件数据同步
  • 本质是 v-bind 和 v-on 的语法糖

2. 基础用法对比

2.1 表单元素绑定

vue 复制代码
<!-- 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 组件属性绑定

vue 复制代码
<!-- v-bind 方式 -->
<template>
  <CustomInput
    :value="searchText"
    @input="searchText = $event"
  />
</template>

<!-- v-model 方式 -->
<template>
  <CustomInput v-model="searchText" />
</template>

3. 主要区别

3.1 数据流向

vue 复制代码
<!-- v-bind: 单向数据流 -->
<ChildComponent
  :title="pageTitle"  <!-- 数据只能从父组件流向子组件 -->
/>

<!-- v-model: 双向数据流 -->
<ChildComponent
  v-model="pageTitle"  <!-- 数据可以双向同步 -->
/>

3.2 实现原理

vue 复制代码
<!-- v-bind 原理 -->
<ChildComponent :value="value" />

<!-- v-model 原理(等价于) -->
<ChildComponent
  :modelValue="value"
  @update:modelValue="value = $event"
/>

3.3 自定义组件实现对比

vue 复制代码
<!-- 使用 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 的场景

vue 复制代码
<!-- 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 的场景

vue 复制代码
<!-- 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. 最佳实践

  1. 选择原则

    • 仅需展示数据时使用 v-bind
    • 需要数据同步时使用 v-model
    • 考虑性能影响选择合适的方式
  2. 代码可维护性

    • v-bind 更直观,易于追踪数据流向
    • v-model 代码更简洁,但需要注意数据追踪
  3. 性能优化

    • 合理使用计算属性
    • 避免不必要的双向绑定
    • 大量数据展示场景优先使用 v-bind
相关推荐
奶球不是球几秒前
el-table(elementui)表格合计行使用以及滚动条默认样式修改
前端·vue.js·elementui
liuyang___3 分钟前
vue管理布局左侧菜单栏NavMenu
前端·javascript·vue.js
@业精于勤荒于嬉12 分钟前
将图片存储至阿里云 OSS
前端·阿里云·云计算·oss
前端Hardy27 分钟前
HTML&CSS&JS:必学!用粒子爆炸效果,让按钮点击 “告别枯燥”
javascript·css·html
前端Hardy30 分钟前
HTML&CSS&JS:必看!主题“自动换装”,10+风格随机切换超惊艳
javascript·css·html
打野赵怀真37 分钟前
render函数中return如果没有使用()会有什么问题?
前端·javascript
Scraper002438 分钟前
如何使用API和Node.js抓取Google新闻?
javascript
Riesenzahn39 分钟前
写一个左中右的满屏布局,左右固定220px,中间自适应并且要优先加载
前端·javascript
Riesenzahn39 分钟前
css在页面上画一个正方形,边长为页面宽度的一半
前端·javascript
tommyrunner41 分钟前
Cursor rule文件测试 一秒了解AI行为规则文件
前端·cursor