
初体验 Vue 2
官网https://v2.cn.vuejs.org/v2/guide/
安装
首先,你需要在你的项目中安装 Vue 2。可以通过 CDN 引入,这对于学习和小规模项目来说非常方便:
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
创建一个简单的 Vue 应用
-
HTML 文件:在你的 HTML 文件中添加一个元素作为 Vue 实例的挂载点。
<div id="app"> {{ message }} </div>
-
初始化 Vue 实例 :接下来,在你的 JavaScript 文件中创建一个新的 Vue 实例,并指定
el
属性为你的挂载点,data
属性包含你想要绑定的数据。new Vue({ el: '#app', data: { message: 'Hello Vue!' } });
当你运行这个简单的例子时,你应该能够在页面上看到 "Hello Vue!" 文本。这是与 Vue 进行交互的一个非常基本的例子。
vue指令
Vue 2 中的指令是带有 v-
前缀的特殊属性,它们用于在模板中直接应用 Vue 的响应式特性。指令的核心作用是在表达式执行后,对 DOM 进行操作。以下是一些常用的 Vue 2 指令及其详细解释:
1. v-text
-
用途:更新元素内的文本内容。
-
示例 :
<span v-text="message"></span> <!-- 等同于 --> <span>{{ message }}</span>
2. v-html
-
用途:更新元素的 innerHTML。注意,由于它会直接作为 HTML 进行渲染,因此使用时需谨慎处理不受信任的内容,以避免 XSS 攻击。
-
示例 :
<div v-html="rawHtml"></div>
3. v-show
-
用途 :根据表达式的真假值来切换元素的显示或隐藏(通过 CSS 的
display
属性)。 -
示例 :
<h1 v-show="isShow">Hello!</h1>
4. v-if
, v-else-if
, v-else
-
用途 :条件性地渲染一块内容。
v-if
是"真正的"条件渲染,因为它确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-else-if
和v-else
需与v-if
或v-else-if
配合使用。 -
示例 :
<div v-if="type === 'A'">A</div> <div v-else-if="type === 'B'">B</div> <div v-else>Not A/B</div>
5. v-for
-
用途 :基于源数据多次渲染元素或模板块。此指令需要使用特定的语法形式,如
item in items
。 -
示例 :
<ul> <li v-for="(item, index) in items" :key="index">{{ item.name }}</li> </ul>
6. v-on
-
用途:绑定事件监听器。
-
示例 :
<button v-on:click="doSomething">Click Me</button> <!-- 缩写 --> <button @click="doSomething">Click Me</button>
7. v-bind
-
用途:动态地绑定一个或多个属性,或一个组件 prop 到表达式。
-
示例 :
<img v-bind:src="imageSrc"> <!-- 缩写 --> <img :src="imageSrc">
8. v-model
-
用途:创建双向数据绑定,在表单控件或者组件上使用。
-
示例 :
<input v-model="message" placeholder="edit me">
计算属性
计算属性定义在 Vue 实例的 computed
选项中,就像方法一样,但它们会自动追踪其依赖的数据,并且只在依赖数据发生变化时重新计算结果。
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性 getter
reversedMessage: function () {
return this.message.split('').reverse().join('');
}
}
});
在这个例子中,reversedMessage
是一个计算属性,它根据 message
的值动态计算出反转后的字符串。
计算属性 vs 方法
虽然你可以通过方法实现同样的功能,但是计算属性是基于它的依赖进行缓存的。只有当它的依赖发生变化时,才会重新求值。这对于性能优化非常有用,特别是在计算开销较大的情况下。
<div id="demo">{{ reversedMessage }}</div>
<div>{{ result() }}</div>
<script>
new Vue({
el: '#demo',
data: {
message: 'Hello Vue!'
},
computed: {
reversedMessage: function () {
console.log('计算属性被调用');
return this.message.split('').reverse().join('');
}
},
methods: {
result: function () {
console.log('方法被调用');
return this.message.split('').reverse().join('');
}
}
});
</script>
当你多次访问 reversedMessage
,只会看到一次 "计算属性被调用" 的日志,而每次访问 result()
都会打印 "方法被调用"。
计算属性的 setter
默认情况下,计算属性只有 getter,不过你也可以提供一个 setter:
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName;
},
// setter
set: function (newValue) {
var names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
现在当你修改 fullName
时,setter 会被调用,相应的 firstName
和 lastName
也会更新。
定义方法
在 Vue 2 中,方法(methods)是定义在 Vue 实例的 methods
选项中的函数。它们可以被用来定义事件处理器、执行数据操作、发起异步请求等。与计算属性不同,方法不会基于其依赖进行缓存,每次调用都会执行函数体内的代码。
你可以像下面这样在 Vue 实例中定义方法:
new Vue({
el: '#example',
data: {
message: 'Hello Vue!'
},
methods: {
reverseMessage: function () {
return this.message.split('').reverse().join('');
},
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.message + '!');
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName);
}
}
}
});
在这个例子中,我们定义了两个方法:reverseMessage
和 greet
。前者简单地反转了 message
的值,后者则展示了如何处理一个事件,并使用了传递给它的参数(如 event
)。
调用方法
- 直接调用:你可以在 JavaScript 代码中直接调用这些方法。
- 通过事件绑定调用 :也可以通过
v-on
指令将方法绑定到特定的 DOM 事件上。
例如,在 HTML 中通过点击按钮触发 greet
方法:
<div id="example">
<button v-on:click="greet">这个方法不带event</button>
<br/><br/>
<button v-on:click="greet()">这个方法不带event</button>
<br/><br/>
<button v-on:click="greet(event)">如果带参数,可以传递内置事件对象event</button>
<!-- 使用插值表达式显示方法的返回值 (文本内容) -->
<p>{{ reverseMessage() }}</p>
<!-- 使用 v-text 显示方法的返回值 (文本内容) -->
<p v-text="reverseMessage()"></p>
</div>
<button v-on:click="greet(event)">如果带参数,可以传递内置事件对象event</button>
参考 5.2.1 javascript 事件对象.内容补充.-CSDN博客
方法 vs 计算属性
虽然方法和计算属性都可以用于处理逻辑并返回结果,但它们之间有一些重要的区别:
- 缓存:计算属性会基于它们的依赖进行缓存,只有当相关依赖发生改变时才会重新求值。而方法则没有这种缓存机制,每次调用都会执行函数体内的代码。
- 用途:计算属性更适合用于根据其他数据的变化来计算值的情况,尤其是当你需要展示计算后的结果时。而方法则更适合用于处理事件、执行异步操作或其它不涉及展示逻辑的操作。
异步操作示例
方法非常适合处理异步操作,比如从服务器获取数据:
new Vue({
el: '#app',
data: {
message: 'Loading...',
posts: []
},
methods: {
fetchData: function() {
var vm = this;
setTimeout(function() {
vm.message = 'Data loaded';
vm.posts = [
{ id: 1, title: 'First Post' },
{ id: 2, title: 'Second Post' }
];
}, 1000);
}
}
});
在这个例子中,fetchData
方法模拟了一个异步的数据获取过程,并更新了 message
和 posts
数据。
总结
- 方法:用于定义可重复使用的函数,可以包含任意复杂的逻辑,包括异步操作。适合处理交互行为和动态响应用户输入。
- 计算属性:更适合于基于其他数据的变化来计算值,并且能够利用缓存提升性能,特别适用于展示经过计算的结果。
综合案例
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Vue 2 Todo App</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<style>
.completed {
text-decoration: line-through;
color: #888;
}
.todo-item {
margin: 5px 0;
}
</style>
</head>
<body>
<div id="app">
<h1>我的待办事项</h1>
<!-- 输入框用于添加新任务 -->
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="添加新任务..."
class="todo-input"
>
<button @click="addTodo">添加</button>
<!-- 显示待办事项列表 -->
<ul>
<li
v-for="(todo, index) in todos"
:key="index"
:class="{ completed: todo.done }"
class="todo-item"
>
<!-- 使用 v-model 创建双向绑定 -->
<input
type="checkbox"
v-model="todo.done"
>
<!-- 使用 v-text 显示任务文本 -->
<span v-text="todo.text"></span>
<!-- 删除按钮 -->
<button @click="removeTodo(index)">删除</button>
</li>
</ul>
<!-- 使用 v-show 显示未完成任务数量 -->
<p v-show="remainingCount > 0">
还有 {{ remainingCount }} 项任务未完成。
</p>
<!-- 使用 v-if 显示所有任务已完成的消息 -->
<p v-if="remainingCount === 0 && todos.length > 0">
恭喜!所有任务都已完成。
</p>
<!-- 使用 v-else 显示没有任务时的消息 -->
<p v-else-if="todos.length === 0">
暂无待办事项。
</p>
</div>
<script>
new Vue({
el: '#app',
data: {
newTodo: '', // 输入框中的新任务文本
todos: [] // 存储所有待办事项的数组
},
computed: {
// 计算属性:计算未完成任务的数量
remainingCount() {
return this.todos.filter(todo => !todo.done).length;
}
},
methods: {
// 添加新任务
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({
text: this.newTodo,
done: false
});
this.newTodo = ''; // 清空输入框
}
},
// 删除指定索引的任务
removeTodo(index) {
this.todos.splice(index, 1);
}
}
});
</script>
</body>
</html>