Vue2 模板语法与样式绑定

Vue2 模板语法与样式绑定

一、插值语法

1. 文本插值 {``{ }}

在标签的内容区域使用双大括号,可以把 data 中的数据渲染出来:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Vue2 文本插值</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <p>{{ message }}</p>
  </div>

  <script>
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue'
      }
    });
  </script>
</body>
</html>

页面渲染结果:Hello Vue

使用规则:

  • {``{ }} 只能写在标签的内容区域,不能写在标签属性中。给属性绑定值要用 v-bind(见下文)。
  • 内部支持 JavaScript 表达式:{``{ number + 1 }}{``{ message.toUpperCase() }}{``{ isOk ? '是' : '否' }}{``{ arr.join('、') }}
  • 内部不能写语句:{``{ if (x) { return 1 } }} 会直接报错,因为插值里只接受表达式,不接受语句。
  • 插值对应的 data 发生变化时,页面会自动更新,这是 Vue 的响应式机制。

2. v-text 与 v-html

v-textv-html 都是指令,用来把数据写进标签内容,与插值的作用有重叠,但行为不同:

  • v-text:以纯文本方式渲染,等价于 JS 的 innerText。用它替代插值可以避免页面加载瞬间闪现原始 {``{ }}(闪烁问题)。
  • v-html:把内容当作 HTML 解析后渲染,等价于 innerHTML
html 复制代码
<div id="app">
  <div v-text="content"></div>
  <div v-html="content"></div>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      content: '<strong>加粗文字</strong>'
    }
  });
</script>

第一个 div 显示原样字符串 <strong>加粗文字</strong>,第二个 div 显示加粗后的「加粗文字」。

安全要求:v-html 会解析传入的 HTML,包括其中的脚本逻辑。不要把用户可输入的内容直接传给 v-html,否则存在 XSS(跨站脚本)攻击风险。需要展示富文本时,应先用库(如 DOMPurify)做过滤再渲染。

3. v-once、v-pre、v-cloak

  • v-once:元素只渲染一次,之后数据再变化也不再更新。适合渲染后不再变化的静态内容,可以减少不必要的更新开销。
  • v-pre:跳过当前元素及其所有子元素的编译,内容原样输出,不做插值处理。适合展示原始模板文本,也能加快编译速度。
  • v-cloak:配合 CSS 使用,解决插值闪烁。原理是:在 Vue 完成编译前,带有 v-cloak 的元素被 CSS 隐藏;编译完成后 Vue 自动移除 v-cloak 属性,元素显示。
html 复制代码
<style>
  [v-cloak] {
    display: none;
  }
</style>

<div id="app">
  <div v-cloak>{{ message }}</div>
</div>

二、指令

指令是 Vue 模板语法的主体。所有指令都以 v- 开头,作用是在元素上绑定特定的行为。

1. 条件渲染 v-if / v-else-if / v-else

v-if 根据表达式的真假决定元素是否渲染。为假时元素不会出现在 DOM 中

html 复制代码
<div id="app">
  <p v-if="score >= 90">优秀</p>
  <p v-else-if="score >= 60">及格</p>
  <p v-else>不及格</p>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      score: 75
    }
  });
</script>

规则:

  • v-ifv-else-ifv-else 必须是相邻的兄弟元素,中间不能插入其他标签,否则 v-else 无法正确匹配。
  • 如果一次要控制多个相邻元素,可以配合 <template> 标签包裹,v-if 写在 <template> 上,<template> 本身不会渲染成 DOM。
html 复制代码
<template v-if="isShow">
  <h3>标题</h3>
  <p>段落一</p>
  <p>段落二</p>
</template>

2. v-show 与 v-if 的区别

v-show 也是条件显示,但行为不同:v-show 为假时元素仍然渲染在 DOM 中 ,只是被加上 display: none

html 复制代码
<p v-show="isShow">这段文字由 v-show 控制</p>
对比项 v-if v-show
为假时的行为 不渲染到 DOM 渲染到 DOM,用 display:none 隐藏
切换成本 需要创建/销毁元素,成本高 只切换样式,成本低
初次渲染 为假时不做渲染,适合懒加载场景 无论真假都渲染
使用场景 切换不频繁、初始为假的内容 高频切换的内容

3. 列表渲染 v-for

v-for 用来遍历数组、对象和数字,生成一组元素。

