myfreax

将您的Vue 2应用重构为Vue 3应用

在本教程中,我们将探讨Vue 3中的新功能。Vue 3为开发人员提供更好的方法来构建Vue应用程序。

9 min read
By myfreax
将您的Vue 2应用重构为Vue 3应用

Vue 3 为开发人员提供替代和更好的方法来构建VUE应用程序。 Vue 3中的组合物API 和组合功能的介绍使代码组织和可重复使用的微风。

预期

在本教程中,我们将探讨Vue 3中的新功能。我们还将重构 Brad Traversy 开源Vue 2应用到Vue 3.在此过程中 ,您将学习如何使用新的Vue 3功能,包括组合API和Adition功能。 最后,您还将学习如何在Vue 3应用程序中使用新的 Vuex 4

没有涵盖的

  • Styling  - 我们不会详细介绍该项目中使用的CSS属性。 虽然它可以在项目存储库上为您提供
  • Vue 3的简介  - 本教程致力于熟悉Vue 3的composition API 和响应式的基础
  • TypeScript  - 我们不会介绍该项目范围内的Vue 3中Typescript的用法

先决条件:

  • 假设你基本了解JavaScript和Vue.js并改善你的开发技能
  • 请安装您选择的任何一种代码编辑器或安装 Visual Studio code
  • 本教程假设您对Vue 2和Vue 3的基本了解
  • 这不是Vue 3教程的介绍,你希望将vue 2项升级到vue 3

Vue 2有什么问题? 🤔

Vue 3的灵感来自于Vue2的现有局限性。其中一些是:

  • 组分变得不太可读,随着它们的增长,维护变得困难
  • Vue 2中的所有可用代码可重用性模式具有未解决的瓶颈
  • Vue 2具有有限的类型支持
  • 更多原因在这里

Vue 3🖐🏽

Vue 3旨在解决Vue2的现有限制。在Vue 3中使用composition 组合API,您可以根据逻辑组织组件代码,而不是组件选项。 这在Vue 2中存在问题,因为代码可以在多个组件选项中展开。 这使得Vue 3特别简单易读和维护。

入门

让我们从 brad traversy创建的 Vue 2项目开始。 该项目是一个TODO应用程序,您可以在其中执行以下操作:

  • 添加todos
  • 删除todos
  • 标记已完成todos
  • 筛选todos
  • 隐藏/显示所有todos
vue todos

在项目中,从API获取TODOS。 对数据执行的所有操作都在后端进行。

创建VUE应用程序

首先,您需要使用以下命令安装 Vue CLI v4.5 的最新版本:

yarn global add @vue/cli
#OR
npm install -g @vue/cli

创建VUE应用程序的过程没有改变。 如果您安装了 Vue CLI ,请运行以下命令以创建一个名为Vue3-todo的新VUE项目:

vue create vue3-todo

按照终端提示,然后选择Vue 3预设以完成设置过程。 务必选择Vuex作为项目所需功能的一部分。

项目文件中的一些明显的更改:

Vue 2使用new Vue()方法来引导新的VUE应用程序。 Vue 3使用createApp方法。 如果您想知道为什么需要这种更改,这是因为旧的语法使全局配置成为可能的永久变异的全局状态。以下是查看main.js文件:

main js file

Vuex 4现在有一个createStore()方法,符合Vue 3标准。 使用Vuex 4您可以在几行代码中创建Vuex store。 以下是目前的实现:

Vue store created in a few lines of code

获取todos

从Vue 2的实现重构,当应用程序加载时,当App载入时调度action从中获取TODOS。 让我们在Vuex中设置一个action来处理:

// @/store/index.js
import { ACTION_TYPES } from "../constants/action-types";
import Vuex from "vuex";
import Axios from "axios";
export default Vuex.createStore({
  state: {
    todos: [],
  },
  mutations: {
    [ACTION_TYPES.fetchTodos]: (state, todos) => (state.todos = todos),
  },
  actions: {
    onFetchTodos: async ({ commit }) => {
      const response = await Axios.get(
        "https://jsonplaceholder.typicode.com/todos"
      );
      commit(ACTION_TYPES.fetchTodos, response.data);
    },
  },
});

这里,onFetchTodos action获取来Typicode的TODO列表并提交fetchTodos mutation。 然后,mutation更新状态对象中的todos。 我们将在Todo.vue组件中调度此action。

您可能已经注意到我们从不存在的文件导入ACTION_TYPES。 让我们创建它。 在根文件夹中,创建一个src/constants/action-types.js文件:

// @/constants/action-types.js
export const ACTION_TYPES = {
  fetchTodos: "fetchTodos",
  addTodo: "addTodo",
  deleteTodo: "deleteTodo",
  updateTodo: "updateTodo",
};

上面文件中指定的action类型将在整个项目中保持不变,并帮助我们在应用程序中维护命名一致性。 接下来,让我们创建一个src/components/Todos.vue文件,该文件将调度onFetchTodos action并返回Todos。

我建议在继续本教程之前阅读composition API文档。 让我们快速浏览这个组件中的一些新的Vue 3 Api:

setup() function

Vue 3使用组合composition API,可以在setup()函数内的组织组件的所有逻辑,该函数返回模板中所需的数据。 此功能使通过逻辑关注来组织组件成为可能。 这是因为我们可以在setup()函数中具有生命周期方法,计算属性,状态数据等。

onMounted()

Vue 3中的onMounted()钩子是Vue 2中mounted()。当组件调用钩子时执行的回调函数:

