Vue.js最吸引人的特性之一就是数据驱动视图,开发者只需要操作数据,页面就会自动更新。而实现这一切的基础,正是数据绑定语法。不少刚接触Vue的同学在写模板时会出现变量渲染空白、数据改了视图不动等问题,追根溯源都是对绑定语法的细节理解不到位。本文从插值、属性绑定、双向绑定到常见疑问,把Vue数据绑定的核心内容完整过一遍。

插值表达式:文本、HTML与表达式的三种写法
插值是Vue模板里最基础的绑定方式,使用双花括号将数据包裹起来:{{ message }}。花括号里可以放变量,也可以放简单的JavaScript表达式,比如{{ count * 2 }}、{{ ok ? '是' : '否' }}、{{ message.split('').reverse().join('') }}。但要注意,它只能放单个表达式,不能放语句,写成{{ if (ok) { return 'a' } }}是会直接报错的。
双花括号输出的是纯文本,如果数据里包含HTML标签,浏览器只会把它当字符串显示。想让HTML真正被渲染,需要使用v-html指令。但要特别提醒,v-html存在XSS风险,如果内容来自用户输入,攻击者可能注入恶意脚本,因此只对可信内容使用。另外双花括号不能作用在HTML属性上,属性绑定必须使用v-bind,这是初学者最常犯的错误之一。
<div id="app">
<!-- 文本插值 -->
<p>{{ message }}</p>
<!-- 表达式插值 -->
<p>总价:{{ price * count }} 元</p>
<!-- 渲染HTML内容,注意XSS风险 -->
<p v-html="rawHtml"></p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: '你好 Vue',
price: 25,
count: 3,
rawHtml: '<span style="color:red">红色文字</span>'
}
});
</script>插值还有一个容易被忽略的特性:首次渲染完成后,数据变化会立即反映到视图上,这就是响应式更新。如果希望某段内容只渲染一次、后续数据变化不再更新,可以加上v-once指令,这个属性在展示静态配置信息时偶尔会用到,能减少不必要的渲染开销。
v-bind与v-model:属性绑定和双向绑定的区别
v-bind用来把数据绑定到HTML属性上,完整写法是v-bind:src、v-bind:href,也可以简写成:src、:href。没有这个指令,属性值里写花括号是不生效的,比如<img src="{{ url }}">这种写法在Vue 2的某些场景下会出现问题,正确写法是<img :src="url">。绑定属性时还支持对象和数组语法,最典型的应用是动态切换class和style。
<!-- 属性绑定简写 -->
<img :src="imgUrl" :alt="imgName">
<a :href="linkUrl">跳转</a>
<!-- class的对象语法:isActive为true时添加active类 -->
<div :class="{ active: isActive, danger: hasError }"></div>
<!-- style的对象语法 -->
<div :style="{ color: fontColor, fontSize: size + 'px' }">文字</div>v-model是双向绑定的语法糖,主要用于表单元素。所谓双向,是指数据变了输入框跟着变,输入框里输入内容数据也跟着变。本质上v-model等价于:value加@input的组合,理解这一点对排查问题很有帮助。需要注意的是,v-model只能用在表单控件或自定义组件上,普通标签上写v-model是没有效果的。此外单选框、复选框、下拉选择各有对应的绑定细节,比如复选框绑定数组时会自动收集勾选项。
<input type="text" v-model="username" placeholder="用户名"> <textarea v-model="remark"></textarea> <!-- 复选框绑定数组 --> <input type="checkbox" value="篮球" v-model="hobbies">篮球 <input type="checkbox" value="游泳" v-model="hobbies">游泳 <!-- 修饰符 --> <input type="text" v-model.lazy="email"> <input type="number" v-model.number="age"> <input type="text" v-model.trim="name">
v-model提供了三个常用修饰符:.lazy把同步时机从input事件改为change事件,也就是失去焦点才更新;.number自动把输入值转成数字;.trim自动去掉首尾空格。这些小细节在实际表单开发中非常实用,能省掉不少手动处理数据的代码。
常见疑问解答:数据绑定的高频坑点
疑问一:为什么数组或对象更新了,视图没有刷新?这是Vue 2的经典问题。Vue 2通过Object.defineProperty实现响应式,无法侦测到通过索引直接修改数组元素(arr[0] = 1)和给对象添加新属性。解决方法是使用变异方法如push、splice,或者用Vue.set、this.$set来更新。Vue 3改用Proxy实现响应式,这些问题已经不复存在。
疑问二:单向数据流是什么意思,为什么不能直接修改props?父组件通过props向子组件传值,数据只能从父流向子,子组件不能直接修改props。如果确实需要基于props修改数据,正确做法是把props值赋给本地data,或者通过$emit通知父组件去改。直接修改props不仅会触发警告,还会让数据流向变得难以追踪。
疑问三:插值里显示空白是怎么回事?常见原因有三个:一是数据字段名拼写错误;二是数据还没请求回来就渲染了,可以用v-if判断后再渲染;三是渲染的层级不在Vue实例挂载的根元素内部。遇到空白先打开浏览器控制台看有没有报错,再逐项排查这三点,基本都能定位问题。
疑问四:v-bind和v-model到底怎么选?一句话概括:v-bind是单向的,数据驱动视图;v-model是双向的,视图也能反过来改数据。展示类的内容用v-bind,表单输入类的内容用v-model,遵循这个原则基本不会出错。把v-model用在展示数据上,或者指望v-bind实现表单回写,都是对语法语义的误用。
掌握这些绑定语法的关键点后,建议动手写几个小demo验证一遍,尤其是数组更新的边界情况和v-model修饰符的效果。数据绑定是Vue组件通信和状态管理的地基,把这部分理解透了,后面学习props验证、自定义事件的v-model以及Vuex或Pinia时,会发现很多概念都是一脉相承的。
Vue.js数据绑定插值表达式v-model双向绑定修改时间:2026-09-11 11:00:44