引言
在现代前端开发中,数据驱动界面 (Data-Driven Interface,简称DDI )已经成为一种标准模式。它允许开发者通过简单的声明性代码来创建复杂的用户界面(UI),并且随着底层数据的变化自动更新这些界面。下面将使用todos(待办事项应用) 实例来介绍Vue
的数据驱动界面 。比较Vue2
和Vue3
的优缺点。
专注于业务开发
在开始之前,我们要时刻牢记Vue
的设计哲学:
Vue更关注于业务开发,数据驱动页面。
因为Vue
通过提供简洁的语法、组件化架构、双向数据绑定和高效的响应式系统等特性,简化了用户界面的构建过程,使开发者能够将更多精力集中在解决业务问题上,而非纠结于复杂的前端技术细节。
我们要使用数据来驱动界面,保证数据和界面数据的一致性。为了开发者专注于业务开发,Vue
给我们提供许多的方法:
- {{}} : 插值表达式,它用于将 Vue 实例中的数据属性插入到模板中。这种插值是单向绑定。
- v-bind : 可缩写为
:
。单向数据绑定,动态绑定,它允许你在运行时根据 Vue 实例的数据动态地设置 HTML 属性的值。 - v-model : 在表单输入元素或组件上创建双向绑定。
todos 业务(vue2版)
下面开始我们的todos
。我们需要考虑应该有哪些业务,而不只专注于代码的语法功能。
这个应用的功能包括添加新的待办事项、标记已完成的任务、显示未完成任务的数量,并全选/取消全选所有任务。
我们本篇文章致力于理解Vue
的数据驱动能力,所以我们只是在html
中引入Vue
,并没有也不需要创建一个完整的项目。
我们分别来完成这几个功能,先来使用Vue2
的方法,之后再来将Vue2
和Vue3
进行比较。
Vue2
是选择式的。在Vue2
中,规定
- 使用
data
来返回数据 - 使用
methods
定义在模板中调用的方法 - 使用
computed
定义计算属性
基本框架
使用v-for
循环将数据打印到页面中
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todos</title>
</head>
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.global.min.js"></script>
<body>
<!-- 挂载点, vue 作用域 -->
<div id="app">
<h2>{{title}}</h2>
<input type="text" />
<ul>
<li v-for="todo in todos">
<input type="checkbox">
<span >{{todo.title}}</span>
</li>
</ul>
</div>
<script>
const App = {
// vue 2.0
// 数据
data() {
return {
title: "todos",
todos: [
{ title: "吃饭", done: true },
{ title: "睡觉", done: false }
]
}
},
// 方法
methods: {
},
// 计算属性
computed: {
},
}
// 将App实例挂载到#app标签上
Vue.createApp(App).mount('#app');
</script>
</body>
</html>
1. 添加新的待办事项
我们将input
表单与title
双向绑定,使input
中的内容与数据title
保持一致,并动态显示在页面上。
为input
添加v-model
,并添加点击事件,要求用户点击回车之后生效。我们使用@keydown.enter
。
html
<input type="text" v-model="title" @keydown.enter="addTodo"/>
addTodo
方法,写在methods
下。触发时,将在todos
数组中以相同的格式添加数据,并将输入框清空。
javascript
// 事件处理函数
methods: {
addTodo() {
this.todos.push({
title: this.title,
done: false,
})
// 输入框清空
this.title = '';
}
},
2. 标记已完成的任务
在数据中已经设置了done
的值来记录是否完成。我们将复选框与todo.done
绑定。使用v-bind
为span
根据done
的值添加类名。添加CSS样式。
html
<style>
.done {
color: gray;
text-decoration: line-through;
}
</style>
<li v-for="todo in todos">
<input type="checkbox" v-model="todo.done">
<span :class="{done:todo.done}">{{todo.title}}</span>
</li>
3. 显示未完成任务的数量
先添加html。我们需要计算未完成任务的数量,那就需要到了computed
计算属性。
html
<div>
<span>{{active}} / {{all}}</span>
</div>
<script>
// 计算属性 返回值
computed: {
all() { // 总数量
return this.todos.length
},
active() { // done 为 false 的数量 filter筛选
return this.todos.filter(todo => !todo.done).length;
},
</script>
4. 全选/取消全选所有任务
添加全选按钮,要求勾选后所有项都被选择,取消勾选所有项都取消,当所有项全部勾选后全选也被勾选,当所有项全部勾选取消一个勾选后全选也被取消。
双向绑定allDone
,不仅要获取值(get
),还要设置值(set
)
get
: 获取未完成的任务数量,如果为0,那么全选就应该勾选 set
: 全选被勾选或取消勾选,要修改todos
中的所有done
值
html
全选<input type="checkbox" v-model="allDone">
<script>
computed: {
// get set 两个都
allDone:{
get(){ // 根据 active 改值
// this -> 计算属性
return this.active === 0
},
set(val){
// 设置true false 状态
// 数据和界面要保持一致
this.todos.forEach(todo => (todo.done = val));
},
}
}
</script>
至此,我们已经成功完成了todos
业务。页面是由数据驱动的,在页面被修改时,要同步到数据。
下面是完整代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todos</title>
<style>
.done {
color: gray;
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app">
<h2>{{title}}</h2>
<input type="text" v-model="title" @keydown.enter="addTodo" placeholder="输入新任务并按回车键添加"/>
<ul>
<li v-for="(todo, index) in todos" :key="index">
<input type="checkbox" v-model="todo.done">
<span :class="{done: todo.done}">{{todo.title}}</span>
</li>
</ul>
<div>
全选<input type="checkbox" v-model="allDone">
<span>{{active}} / {{all}}</span>
</div>
</div>
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.global.min.js"></script>
<script>
const App = {
data() {
return {
title: "todos",
todos: [
{ title: "吃饭", done: true },
{ title: "睡觉", done: false }
]
};
},
methods: {
addTodo() {
if (this.title.trim()) {
this.todos.push({
title: this.title,
done: false,
});
this.title = '';
}
}
},
computed: {
all() {
return this.todos.length;
},
active() {
return this.todos.filter(todo => !todo.done).length;
},
allDone: {
get() {
return this.active === 0;
},
set(val) {
this.todos.forEach(todo => todo.done = val);
}
}
}
};
Vue.createApp(App).mount('#app');
</script>
</body>
</html>
todos 业务(vue3版)
Vue3
的逻辑与Vue2
相同,只是在写法上不同,所以我直接给出代码。 Vue2
规定了data、method、computed
,这让语法看起来非常简单。但是到了大型项目中,缺点也越来越明显:不灵活。
Vue3
使用了setup
组合式,将对应的data + method + computed
放一起。这有利于大型项目的维护。
可以清楚的看到vue2
和vue3
之间的区别
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todos</title>
</head>
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.2.31/vue.global.min.js"></script>
<style>
.done {
color: gray;
text-decoration: line-through;
}
</style>
<body>
<div id="app">
<h2>{{ title }}</h2>
<input type="text" v-model="title" @keydown.enter="addTodo" />
<ul>
<li v-for="todo in todos">
<input type="checkbox" v-model="todo.done">
<span :class="{ done: todo.done }">{{ todo.title }}</span>
</li>
</ul>
<div>
全选<input type="checkbox" v-model="allDone">
<span>{{ active }} / {{ all }}</span>
</div>
</div>
<script>
const { ref, computed } = Vue; // 解构赋值引入需要的函数
let App = {
setup() {
const title = ref('todos');
const todos = ref([
{ title: '吃饭', done: true },
{ title: '睡觉', done: false }
]);
function addTodo() {
todos.value.push({ title: title.value, done: false });
title.value = '';
}
const all = computed(() => todos.value.length);
const active = computed(() => todos.value.filter(todo => !todo.done).length);
const allDone = computed({
get: () => active.value === 0,
set: (value) => todos.value.forEach(todo => todo.done = value)
});
return {
title,
todos,
addTodo,
all,
active,
allDone
};
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
总结
通过采用 Vue 的数据驱动页面开发模式,开发者能够将更多的精力集中在业务逻辑的实现上,而无需为复杂的 DOM 操作和状态管理头疼。Vue 提供的响应式系统、简洁的模板语法以及强大的组件化架构,不仅简化了用户界面的构建过程,还确保了应用的高效运行和易于维护。
随着 Vue 3 的推出,组合式 API (setup
) 进一步增强了代码的模块化和可重用性,使得大型项目的开发和维护变得更加直观和高效。无论是初创团队还是企业级开发,Vue 都提供了一个灵活且高效的解决方案,帮助团队快速迭代并专注于解决核心业务问题。
总之,Vue 的数据驱动方法让前端开发回归本质------即通过清晰的数据流和简化的逻辑结构来构建富有表现力的应用程序。它鼓励开发者思考如何更好地组织和处理数据,而不是被技术细节所困扰。借助 Vue,我们可以创建出既美观又实用的用户界面,同时确保代码库的长期健康和可持续发展。让我们充分利用 Vue 的优势,专注于业务开发,创造出更加优秀的产品和服务。