你好,我是大圣,欢迎进入课程的第六讲。

在上一讲中,我带你搭建了项目的雏形,这是后面项目开发的起点。从今天开始,我就带你在这个骨架结构的基础之上,开始项目的实战开发。首先我们要掌握的,就是 Vue 3 的 Composition API + <script setup> 这种最新的代码组织方式。

Untitled

我们在前面的第三讲中,有详细地讲到过 Composition API ,相信你对这个 API 的语法细节已经有所掌握了。那你肯定会很好奇,这个 <script setup> 又是什么?为什么尤雨溪要在微博上强推 <script setup> 呢?

别急,今天我就带你使用 Composition API 和 <script setup> 去重构第二讲的清单应用。在重构的过程中,你能逐渐明白,Composition API 可以让我们更好地组织代码结构,而让你感到好奇的 <script setup> 本质上是以一种更精简的方式来书写 Composition API 。

Composition API 和 <script setup> 上手

首先我想提醒你,我们在这一讲中写代码的方式,就和前面的第二讲有很大的区别。

在第二讲中,我们开发清单应用时,是直接在浏览器里使用 Options API 的方式写代码;但在接下来的开发中,我们会直接用单文件组件——也就是 .vue 文件,的开发方式。这种文件格式允许我们把 Vue 组件的 HTML、CSS 和 JavaScript 写在单个文件内容中。下面我带你用单文件组件的方式,去重构第二讲做的清单应用。

我们现在已经搭建好了项目的骨架,以后在这个骨架之内会有很多页面和组件。从这里开始,我们就要逐步适应组件化的开发思路,新的功能会以组件的方式来组织。

按照上一讲制定的规范,首先,我们打开项目文件夹下面的 src 下的 components 目录,新建一个 Todolist.vue ,并在这个文件里写出下面的代码:

<template>
  <div>
    <h1 @click="add">{{count}}</h1>
  </div>
</template>

<script setup>
import { ref } from "vue";
let count = ref(1)
function add(){
    count.value++
}
</script>

<style>
h1 {
  color: red;
}
</style>

在上述代码中,我们使用 template 标签放置模板、script 标签放置逻辑代码,并且用 setup 标记我们使用 <script setup> 的语法,style 标签放置 CSS 样式。

从具体效果上看,这段代码实现了一个累加器。在 <script setup> 语法中,我们使用引入的 ref 函数包裹数字,返回的 count 变量就是响应式的数据,使用 add 函数实现数字的修改。需要注意的是,对于 ref 返回的响应式数据,我们需要修改 .value 才能生效,而在 <script setup> 标签内定义的变量和函数,都可以在模板中直接使用。

实现累加器以后,我们再回到 src/pages/Home.vue 组件中,使用如下代码显示清单应用。在这段代码里,我们直接 import TodoList.vue 组件,然后 <script setup> 会自动把组件注册到当前组件,这样我们就可以直接在 template 中使用来显示清单的功能。

<template>
    <h1>这是首页</h1>
    <TodoList />    
</template>

<script setup>
import TodoList from '../components/TodoList.vue'
</script>

这个时候我们就把清单功能独立出来了,可以在任意你需要的地方复用。在课程的后续内容中,我会详细给你介绍基于组件去搭建应用的方式。通过这种方式,你可以实现对业务逻辑的复用。这样做的好处就是,如果有其他页面也需要用到这个功能,可以直接复用过去。

然后,我们就可以基于新的语法实现之前的清单应用。下面的代码就是把之前的代码移植过来后,使用 ref 包裹的响应式数据。在你修改 title 和 todos 的时候,注意要修改响应式数据的 value 属性。

<template>
  <div>
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <ul v-if="todos.length">
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done" />
        <span :class="{ done: todo.done }"> {{ todo.title }}</span>
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from "vue";
let title = ref("");
let todos = ref([{title:'学习Vue',done:false}])

function addTodo() {
  todos.value.push({
    title: title.value,
    done: false,
  });
  title.value = "";
}
</script>