关于vue3

前言

Vue3 作为目前最流行的前端框架之一,带来了许多激动人心的新特性和改进。无论是性能优化、开发体验还是代码组织方式,Vue3 都有了质的飞跃。本博客将带你从零开始,首先学习如何搭建 Vue 3 项目,然后逐步深入其核心特性,并通过一个实战项目,让你掌握 Vue3 的开发技巧。

第一章:搭建你的第一个 Vue 3 项目

在开始学习 Vue3 的核心特性之前,我们首先需要一个可以运行的项目环境。目前,官方最推荐的方式是使用 Vite 来创建 Vue3 项目,因为它能提供极速的开发体验。

前提条件

确保你的电脑上已经安装了 Node.js (推荐版本为 18.0 或更高)。你可以在终端中运行以下命令来检查 Node.js 是否安装成功:

bash 复制代码
node -v
# v18.17.1  # 看到类似这样的版本号即表示安装成功

步骤 1: 使用 Vite 创建项目

打开你的终端(在 Windows 上可以使用 CMD 或 PowerShell,在 macOS/Linux 上使用 Terminal),然后运行以下命令:

bash 复制代码
# npm 方式 (推荐)
npm create vite@latest

# yarn 方式 (如果你习惯使用 yarn)
# yarn create vite

# pnpm 方式 (如果你习惯使用 pnpm)
# pnpm create vite

步骤 2: 配置项目信息

运行命令后,Vite 会引导你进行项目配置:

  1. 项目名称 : 输入你的项目名称,例如 vue3-todo-app
  2. 选择框架 : 上下箭头键选择 Vue,然后按回车。
  3. 选择变体 : 再次使用上下箭头键,根据你的喜好选择 JavaScriptTypeScript。对于本教程,选择 JavaScript 即可。

配置过程如下所示:

bash 复制代码
√ Project name: ... vue3-todo-app
√ Select a framework: >> Vue
√ Select a variant: >> JavaScript

Scaffolding project in /path/to/your/project/vue3-todo-app...

Done. Now run:

  cd vue3-todo-app
  npm install
  npm run dev

步骤 3: 进入项目并安装依赖

根据终端的提示,执行以下命令:

bash 复制代码
# 进入你刚刚创建的项目目录
cd vue3-todo-app

# 安装项目所需的依赖包
npm install

步骤 4: 启动开发服务器

依赖安装完成后,运行以下命令来启动本地开发服务器:

bash 复制代码
npm run dev

启动成功后,你会在终端看到类似下面的信息,告诉你项目运行在哪个地址上:

bash 复制代码
  VITE v4.4.9 ready in 300 ms

  ➜  Local:   http://127.0.0.1:5173/
  ➜  Network: use --host to expose

现在,打开你的浏览器,访问 http://127.0.0.1:5173/,你应该能看到 Vue3 的欢迎页面,这表示你的项目已经成功创建并运行起来了!

项目目录结构

让我们简单了解一下 Vite 创建的 Vue3 项目结构:

bash 复制代码
vue3-todo-app/
├── node_modules/    # 项目依赖
├── public/          # 静态资源文件夹
├── src/             # 源代码文件夹 (我们主要在这里工作)
│   ├── assets/      # 图片、字体等资源
│   ├── components/  # Vue 组件文件夹
│   │   └── HelloWorld.vue # 一个示例组件
│   ├── App.vue      # 根组件
│   ├── main.js      # 入口文件,用于创建 Vue 应用
│   └── style.css    # 全局样式文件
├── .gitignore       # Git 忽略文件配置
├── index.html       # 应用的 HTML 入口
├── package.json     # 项目配置和依赖管理
└── vite.config.js   # Vite 的配置文件

第二章:为什么选择 Vue3?

Vue3 相比 Vue2 有以下几个显著的优势:

  1. 更好的性能:Vue3 使用了 Proxy 代替 Object.defineProperty 实现响应式,性能更高,并且支持对数组、Map、Set 等数据结构的响应式处理。
  2. 更小的体积:通过 Tree-shaking 优化,Vue3 的核心库体积更小,只引入需要的功能。
  3. Composition API:提供了全新的 Composition API,让代码组织更加灵活,更适合大型项目。
  4. TypeScript 支持:Vue3 完全用 TypeScript 重写,提供了更好的类型推断和类型检查。
  5. 更好的扩展性:支持自定义渲染器,可以将 Vue 组件渲染到不同的平台。

第三章:Vue3 核心特性

1. Composition API

