第一个Vue应用 #
一、创建应用 #
1.1 最简单的Vue应用 #
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>第一个Vue应用</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<p>计数器: {{ count }}</p>
<button @click="increment">+1</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const message = ref('Hello Vue!')
const count = ref(0)
function increment() {
count.value++
}
return {
message,
count,
increment
}
}
}).mount('#app')
</script>
</body>
</html>
1.2 应用结构解析 #
text
createApp() 创建Vue应用实例
│
├── setup() 组合式API入口
│ │
│ ├── ref() 创建响应式数据
│ ├── computed() 创建计算属性
│ ├── watch() 创建侦听器
│ └── return {} 返回模板需要的数据和方法
│
└── mount() 挂载到DOM元素
二、模板语法 #
2.1 文本插值 #
html
<div id="app">
<!-- 双大括号语法 -->
<p>{{ message }}</p>
<!-- 支持JavaScript表达式 -->
<p>{{ count + 1 }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
<p>{{ count > 10 ? '大于10' : '小于等于10' }}</p>
</div>
2.2 属性绑定 #
html
<div id="app">
<!-- v-bind指令 -->
<img v-bind:src="imageSrc" v-bind:alt="imageAlt">
<!-- 简写形式 -->
<img :src="imageSrc" :alt="imageAlt">
<!-- 动态属性名 -->
<button :[attrName]="attrValue">按钮</button>
<!-- 绑定多个属性 -->
<div v-bind="objectOfAttrs"></div>
</div>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const imageSrc = ref('image.png')
const imageAlt = ref('图片描述')
const attrName = ref('disabled')
const attrValue = ref(true)
const objectOfAttrs = ref({
id: 'container',
class: 'wrapper'
})
return { imageSrc, imageAlt, attrName, attrValue, objectOfAttrs }
}
}).mount('#app')
</script>
2.3 条件渲染 #
html
<div id="app">
<!-- v-if -->
<p v-if="seen">现在你看到我了</p>
<!-- v-else -->
<p v-if="type === 'A'">A类型</p>
<p v-else-if="type === 'B'">B类型</p>
<p v-else>其他类型</p>
<!-- v-show -->
<p v-show="visible">切换显示</p>
</div>
2.4 列表渲染 #
html
<div id="app">
<!-- 遍历数组 -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index }}: {{ item.name }}
</li>
</ul>
<!-- 遍历对象 -->
<ul>
<li v-for="(value, key, index) in object" :key="key">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul>
</div>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const items = ref([
{ id: 1, name: '苹果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橙子' }
])
const object = ref({
name: '张三',
age: 25,
city: '北京'
})
return { items, object }
}
}).mount('#app')
</script>
三、事件处理 #
3.1 基本事件 #
html
<div id="app">
<!-- 完整写法 -->
<button v-on:click="count++">点击 {{ count }}</button>
<!-- 简写形式 -->
<button @click="count++">点击 {{ count }}</button>
<!-- 调用方法 -->
<button @click="increment">+1</button>
<!-- 传递参数 -->
<button @click="add(5)">+5</button>
<!-- 访问事件对象 -->
<button @click="handleClick($event)">点击</button>
</div>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const count = ref(0)
function increment() {
count.value++
}
function add(num) {
count.value += num
}
function handleClick(event) {
console.log('事件对象:', event)
console.log('目标元素:', event.target)
}
return { count, increment, add, handleClick }
}
}).mount('#app')
</script>
3.2 事件修饰符 #
html
<div id="app">
<!-- 阻止默认行为 -->
<form @submit.prevent="onSubmit">
<button type="submit">提交</button>
</form>
<!-- 阻止事件冒泡 -->
<div @click="onDivClick">
<button @click.stop="onBtnClick">按钮</button>
</div>
<!-- 事件只触发一次 -->
<button @click.once="doOnce">只触发一次</button>
<!-- 按键修饰符 -->
<input @keyup.enter="onEnter" @keyup.esc="onEsc">
<!-- 组合修饰符 -->
<input @keyup.ctrl.enter="onCtrlEnter">
</div>
3.3 常用修饰符 #
| 修饰符 | 说明 |
|---|---|
.stop |
阻止事件冒泡 |
.prevent |
阻止默认行为 |
.capture |
使用事件捕获模式 |
.self |
只当事件在该元素本身触发时触发 |
.once |
事件只触发一次 |
.passive |
提升移动端滚动性能 |
四、双向绑定 #
4.1 v-model基础 #
html
<div id="app">
<!-- 文本输入 -->
<input v-model="text" placeholder="输入文本">
<p>输入内容: {{ text }}</p>
<!-- 多行文本 -->
<textarea v-model="content" placeholder="输入内容"></textarea>
<!-- 复选框 -->
<input type="checkbox" v-model="checked">
<label>{{ checked ? '已选中' : '未选中' }}</label>
<!-- 多个复选框 -->
<input type="checkbox" v-model="checkedNames" value="张三">
<input type="checkbox" v-model="checkedNames" value="李四">
<input type="checkbox" v-model="checkedNames" value="王五">
<p>选中: {{ checkedNames }}</p>
<!-- 单选按钮 -->
<input type="radio" v-model="picked" value="one">
<input type="radio" v-model="picked" value="two">
<p>选中: {{ picked }}</p>
<!-- 下拉框 -->
<select v-model="selected">
<option value="">请选择</option>
<option value="a">A</option>
<option value="b">B</option>
</select>
</div>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const text = ref('')
const content = ref('')
const checked = ref(false)
const checkedNames = ref([])
const picked = ref('')
const selected = ref('')
return { text, content, checked, checkedNames, picked, selected }
}
}).mount('#app')
</script>
4.2 v-model修饰符 #
html
<div id="app">
<!-- .lazy - 在change事件后同步 -->
<input v-model.lazy="text">
<!-- .number - 转换为数字 -->
<input v-model.number="age" type="number">
<!-- .trim - 去除首尾空格 -->
<input v-model.trim="name">
</div>
五、计算属性 #
5.1 基本使用 #
html
<div id="app">
<p>原价: {{ price }}</p>
<p>折扣价: {{ discountPrice }}</p>
<p>最终价格: {{ finalPrice }}</p>
</div>
<script>
const { createApp, ref, computed } = Vue
createApp({
setup() {
const price = ref(100)
// 计算属性
const discountPrice = computed(() => {
return price.value * 0.8
})
// 可写的计算属性
const finalPrice = computed({
get() {
return price.value * 0.8
},
set(newValue) {
price.value = newValue / 0.8
}
})
return { price, discountPrice, finalPrice }
}
}).mount('#app')
</script>
5.2 计算属性 vs 方法 #
html
<div id="app">
<!-- 计算属性 - 有缓存 -->
<p>{{ formattedPrice }}</p>
<p>{{ formattedPrice }}</p> <!-- 不会重新计算 -->
<!-- 方法 - 无缓存 -->
<p>{{ formatPrice() }}</p>
<p>{{ formatPrice() }}</p> <!-- 会重新调用 -->
</div>
<script>
const { createApp, ref, computed } = Vue
createApp({
setup() {
const price = ref(100)
// 计算属性 - 基于依赖缓存
const formattedPrice = computed(() => {
console.log('计算属性执行')
return `¥${price.value.toFixed(2)}`
})
// 方法 - 每次都执行
function formatPrice() {
console.log('方法执行')
return `¥${price.value.toFixed(2)}`
}
return { price, formattedPrice, formatPrice }
}
}).mount('#app')
</script>
六、完整示例:待办事项 #
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>待办事项</title>
<style>
.completed { text-decoration: line-through; color: #999; }
.todo-item { padding: 8px; border-bottom: 1px solid #eee; }
.todo-item:hover { background: #f5f5f5; }
</style>
</head>
<body>
<div id="app">
<h2>待办事项</h2>
<!-- 输入框 -->
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="添加新任务"
>
<button @click="addTodo">添加</button>
<!-- 过滤按钮 -->
<div>
<button @click="filter = 'all'" :class="{ active: filter === 'all' }">全部</button>
<button @click="filter = 'active'" :class="{ active: filter === 'active' }">未完成</button>
<button @click="filter = 'completed'" :class="{ active: filter === 'completed' }">已完成</button>
</div>
<!-- 列表 -->
<ul>
<li v-for="todo in filteredTodos" :key="todo.id" class="todo-item">
<input type="checkbox" v-model="todo.completed">
<span :class="{ completed: todo.completed }">{{ todo.text }}</span>
<button @click="removeTodo(todo.id)">删除</button>
</li>
</ul>
<!-- 统计 -->
<p>共 {{ totalTodos }} 项,已完成 {{ completedTodos }} 项</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp, ref, computed } = Vue
createApp({
setup() {
const newTodo = ref('')
const filter = ref('all')
const todos = ref([
{ id: 1, text: '学习Vue基础', completed: false },
{ id: 2, text: '学习Vue组件', completed: false },
{ id: 3, text: '学习Vue Router', completed: false }
])
// 添加待办
function addTodo() {
const text = newTodo.value.trim()
if (text) {
todos.value.push({
id: Date.now(),
text,
completed: false
})
newTodo.value = ''
}
}
// 删除待办
function removeTodo(id) {
const index = todos.value.findIndex(t => t.id === id)
if (index > -1) {
todos.value.splice(index, 1)
}
}
// 过滤后的列表
const filteredTodos = computed(() => {
switch (filter.value) {
case 'active':
return todos.value.filter(t => !t.completed)
case 'completed':
return todos.value.filter(t => t.completed)
default:
return todos.value
}
})
// 统计
const totalTodos = computed(() => todos.value.length)
const completedTodos = computed(() =>
todos.value.filter(t => t.completed).length
)
return {
newTodo,
filter,
todos,
addTodo,
removeTodo,
filteredTodos,
totalTodos,
completedTodos
}
}
}).mount('#app')
</script>
</body>
</html>
七、总结 #
| 概念 | 说明 |
|---|---|
createApp() |
创建Vue应用实例 |
mount() |
挂载应用到DOM |
ref() |
创建响应式数据 |
{{ }} |
模板插值语法 |
v-bind/: |
属性绑定 |
v-on/@ |
事件绑定 |
v-model |
双向数据绑定 |
v-if/v-show |
条件渲染 |
v-for |
列表渲染 |
computed() |
计算属性 |
学习要点:
- 理解Vue应用的创建和挂载过程
- 掌握模板语法和指令的使用
- 学会响应式数据绑定
- 熟悉事件处理和修饰符
- 理解计算属性的缓存特性
最后更新:2026-03-26