Skip to content

VueJS - 模板

Vue 使用基于 HTML 的 模板语法 (template syntax),允许你声明性地将渲染的 DOM 绑定到基础 组件实例 (component instance) 的数据。所有 Vue 模板都是语法有效的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。

在底层,Vue 将模板编译成高度优化的 JavaScript 代码,通常是 虚拟 DOM (Virtual DOM) 渲染函数,以高效地更新实际的 DOM。

最基本的数据绑定形式是使用“Mustache”语法(双大括号 {{ }})进行的文本插值:

<p>Message: {{ message }}</p>

大括号内的内容将被替换为组件状态中 message 属性的值。当 message 属性发生变化时,它也会自动更新。

你只能在插值中使用 单个表达式 (single expressions),不能使用 语句 (statements)。例如,{{ count + 1 }} 是有效的,但 {{ var a = 1 }} 或 {{ if (ok) { return message } }} 是无效的。

双大括号会将数据解释为纯文本,而不是 HTML。如果你需要输出存储在数据中的实际 HTML 内容,必须使用 v-html 指令。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Template Syntax</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app">
<h2>Text Interpolation:</h2>
<p>{{ rawHtmlContent }}</p> <!-- This will show HTML tags as text -->
<h2>Using v-html:</h2>
<div v-html="rawHtmlContent"></div> <!-- This will render the HTML -->
</div>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const rawHtmlContent = ref('<span style="color: red; font-weight: bold;">This should be red and bold.</span>');
return { rawHtmlContent };
}
}).mount('#app');
</script>
</body>
</html>

在浏览器中:

  • 第一个段落会字面显示:<span style="color: red; font-weight: bold;">This should be red and bold.</span>
  • 第二个 div 使用 v-html,会显示文本“This should be red and bold.”,并按照 HTML 进行红色加粗样式渲染。

在你的网站上动态渲染任意 HTML 可能非常危险,因为它很容易导致 跨站脚本攻击 (Cross-Site Scripting, XSS)。 仅在可信内容上使用 v-html,并且永远不要用于用户提供的内容。如果处理需要富文本格式的用户输入,请先使用库对 HTML 进行 净化 (sanitize)。

Mustache 语法不能用于 HTML 属性内部。相反,使用 v-bind 指令将属性的值绑定到组件的状态。

<!-- Bind element ID -->
<div v-bind:id="dynamicId">...</div>
<!-- Bind element class -->
<div v-bind:class="activeClass">...</div>
<!-- Bind boolean attribute (e.g., disabled) -->
<button v-bind:disabled="isButtonDisabled">Click Me</button>
<!-- Bind image source -->
<img v-bind:src="imageUrl">

由于 v-bind 使用非常频繁,Vue 提供了一个方便的简写方式——冒号(:):

<!-- Shorthand for v-bind:id -->
<div :id="dynamicId">...</div>
<!-- Shorthand for v-bind:class -->
<div :class="activeClass">...</div>
<!-- Shorthand for v-bind:disabled -->
<button :disabled="isButtonDisabled">Click Me</button>
<!-- Shorthand for v-bind:src -->
<img :src="imageUrl">

这种简写方式在 Vue 社区中被广泛使用。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Attribute Binding</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.active { border: 2px solid blue; }
.text-danger { color: red; }
img { max-width: 100px; display: block; margin-top: 10px; }
</style>
</head>
<body>
<div id="app">
<h1 :id="headingId">My Dynamic Heading</h1>
<p :class="statusClass">Status message</p>
<button @click="isError = !isError">Toggle Error State</button>
<button :disabled="isDisabled">{{ isDisabled ? 'Processing...' : 'Submit' }}</button>
<button @click="isDisabled = !isDisabled">Toggle Disabled</button>
<img :src="currentImage" alt="Dynamic Image">
<button @click="changeImage">Change Image</button>
<!-- Binding multiple attributes -->
<div v-bind="divAttributes">Div with multiple bound attributes</div>
</div>
<script>
const { createApp, ref, computed, reactive } = Vue;
createApp({
setup() {
const headingId = ref('main-heading');
const isError = ref(false);
const isDisabled = ref(false);
const images = [
'https://via.placeholder.com/100/0000FF/FFFFFF?text=Image1',
'https://via.placeholder.com/100/FF0000/FFFFFF?text=Image2'
];
const currentImageIndex = ref(0);
// Computed property for dynamic class
const statusClass = computed(() => {
return {
active: !isError.value,
'text-danger': isError.value
};
});
const currentImage = computed(() => images[currentImageIndex.value]);
function changeImage() {
currentImageIndex.value = (currentImageIndex.value + 1) % images.length;
}
// Object for binding multiple attributes
const divAttributes = reactive({
'data-index': 1,
title: 'This is a dynamic title'
});
return {
headingId,
isError,
statusClass,
isDisabled,
currentImage,
changeImage,
divAttributes
};
}
}).mount('#app');
</script>
</body>
</html>

在这个例子中:

  • :id 绑定 <h1> 的 ID。
  • :class 使用对象语法(稍后会详细介绍类和样式绑定)根据 isError 状态动态绑定类。
  • :disabled 绑定按钮的禁用状态。
  • :src 动态绑定图片源。
  • 点击按钮会更新 响应式状态 (reactive state),Vue 会自动更新 DOM 中相应的属性。
  • 使用 v-bind(不带参数)绑定一个对象 divAttributes,可以一次性设置多个属性。

Vue 支持在所有数据绑定(Mustache 语法和 指令 (directive) 值)中使用 JavaScript 表达式的全部能力。

{{ count + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="'list-' + id"></div>

但是,每个绑定只能包含 一个单一的表达式。复杂的逻辑通常应该在组件的 <script> 部分通过 计算属性 (computed properties) 或 方法 (methods) 来处理。

限制:表达式被 沙盒化 (sandboxed),只能访问组件属性和有限的全局 白名单 (allowlist)(如 Math、Date)。你不能访问任意用户定义的全局变量。

本章涵盖了 Vue 模板语法用于显示文本和绑定属性的基础知识。后续章节将探讨其他指令,如用于事件的 v-on 和用于表单绑定的 v-model,以及更高级的类和样式绑定技术。

进一步阅读:Vue 官方文档中关于模板语法的章节:https://vuejs.org/guide/essentials/template-syntax.html