Composition API 是 Vue3 最重要的新特性之一。它允许我们将组件的逻辑按照功能进行组织,而不是按照选项(data、methods、computed 等)进行分割。

示例代码:

bash 复制代码
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

// 响应式数据
const count = ref(0);

// 方法
const increment = () => {
  count.value++;
};

// 生命周期钩子
onMounted(() => {
  console.log('Component mounted');
});
</script>

2. 响应式系统

Vue3 的响应式系统基于 Proxy 实现,相比 Vue2 的 Object.defineProperty 有以下改进:

  • 支持对数组索引和 length 属性的响应式处理
  • 支持对 Map、Set、WeakMap、WeakSet 的响应式处理
  • 不需要手动处理数组的变异方法(push、pop、shift、unshift 等)

示例代码:

javascript 复制代码
import { reactive, watch } from 'vue';

const state = reactive({
  name: 'Vue3',
  age: 3,
  hobbies: ['reading', 'coding']
});

// 监听响应式数据变化
watch(() => state.name, (newVal, oldVal) => {
  console.log(`Name changed from ${oldVal} to ${newVal}`);
});

state.name = 'Vue'; // 触发 watch
state.hobbies.push('running'); // 触发 watch

3. 生命周期钩子

Vue3 的生命周期钩子相比 Vue2 有一些变化,并且可以在 Composition API 中使用。

常用生命周期钩子:

  • onBeforeMount:组件挂载前调用
  • onMounted:组件挂载后调用
  • onBeforeUpdate:组件更新前调用
  • onUpdated:组件更新后调用
  • onBeforeUnmount:组件卸载前调用
  • onUnmounted:组件卸载后调用

示例代码:

bash 复制代码
<script setup>
import { onMounted, onUnmounted } from 'vue';

onMounted(() => {
  console.log('Component mounted');
});

onUnmounted(() => {
  console.log('Component unmounted');
});
</script>

4. 模板语法改进

Vue3 的模板语法相比 Vue2 有一些改进,包括:

  • 支持多个根节点
  • 支持片段(Fragment)
  • 支持 Teleport 组件,可以将组件的内容渲染到 DOM 树的其他位置
  • 支持 Suspense 组件,可以处理异步组件的加载状态

示例代码:

bash 复制代码
<template>
  <div>Root node 1</div>
  <div>Root node 2</div>
</template>

第四章:实战项目:Todo List

接下来,我们将通过一个简单的 Todo List 项目,来实践 Vue3 的核心特性。

编写 Todo List 组件

src/components 目录下创建 TodoList.vue 文件,并填入以下代码:

bash 复制代码
<template>
  <div class="todo-list">
    <h1>Todo List</h1>
    
    <!-- 添加 todo -->
    <div class="add-todo">
      <input 
        type="text" 
        v-model="newTodo" 
        placeholder="Add a new todo..."
        @keyup.enter="addTodo"
      >
      <button @click="addTodo">Add</button>
    </div>
    
    <!-- 过滤 todo -->
    <div class="filters">
      <button 
        :class="{ active: filter === 'all' }"
        @click="setFilter('all')"
      >
        All
      </button>
      <button 
        :class="{ active: filter === 'active' }"
        @click="setFilter('active')"
      >
        Active
      </button>
      <button 
        :class="{ active: filter === 'completed' }"
        @click="setFilter('completed')"
      >
        Completed
      </button>
    </div>
    
    <!-- 显示 todo 列表 -->
    <ul class="todo-items">
      <li 
        v-for="todo in filteredTodos" 
        :key="todo.id"
        :class="{ completed: todo.completed }"
      >
        <input 
          type="checkbox" 
          v-model="todo.completed"
        >
        <span>{{ todo.text }}</span>
        <button @click="deleteTodo(todo.id)">×</button>
      </li>
    </ul>
    
    <!-- 清除已完成 todo -->
    <div class="clear-completed">
      <button 
        @click="clearCompleted"
        :disabled="!hasCompletedTodos"
      >
        Clear completed
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

// 响应式数据
const todos = ref([
  { id: 1, text: 'Learn Vue3', completed: false },
  { id: 2, text: 'Build a todo app', completed: false }
]);
const newTodo = ref('');
const filter = ref('all');

// 计算属性:过滤 todo
const filteredTodos = computed(() => {
  switch (filter.value) {
    case 'active':
      return todos.value.filter(todo => !todo.completed);
    case 'completed':
      return todos.value.filter(todo => todo.completed);
    default:
      return todos.value;
  }
});