html 复制代码
<div id="app">
  <ul>
    <li v-for="(item, index) in list" :key="item.id">
      {{ index }} - {{ item.name }}
    </li>
  </ul>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      list: [
        { id: 1, name: '张三' },
        { id: 2, name: '李四' },
        { id: 3, name: '王五' }
      ]
    }
  });
</script>

规则:

  • 遍历数组时写 v-for="item in list",需要下标时写 v-for="(item, index) in list"
  • 遍历对象时写 v-for="(value, key, index) in obj"
  • 遍历数字时写 v-for="n in 10",n 从 1 开始。
  • 必须给每个循环项绑定唯一的 :keykey 帮助 Vue 在列表变化时复用和识别节点,不要用 index 作为 key,否则插入、删除、排序时可能出现渲染错乱。key 应使用数据自身的唯一标识(如 id)。

4. 事件绑定 v-on

v-on 给元素绑定事件,简写为 @

html 复制代码
<div id="app">
  <button @click="count++">点击加一:{{ count }}</button>
  <button @click="say('你好')">传参调用</button>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      count: 0
    },
    methods: {
      say(msg) {
        console.log(msg);
      }
    }
  });
</script>
  • 事件处理函数写在 methods 中,通过方法名调用。
  • 传参时写 @click="say('你好')"
  • 需要事件对象时写 @click="say($event)"
  • 常用修饰符:.stop(阻止冒泡)、.prevent(阻止默认行为)、.once(只触发一次)、.enter(回车键触发)等。
html 复制代码
<form @submit.prevent="onSubmit">
  <button type="submit">提交</button>
</form>

5. 双向绑定 v-model

v-model 用于表单元素,实现数据与视图的双向绑定:数据变视图变,用户输入后视图变数据也变。

html 复制代码
<div id="app">
  <input v-model="username" placeholder="请输入用户名">
  <p>当前输入:{{ username }}</p>

  <input type="checkbox" v-model="checked"> 已阅读协议
  <p>选中状态:{{ checked }}</p>

  <select v-model="city">
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
  </select>
  <p>选择城市:{{ city }}</p>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      username: '',
      checked: false,
      city: 'beijing'
    }
  });
</script>

v-model 的底层原理:

  • 普通文本输入框:value 属性 + input 事件。
  • 复选框、单选按钮:checked 属性 + change 事件。
  • 下拉选择:value 属性 + change 事件。

常用修饰符:

  • .lazy:把同步时机从 input 事件改为 change 事件,即失去焦点或回车时才更新数据。
  • .number:把输入值自动转成数字类型。
  • .trim:自动去除输入内容首尾空格。
html 复制代码
<input v-model.number="age" placeholder="年龄">
<input v-model.trim="name" placeholder="姓名">

6. 属性绑定 v-bind

v-bind 把 data 中的数据绑定到标签属性上,简写为 :。它是 class / style 绑定的基础。

html 复制代码
<div id="app">
  <img :src="imgUrl" :alt="altText">
  <a :href="link">链接</a>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      imgUrl: 'https://example.com/logo.png',
      altText: 'Logo',
      link: 'https://example.com'
    }
  });
</script>
  • 布尔属性(如 disabledchecked)绑定 false 时,属性会被移除;绑定 true 时,属性会出现。
  • 不带参数的 v-bind 可以把一个对象的所有属性一次性绑定到元素上:
html 复制代码
<div v-bind="{ id: 'box1', title: '提示' }"></div>

三、绑定 class

通过 v-bind:class(简写 :class)可以动态控制元素的 class。与原生 class 属性可以共存。

1. 对象语法

:class 的值是一个对象:键是类名,值是布尔表达式。值为真时该类名生效。

html 复制代码
<div id="app">
  <p :class="{ active: isActive, 'text-danger': hasError }">状态文字</p>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      isActive: true,
      hasError: false
    }
  });
</script>

渲染结果:<p class="active">状态文字</p>

  • 类名是合法标识符时可以不加引号(如 active)。
  • 类名包含短横线等特殊字符时必须加引号(如 'text-danger')。
  • isActive 变为 false 时,active 类自动移除。

2. 数组语法

:class 的值是一个数组,数组中的每一项都会作为类名应用。

html 复制代码
<p :class="[baseClass, activeClass]">文字</p>
js 复制代码
data: {
  baseClass: 'text-center',
  activeClass: 'text-bold'
}

