理论知识准备得差不多了,现在让我们动手创建第一个 Vue 应用。我们将从最基础的例子开始,逐步深入。
创建一个 index.html 文件:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一个 Vue 应用</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>
用浏览器打开这个文件,你会看到 "Hello Vue!"。
var app = new Vue({
el: '#app', // 挂载点:Vue 管理的 DOM 范围
data: { // 数据:页面显示的内容
message: 'Hello Vue!'
}
})
el:指定 Vue 实例挂载的 DOM 元素data:定义响应式数据{{ message }}:插值表达式,显示 data 中的 message让我们添加一个输入框,体验 Vue 的双向绑定:
<div id="app">
<input type="text" v-model="message">
<p>你输入的是:{{ message }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
当你在输入框中输入内容时,下面的文字会实时更新。这就是 Vue 的双向数据绑定。
一个稍微复杂点的例子——计数器:
<div id="app">
<h2>计数器</h2>
<p>当前计数:{{ count }}</p>
<button @click="decrement">-1</button>
<button @click="increment">+1</button>
<button @click="reset">重置</button>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
increment: function() {
this.count++
},
decrement: function() {
this.count--
},
reset: function() {
this.count = 0
}
}
})
</script>
methods:定义方法@click:事件绑定,@ 是 v-on: 的简写this.count:在方法中通过 this 访问 data让我们做一个更实用的例子——待办事项:
<div id="app">
<h2>待办事项</h2>
<!-- 输入区域 -->
<input
type="text"
v-model="newItem"
@keyup.enter="addItem"
placeholder="输入待办事项,按回车添加"
>
<button @click="addItem">添加</button>
<!-- 列表区域 -->
<ul>
<li v-for="(item, index) in items" :key="index">
<input type="checkbox" v-model="item.done">
<span :style="{ textDecoration: item.done ? 'line-through' : 'none' }">
{{ item.text }}
</span>
<button @click="removeItem(index)">删除</button>
</li>
</ul>
<!-- 统计区域 -->
<p>共 {{ items.length }} 项,已完成 {{ doneCount }} 项</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
newItem: '',
items: [
{ text: '学习 Vue 基础', done: true },
{ text: '学习 Vue 组件', done: false },
{ text: '学习 Vue Router', done: false }
]
},
computed: {
doneCount: function() {
return this.items.filter(function(item) {
return item.done
}).length
}
},
methods: {
addItem: function() {
var text = this.newItem.trim()
if (text) {
this.items.push({
text: text,
done: false
})
this.newItem = ''
}
},
removeItem: function(index) {
this.items.splice(index, 1)
}
}
})
</script>
v-for:列表渲染v-model:表单双向绑定@keyup.enter:按键修饰符computed:计算属性:style:动态样式绑定:key:列表渲染的 key如果你使用 Vue CLI 或 Vite 创建项目,会使用 .vue 单文件组件:
<template>
<div class="todo-app">
<h2>待办事项</h2>
<div class="input-area">
<input
v-model="newItem"
@keyup.enter="addItem"
placeholder="输入待办事项"
>
<button @click="addItem">添加</button>
</div>
<ul class="todo-list">
<li
v-for="(item, index) in items"
:key="item.id"
:class="{ done: item.done }"
>
<input type="checkbox" v-model="item.done">
<span>{{ item.text }}</span>
<button class="delete-btn" @click="removeItem(index)">×</button>
</li>
</ul>
<div class="stats">
<span>共 {{ items.length }} 项</span>
<span>已完成 {{ doneCount }} 项</span>
</div>
</div>
</template>
<script>
export default {
name: 'TodoApp',
data() {
return {
newItem: '',
items: [],
nextId: 1
}
},
computed: {
doneCount() {
return this.items.filter(item => item.done).length
}
},
methods: {
addItem() {
const text = this.newItem.trim()
if (text) {
this.items.push({
id: this.nextId++,
text: text,
done: false
})
this.newItem = ''
}
},
removeItem(index) {
this.items.splice(index, 1)
}
}
}
</script>
<style scoped>
.todo-app {
max-width: 500px;
margin: 20px auto;
padding: 20px;
}
.input-area {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.input-area input {
flex: 1;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
}
.todo-list {
list-style: none;
padding: 0;
}
.todo-list li {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
border-bottom: 1px solid #eee;
}
.todo-list li.done span {
text-decoration: line-through;
color: #999;
}
.delete-btn {
margin-left: auto;
background: none;
border: none;
color: #f44336;
cursor: pointer;
font-size: 18px;
}
.stats {
margin-top: 20px;
color: #666;
display: flex;
gap: 20px;
}
</style>
// 在控制台直接访问 Vue 实例
app.message = 'New Message'
app.items.push({ text: 'New Item', done: false })
// 在 Vue 实例中添加 watch
var app = new Vue({
data: { count: 0 },
watch: {
count: function(newVal, oldVal) {
console.log('count changed:', oldVal, '->', newVal)
}
}
})
// ❌ 错误:找不到 #app 元素
new Vue({
el: '#app'
})
// ✅ 正确:确保 DOM 已加载
document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#app'
})
})
// ❌ 错误:组件中 data 不能是对象
Vue.component('my-component', {
data: {
message: 'Hello'
}
})
// ✅ 正确:组件中 data 必须是函数
Vue.component('my-component', {
data: function() {
return {
message: 'Hello'
}
}
})
// ❌ 错误:Vue 无法检测
this.items[0] = newValue
// ✅ 正确:使用 $set
this.$set(this.items, 0, newValue)
通过这几个例子,你已经学会了:
v-model 实现双向绑定v-on 绑定事件v-for 渲染列表computed 计算属性接下来,我们将深入学习 Vue 的每个特性。