Appearance
Vue.js 简介
Vue.js 是一套用于构建用户界面的渐进式框架,基于标准 HTML、CSS 和 JavaScript 构建,提供了声明式和组件化的编程模型,帮助你高效地开发用户界面。
Vue.js 的核心特点:
- 声明式渲染:通过简洁的模板语法描述数据和 DOM 之间的关系
- 响应式数据绑定:当数据发生变化时,自动更新相关视图
- 组件化开发:将应用拆分为独立、可复用的组件,每个组件包含自己的状态和逻辑
交互示例
你可以点击下方的按钮来体验 Vue 的响应式特性:
Vue 响应式计数器示例
体验 Vue 3 组合式 API 的响应式特性
:0
增加次数0
减少次数0
重置次数0
响应式特性演示
点击按钮改变计数器的值,观察视图如何自动更新。Vue 的响应式系统会追踪数据变化并高效地更新 DOM。
以上示例的源代码如下:
vue
<template>
<div class="container">
<div class="header">
<h3>Vue 响应式计数器示例</h3>
<p>体验 Vue 3 组合式 API 的响应式特性</p>
</div>
<div class="info">
<span class="message">{{ message }}</span>
<span class="separator">:</span>
<transition name="count" mode="out-in">
<span :key="count" class="count">{{ count }}</span>
</transition>
</div>
<div class="button-group">
<el-button type="primary" size="large" @click="increment" :icon="Plus" circle></el-button>
<el-button type="success" size="large" @click="decrement" :icon="Minus" :disabled="count <= 0" circle></el-button>
<el-button type="warning" size="large" @click="reset" :icon="Refresh" :disabled="count === 0" circle></el-button>
</div>
<div class="stats-row">
<div class="stat-item">
<span class="stat-label">增加次数</span>
<span class="stat-value increment">{{ incrementCount }}</span>
</div>
<div class="stat-item">
<span class="stat-label">减少次数</span>
<span class="stat-value decrement">{{ decrementCount }}</span>
</div>
<div class="stat-item">
<span class="stat-label">重置次数</span>
<span class="stat-value reset">{{ resetCount }}</span>
</div>
</div>
<div class="info-card">
<div class="info-icon">💡</div>
<div class="info-content">
<strong>响应式特性演示</strong>
<p>点击按钮改变计数器的值,观察视图如何自动更新。Vue 的响应式系统会追踪数据变化并高效地更新 DOM。</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { Plus, Minus, Refresh } from '@element-plus/icons-vue';
// 定义响应式状态
const message = ref("当前计数");
const count = ref(0);
// 统计数据
const incrementCount = ref(0);
const decrementCount = ref(0);
const resetCount = ref(0);
// 增加计数
const increment = () => {
count.value++;
incrementCount.value++;
};
// 减少计数
const decrement = () => {
if (count.value > 0) {
count.value--;
decrementCount.value++;
}
};
// 重置计数器
const reset = () => {
if (count.value !== 0) {
count.value = 0;
resetCount.value++;
}
};
</script>
<style scoped>
.container {
padding: 32px;
border: 1px solid #e0e4e8;
border-radius: 16px;
margin: 24px 0;
background: #ffffff;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.container:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
}
.header {
text-align: center;
margin-bottom: 32px;
padding-bottom: 20px;
border-bottom: 2px solid #f0f2f5;
}
.header h3 {
font-size: 1.5rem;
font-weight: 700;
color: #1a1a2e;
margin: 0 0 8px 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header p {
font-size: 0.95rem;
color: #6b7280;
margin: 0;
}
.info {
text-align: center;
margin-bottom: 32px;
font-size: 1.75rem;
font-weight: 600;
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
padding: 24px;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
border-radius: 12px;
}
.message {
color: #6366f1;
}
.separator {
color: #9ca3af;
}
.count {
color: #10b981;
font-size: 3rem;
font-weight: 800;
min-width: 80px;
text-align: center;
font-variant-numeric: tabular-nums;
}
/* 计数数字动画 */
.count-enter-active {
animation: countBounceIn 0.3s ease-out;
}
.count-leave-active {
animation: countBounceOut 0.3s ease-in;
}
@keyframes countBounceIn {
0% {
opacity: 0;
transform: scale(0.5);
}
50% {
transform: scale(1.1);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes countBounceOut {
0% {
opacity: 1;
transform: scale(1);
}
50% {
transform: scale(0.9);
}
100% {
opacity: 0;
transform: scale(0.5);
}
}
.button-group {
display: flex;
justify-content: center;
gap: 16px;
margin-bottom: 28px;
}
.button-group .el-button {
transition: all 0.2s ease;
}
.button-group .el-button:hover:not(:disabled) {
transform: scale(1.1);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}
.button-group .el-button:active:not(:disabled) {
transform: scale(0.95);
}
.info-card {
display: flex;
align-items: flex-start;
gap: 16px;
padding: 20px;
background: linear-gradient(135deg, #fefce8 0%, #fef9c3 100%);
border-radius: 12px;
border-left: 4px solid #f59e0b;
margin-top: 24px;
}
.info-icon {
font-size: 1.75rem;
line-height: 1;
}
.info-content {
flex: 1;
}
.info-content strong {
display: block;
font-size: 1rem;
color: #92400e;
margin-bottom: 8px;
}
.info-content p {
font-size: 0.9rem;
color: #78350f;
margin: 0;
line-height: 1.6;
}
.stats-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.stat-item {
text-align: center;
padding: 16px;
background: #f8fafc;
border-radius: 10px;
transition: all 0.2s ease;
}
.stat-item:hover {
background: #f1f5f9;
transform: translateY(-2px);
}
.stat-label {
display: block;
font-size: 0.85rem;
color: #6b7280;
margin-bottom: 8px;
}
.stat-value {
font-size: 1.5rem;
font-weight: 700;
transition: color 0.2s ease;
}
.stat-value.increment {
color: #10b981;
}
.stat-value.decrement {
color: #f59e0b;
}
.stat-value.reset {
color: #ef4444;
}
/* 响应式设计 */
@media (max-width: 640px) {
.container {
padding: 20px;
margin: 16px 0;
}
.info {
font-size: 1.25rem;
padding: 16px;
}
.count {
font-size: 2.25rem;
min-width: 60px;
}
.button-group {
gap: 12px;
}
.stats-row {
grid-template-columns: 1fr;
gap: 12px;
}
}
</style>渐进式框架
Vue 是一个框架,也是一个生态。Vue 的设计非常注重灵活性和"可以被逐步集成"这个特点。
- 无需构建步骤,渐进式增强静态的 HTML
- 在任何页面中作为 Web Components 嵌入
- 单页应用 (SPA)
- 全栈 / 服务端渲染 (SSR)
- Jamstack / 静态站点生成 (SSG)
- 开发桌面端、移动端、WebGL,甚至是命令行终端中的界面
单文件组件
Vue 使用类似 HTML 格式的文件来书写组件,这种文件被称为单文件组件 (也被称为 *.vue 文件,英文 Single-File Components,缩写为 SFC)。
Vue 的单文件组件会将一个组件的逻辑 (JavaScript),模板 (HTML) 和样式 (CSS) 封装在同一个文件里。
API 风格
Vue 提供了两种不同的 API 风格:
- 选项式 API:使用包含多个选项的对象来描述组件的逻辑。每个选项都有其特定的功能,如
data、methods、computed等。 - 组合式 API:使用基于函数的 API,通过调用 Vue 提供的函数来定义组件的逻辑。组合式 API 更加强大和灵活,特别适用于大型组件和复杂的逻辑。
选项式 API (Options API)
选项式 API 是 Vue 最早引入的 API 风格,它使用一个包含多个选项的对象来描述组件的逻辑。每个选项都有其特定的功能,如 data、methods、computed 等。
以下是一个简单的选项式 API 组件示例:
vue
<template>
<div>
<h1>{{ message }}</h1>
<p>当前计数:{{ count }}</p>
<button @click="add">增加</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue',
count: 0
}
},
methods: {
add() {
this.count++
}
}
}
</script>组合式 API (Composition API)
组合式 API 是 Vue 3 引入的新 API 风格,它使用基于函数的 API,通过调用 Vue 提供的函数来定义组件的逻辑。组合式 API 更加强大和灵活,特别适用于大型组件和复杂的逻辑。
通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与 <script setup> 搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。
以下是一个简单的组合式 API 组件示例:
vue
<template>
<div>
<h1>{{ message }}</h1>
<p>当前计数:{{ count }}</p>
<button @click="add">增加</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('Hello Vue')
const count = ref(0)
function add() {
count.value++
}
</script>