onMounted(() => {
  store.dispatch("onFetchTodos");
});

computed()方法

Vue 3中的computed方法是Vue2中的computed组件属性。它需要执行特定任务并返回响应引用。 引用是不变对象,它从getter中返回值:

const todos = computed(() => store.state.todos);

最后,请注意我们在setup() function中返回todos。 这就是我们如何在我们想要在模板中使用的函数中的数据。 目前,该应用程序在浏览器上看起来像这样:

todo list

添加todos

自从我们使用Vuex以来,我们需要一个action动作和一个要更新Todos状态的mutation。 要实现该方法,请使用下面的代码更新store:

// @/store/index.js

import { ACTION_TYPES } from "../constants/action-types";
import Vuex from "vuex";
export default Vuex.createStore({
  state: {
    todos: [],
  },
  mutations: {
    // ...
    [ACTION_TYPES.addTodo]: (state, todo) => state.todos.unshift(todo),
  },
  actions: {
    // ...
    onAddTodo: async ({ commit }, title) => {
      const response = await Axios.post(
        "https://jsonplaceholder.typicode.com/todos",
        { title, completed: false }
      );
      commit(ACTION_TYPES.addTodo, response.data);
    }
  },
});

onAddTodo action需要在状态和新的TODO中添加到现有TODOS并提交addTodo突变。 addTodo突变将待办事项更新为onAddTodo操作中的新TODO。

另外,在“组件”文件夹中,创建一个components/AddTodo.vue文件。 此组件将呈现一个表单,该表单将允许用户将新Todo添加到现有列表中:

// @/components/AddTodo.vue
<template>
  <div>
    <form>
      <input type="text" v-model="title" placeholder="Add to do ..." />
      <input v-on:click="addNewTodo" type="submit" value="Add" />
    </form>
    <br />
  </div>
</template>
<script>
import { ref } from "vue";
import { useStore } from "vuex";
export default {
  name: "AddTodo",
  setup() {
    const store = useStore();
    const title = ref("");
    const addNewTodo = (e) => {
      e.preventDefault();
      store.dispatch("onAddTodo", {
        title: title.value,
      });
      title.value = "";
    };
    return {
      title,
      addNewTodo,
    };
  },
};
</script>

该组件类似于Todos组件。 这里唯一的新事物是第17行的ref 函数。使用Vue 3,我们可以使用ref function在组件中的任何位置使变量变为响应式的。 考虑这个片段:

// Declaration    
const title = ref("");

ref的Reactivity响应式

上面的片段创建具有初始值的title 响应式变量,其值空String。 要读取变量的值,请执行title.value。 您可以阅读更多关于Vue 3 Refs的信息

最后,我们返回title变量,以及setup()中的addNewTodo fucntion,使其可用于模板中。 如果在浏览器上查看应用程序,则应该能够添加TODOS:

add todos to board

过滤todos

调用fetch todos api时,返回数组包含200个todo。 因此,它们提供了一个api来过滤可以获取的TODO数量。 让我们创建一个过滤器组件,允许用户过滤他们想要获取的Todos的数量。 创建一个src/components/FilterTodo.vue文件并使用下面的代码更新文件:

// @/components/FilterTodo.vue
<template>
  <div>
    <form @submit="filterTodos">
      <input type="number" v-model="limit" placeholder="Add to do ..." />
      <input @click.prevent="filterTodos" type="submit" value="Filter" />
    </form>
    <br />
  </div>
</template>
<script>
import { ref } from "vue";
import { useStore } from "vuex";
export default {
  name: "FilterTodos",
  setup() {
    const limit = ref(200);
    const store = useStore();
    const filterTodos = () => {
      store.dispatch("onFilterTodos", limit.value);
    };
    return {
      limit,
      filterTodos,
    };
  },
};
</script>

此组件呈现输入表单以收集要过滤的todos数量。 提交后,调度onFilterTodos action。 此action提交fetchTodos mutation,然后更新TODOS状态。 让我们使用onFilterTodos action更新Vuex存储:

// @/store/index.js

import { ACTION_TYPES } from "../constants/action-types";
import Vuex from "vuex";
export default Vuex.createStore({
  state: {
    todos: [],
  },
  mutations: {
    // ...
    [ACTION_TYPES.fetchTodos]: (state, todos) => (state.todos = todos),
  },
  actions: {
    // ...
    onFilterTodos: async ({ commit }, limit) => {
      const response = await Axios.get(
        `https://jsonplaceholder.typicode.com/todos?_limit=${limit}`
      );
      commit(ACTION_TYPES.fetchTodos, response.data);
    },
  },
});

onFilterTodos action调用Typicode过滤endpoint,其中来自组件中的值。 然后我们提交fetchTodos突变,该突变与响应数据更新Todos状态。 让我们在浏览器上尝试一下:

fetchtodos

项目repo

此项目可在GitHub上查看 。 完整的项目包含我们在本教程中无法涵盖的一些功能。 其中一些是:

  • 删除todos
  • 更新todos
  • 标记todos完成
  • 切换todos可见性

结论

在此项目中,我们将标准Vue 2应用程序和Vuex重构成为一个全新的Vue 3应用程序。 在这个过程中,我们看一些Vue 3的功能,如组合compositionAPI,这些功能和Vuex 4. Vue 3仍在改变,所以在阅读文章时,有些功能代码可能会有所不同,请根据官方Vue 3文档作出修改。