// 计算属性:是否有已完成的 todo
const hasCompletedTodos = computed(() => {
  return todos.value.some(todo => todo.completed);
});

// 方法:添加 todo
const addTodo = () => {
  if (newTodo.value.trim() !== '') {
    todos.value.push({
      id: Date.now(),
      text: newTodo.value.trim(),
      completed: false
    });
    newTodo.value = '';
  }
};

// 方法:删除 todo
const deleteTodo = (id) => {
  todos.value = todos.value.filter(todo => todo.id !== id);
};

// 方法:设置过滤条件
const setFilter = (value) => {
  filter.value = value;
};

// 方法:清除已完成 todo
const clearCompleted = () => {
  todos.value = todos.value.filter(todo => !todo.completed);
};
</script>

<style scoped>
/* 样式部分保持不变 */
.todo-list {
  max-width: 600px;
  margin: 2rem auto;
  padding: 20px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
/* ... (省略其余样式以保持简洁,实际使用时请保留完整样式) ... */
</style>

在 App.vue 中使用 TodoList 组件

修改 src/App.vue 文件,使其内容如下:

bash 复制代码
<template>
  <div id="app">
    <TodoList />
  </div>
</template>

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

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

第五章:Vue3 生态系统

Vue3 拥有丰富的生态系统,包括:

  1. Vue Router:官方路由库,用于构建单页应用。
  2. Pinia:官方状态管理库,替代了 Vuex。
  3. Vue Test Utils:官方测试工具库,用于测试 Vue 组件。
  4. Vue Devtools:浏览器开发者工具,用于调试 Vue 应用。

使用 Pinia 进行状态管理

Pinia 是 Vue3 推荐的状态管理库,相比 Vuex 有以下改进:

  • 更简单的 API
  • 更好的 TypeScript 支持
  • 不需要嵌套模块
  • 支持组合式 API

示例代码:

  1. 安装 Pinia:

    bash 复制代码
    npm install pinia
  2. main.js 中引入 Pinia:

    javascript 复制代码
    import { createApp } from 'vue'
    import { createPinia } from 'pinia'
    import App from './App.vue'
    
    createApp(App)
      .use(createPinia())
      .mount('#app')
  3. 创建 store:

    javascript 复制代码
    // src/stores/todo.js
    import { defineStore } from 'pinia'
    
    export const useTodoStore = defineStore('todo', {
      state: () => ({
        todos: [
          { id: 1, text: 'Learn Vue3', completed: false },
          { id: 2, text: 'Build a todo app', completed: false }
        ]
      }),
      getters: {
        activeTodos: (state) => state.todos.filter(todo => !todo.completed),
        completedTodos: (state) => state.todos.filter(todo => todo.completed)
      },
      actions: {
        addTodo(text) {
          this.todos.push({
            id: Date.now(),
            text,
            completed: false
          })
        },
        deleteTodo(id) {
          this.todos = this.todos.filter(todo => todo.id !== id)
        },
        toggleTodo(id) {
          const todo = this.todos.find(todo => todo.id === id)
          if (todo) {
            todo.completed = !todo.completed
          }
        }
      }
    })
  4. 在组件中使用 store:

    bash 复制代码
    <script setup>
    import { useTodoStore } from '@/stores/todo'
    
    const todoStore = useTodoStore()
    
    // 访问 state
    console.log(todoStore.todos)
    
    // 访问 getters
    console.log(todoStore.activeTodos)
    
    // 调用 actions
    todoStore.addTodo('Learn Pinia')
    </script>
相关推荐
6***830513 小时前
VMware虚拟机配置桥接网络
开发语言·网络·php
de_furina13 小时前
[C++]string类的使用和模拟实现
开发语言·c++·gitee
代码游侠13 小时前
数据结构——单向链表
linux·开发语言·数据结构·学习·算法·链表
csbysj202013 小时前
C 标准库 - <time.h>
开发语言
h***593313 小时前
JAVA进阶 Thread学习06 synchronized关键字
java·开发语言·学习
j***485413 小时前
【JSqlParser】Java使用JSqlParser解析SQL语句总结
java·开发语言·sql
2301_7951672013 小时前
Python 高手编程系列一十五:使用 __new __()方法覆写实例创建过程
开发语言·网络·python
如意.75913 小时前
【C++】——异常
java·开发语言
Elnaij13 小时前
从C++开始的编程生活(14)——容器适配器——stack和queue
开发语言·c++
FAREWELL0007513 小时前
Lua学习记录(5) --- Lua中的协同程序 也称线程Coroutine的介绍
开发语言·学习·lua