渲染结果:<p class="text-center text-bold">文字</p>

数组中的项可以是字符串、三元表达式、对象,三者可以混用:

html 复制代码
<p :class="[baseClass, isActive ? 'active' : '', { 'text-danger': hasError }]">文字</p>

3. 与计算属性配合

对象里的逻辑变复杂时,可以把对象计算好放在计算属性里,模板保持简洁:

html 复制代码
<p :class="classObject">文字</p>
js 复制代码
computed: {
  classObject() {
    return {
      active: this.isActive,
      'text-danger': this.hasError
    };
  }
}

4. 在组件上绑定 class

:class 写在自定义组件标签上时,会作为组件根元素 的 class,不需要组件内部单独接收。这是 Vue 2 中 class 和 style 绑定区别于普通属性的地方(普通属性需要组件用 props 接收)。

四、绑定 style

v-bind:style(简写 :style)用来动态绑定内联样式。

1. 对象语法

:style 的值是一个对象,键是 CSS 属性名,值是属性值。属性名用驼峰命名(fontSize)或加引号的短横线命名('font-size')都可以。

html 复制代码
<div id="app">
  <p :style="{ color: textColor, fontSize: fontSize + 'px', 'font-weight': isBold ? 'bold' : 'normal' }">
    样式绑定示例
  </p>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      textColor: 'red',
      fontSize: 20,
      isBold: true
    }
  });
</script>

渲染结果:<p style="color: red; font-size: 20px; font-weight: bold;">样式绑定示例</p>

2. 数组语法

:style 的值也可以是数组,数组中的多个对象会合并,后者的同名属性覆盖前者。

html 复制代码
<p :style="[baseStyle, overrideStyle]">文字</p>
js 复制代码
data: {
  baseStyle: { color: 'blue', fontSize: '16px' },
  overrideStyle: { color: 'red' }
}

渲染结果:<p style="color: red; font-size: 16px;">文字</p>

3. 自动加前缀与多重值

  • 需要浏览器前缀的 CSS 属性(如 transform),Vue 会检测当前浏览器支持情况,自动加上 -webkit--moz- 等前缀。
  • 从 Vue 2.3.0 开始,:style 的属性值可以是一个数组,表示多重值。浏览器会使用它支持的那一个值:
html 复制代码
<p :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">文字</p>

4. 在组件上绑定 style

与 class 一样,:style 写在组件标签上也会应用到组件根元素。

五、小结

语法 简写 用途
{``{ }} 标签内容插值
v-text / v-html 以文本 / HTML 方式渲染内容
v-if / v-show 条件渲染
v-for 列表渲染
v-on @ 事件绑定
v-model 表单双向绑定
v-bind : 属性绑定
:class : 动态 class(对象 / 数组语法)
:style : 动态 style(对象 / 数组语法)

选择建议:

  • 内容是动态数据 → 插值或 v-text;需要解析 HTML → v-html(注意 XSS 风险)。
  • 切换不频繁或初始不渲染 → v-if;高频切换 → v-show
  • 列表渲染必须绑定唯一 key,避免使用 index。
  • 样式要动态控制 → 优先使用 :class,class 样式可复用、便于维护;:style 适合少量、局部且依赖数据的样式。
相关推荐
Amos_Web41 分钟前
Rspack 源码解析(十一):资产 Hook 与增量构建
前端·rust·源码阅读
PC2005_cloud41 分钟前
Windows 数据使用量页面卡死:1097 个热点档案和 161 MB 的 SRUM 库
前端·后端
烈风逍遥43 分钟前
AI大模型中fetch 和 ReadableStream为啥一起出现
前端·人工智能
PC2005_cloud1 小时前
Nginx 防盗链配置实战:用 referer 模块保护网站静态资源
前端·后端
福兮说1 小时前
Canvas 文字排版:measureText 量出来的宽度为什么总是不对
前端·javascript
夏幻灵1 小时前
从零理解 Redux:从 state、action、reducer 到 Redux Toolkit 与异步请求
前端
烈风逍遥1 小时前
第四篇:AI 模块架构设计:多 Provider 切换、RAG 知识库与 Agent 编排
前端·后端·架构
用户80806181436931 小时前
JavaScript 面向对象入门到精通
前端·javascript
吠品2 小时前
STM32最小系统板引脚梳理与配置实操
前端·javascript·vue.js