Vue 数据驱动页面,让我们专注于业务开发

引言

在现代前端开发中,数据驱动界面 (Data-Driven Interface,简称DDI )已经成为一种标准模式。它允许开发者通过简单的声明性代码来创建复杂的用户界面(UI),并且随着底层数据的变化自动更新这些界面。下面将使用todos(待办事项应用) 实例来介绍Vue数据驱动界面 。比较Vue2Vue3的优缺点。

专注于业务开发

在开始之前,我们要时刻牢记Vue设计哲学:

Vue更关注于业务开发,数据驱动页面。

因为Vue通过提供简洁的语法、组件化架构、双向数据绑定和高效的响应式系统等特性,简化了用户界面的构建过程,使开发者能够将更多精力集中在解决业务问题上,而非纠结于复杂的前端技术细节。

我们要使用数据来驱动界面,保证数据和界面数据的一致性。为了开发者专注于业务开发,Vue给我们提供许多的方法:

  1. {{}} : 插值表达式,它用于将 Vue 实例中的数据属性插入到模板中。这种插值是单向绑定
  2. v-bind : 可缩写为:。单向数据绑定,动态绑定,它允许你在运行时根据 Vue 实例的数据动态地设置 HTML 属性的值。
  3. v-model : 在表单输入元素或组件上创建双向绑定。

todos 业务(vue2版)

下面开始我们的todos。我们需要考虑应该有哪些业务,而不只专注于代码的语法功能。

这个应用的功能包括添加新的待办事项、标记已完成的任务、显示未完成任务的数量,并全选/取消全选所有任务。

我们本篇文章致力于理解Vue的数据驱动能力,所以我们只是在html中引入Vue,并没有也不需要创建一个完整的项目。

我们分别来完成这几个功能,先来使用Vue2的方法,之后再来将Vue2Vue3进行比较。

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-bindspan根据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放一起。这有利于大型项目的维护。

可以清楚的看到vue2vue3之间的区别

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 的优势,专注于业务开发,创造出更加优秀的产品和服务。

相关推荐
过往记忆3 小时前
告别 Shuffle!深入探索 Spark 的 SPJ 技术
大数据·前端·分布式·ajax·spark
高兴蛋炒饭4 小时前
RouYi-Vue框架,环境搭建以及使用
前端·javascript·vue.js
m0_748240444 小时前
《通义千问AI落地—中》:前端实现
前端·人工智能·状态模式
ᥬ 小月亮4 小时前
Vue中接入萤石等直播视频(更新中ing)
前端·javascript·vue.js
呜呼~225145 小时前
前后端数据交互
java·vue.js·spring boot·前端框架·intellij-idea·交互·css3
神雕杨5 小时前
node js 过滤空白行
开发语言·前端·javascript
网络安全-杰克5 小时前
《网络对抗》—— Web基础
前端·网络
m0_748250745 小时前
2020数字中国创新大赛-虎符网络安全赛道丨Web Writeup
前端·安全·web安全
周伯通*6 小时前
策略模式以及优化
java·前端·策略模式
艾斯特_6 小时前
前端代码装饰器的介绍及应用
前端·javascript