Yang's blog Yang's blog
首页
Java
密码学
机器学习
命令手册
关于
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

xiaoyang

编程爱好者
首页
Java
密码学
机器学习
命令手册
关于
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • SpringCloud

    • 微服务架构介绍
    • SpringCloud介绍
    • Spring Cloud:生产者与消费者
    • Spring Cloud Eureka:构建可靠的服务注册与发现
    • Spring Cloud Ribbon:负载均衡
    • Spring Cloud Fegin:服务调用
    • Spring Cloud Hystrix:熔断器
    • Spring Cloud Zuul:统一网关路由
    • Spring Cloud Config:配置中心
  • Java后端框架

    • LangChain4j

      • 介绍
      • 快速开始
      • Chat and Language Models
      • Chat Memory
      • Model Parameters
      • Response Streaming
      • AI Services
      • Agent
      • Tools (Function Calling)
      • RAG
      • Structured Outputs
      • Classification
      • Embedding (Vector) Stores
      • Image Models
      • Quarkus Integration
      • Spring Boot Integration
      • Kotlin Support
      • Logging
      • Observability
      • Testing and Evaluation
      • Model Context Protocol
  • 八股文

    • 操作系统
    • JVM介绍
    • Java多线程
    • Java集合框架
    • Java反射
    • JavaIO
    • Mybatis介绍
    • Spring介绍
    • SpringBoot介绍
    • Mysql
    • Redis
    • 数据结构
    • 云计算
    • 设计模式
    • 计算机网络
    • 锁核心类AQS
    • Nginx
  • 前端技术

    • 初识Vue3
      • 1. Vue 的历史和背景
      • 2. Vue3 新特性概览
      • 3. Composition API:新的组件组织方式
        • 3.1 Vue3 引入 Composition API
        • 3.2 与 Options API 的对比
      • 4. 响应式系统
        • 4.1 声明响应式状态
        • ref() 的使用
        • 为什么要使用 ref()?
        • 深层响应性
        • 4.2 reactive() 的使用
        • Reactive Proxy vs. Original
        • 4.3 reactive() 的局限性
        • 4.4 ref() 解包与 reactive() 的结合
        • 4.5 数组和集合的注意事项
        • 4.6 在模板中解包的注意事项
      • 4. Pinia状态管理库
        • 4.1 Vue3 引入 Pinia 作为新的状态管理库
        • 4.2 与 Vuex 的对比
      • 5. 更好的 TypeScript 支持
        • 5.1 Vue3 原生支持 TypeScript
      • 6. Vite 替代 Vue CLI
        • 6.1 Vue3 引入 Vite 替代 Vue CLI
      • 7. 总结
    • Vue3数据双向绑定
    • Vue3生命周期
    • Vue-Router 组件
    • Pinia 集中式状态存储
  • 中间件

    • RocketMQ
  • 开发知识

    • 请求参数注解
    • 时间复杂度和空间复杂度
    • JSON序列化与反序列化
    • Timestamp vs Datetime
    • Java开发中必备能力单元测试
    • 正向代理和反向代理
    • 什么是VPN
    • 正则表达式
  • Java
  • 前端技术
xiaoyang
2025-02-27
目录

初识Vue3

# 初识 Vue3 —— 从 Vue2 到 Vue3 的演变

# 1. Vue 的历史和背景

Vue.js 是由尤雨溪(Evan You)创建的一个渐进式 JavaScript 框架。Vue 的目标是通过简单的 API 和灵活的设计来简化开发者的前端开发体验。Vue 起源于 2013 年,最初是作为一个个人项目来改善自己在使用其他框架时遇到的痛点。Vue 在发布后受到了广泛的关注,特别是在前端界面开发和组件化开发领域。

Vue.js 的版本大致可以分为几个阶段:

  1. Vue 0.x:最早的版本,功能非常基础,主要是用来试验新概念。
  2. Vue 1.x:Vue 1.x 于 2015 年发布,开始获得广泛的使用,并且逐渐有了更完整的生态系统。
  3. Vue 2.x:2016 年 Vue 2.0 发布,成为主流前端框架之一,引入了 虚拟 DOM、响应式数据绑定、组件化 等核心特性,并得到社区的大量支持。Vue 2.x 的成功奠定了其在前端开发中的地位。
  4. Vue 3.x:Vue 3 在 2020 年正式发布,引入了很多新的特性和 API,并对性能做了全面优化,是一个具有里程碑意义的版本。

# 2. Vue3 新特性概览

在 Vue3 中,最显著的变化包括:

  • Composition API:一种新的组件组织方式
  • 性能优化:更加高效的响应式系统
  • Pinia 作为新的状态管理库:取代 Vuex
  • 更好的 TypeScript 支持
  • Vue Router 和 Vuex 的变化:更现代化的 API
  • Vite 替代 Vue CLI:更高效的开发工具链

# 3. Composition API:新的组件组织方式

组合式 API(Composition API)是一系列 API 的集合,它使我们能够通过函数的方式来组织和编写 Vue 组件,而不再依赖于传统的选项式 API(Options API)。它允许我们在一个地方集中定义组件的状态、逻辑和生命周期钩子,提高了代码的组织性和可复用性。

组合式 API 包括:

  • 响应式 API:例如 ref() 和 reactive(),用于创建响应式数据、计算属性和侦听器。
  • 生命周期钩子:例如 onMounted() 和 onUnmounted(),在组件的不同生命周期阶段执行逻辑。
  • 依赖注入:例如 provide() 和 inject(),在组件中共享响应式状态。

组合式 API 是 Vue 3 的核心特性之一,也可以在 Vue 2.7 及更高版本中使用。对于 Vue 2.x,开发者可以通过官方插件 @vue/composition-api 来引入组合式 API。。

# 3.1 Vue3 引入 Composition API

Composition API 是 Vue3 引入的一种全新的组件设计方式,它允许开发者在一个地方集中定义组件的状态和行为,从而使得代码更加模块化和可重用。它通过 setup() 函数将组件的逻辑组织在一起。

Composition API 示例:

// Vue3 示例:Composition API
<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  • 简洁性:在 Vue3 中,逻辑集中在 setup() 函数中,所有的状态、方法、计算属性等都可以在这个函数里声明并返回,结构更加清晰。
  • 逻辑复用:使用 Composition API,可以将功能模块化到 composable 函数中,方便在多个组件间共享逻辑。

# 3.2 与 Options API 的对比

Vue2 Options API:

// Vue2 示例:Options API
<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },

  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件处理器绑定
  methods: {
    increment() {
      this.count++
    }
  },

  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Vue3 Composition API 相比于 Options API,更加灵活,允许开发者将状态、方法、计算属性等逻辑集中管理,易于维护和复用。

# 4. 响应式系统

Vue 3 的响应式系统利用 Proxy 代替了 Vue 2 中的 Object.defineProperty,使得响应式数据的处理更为高效和灵活。核心概念包括 ref() 和 reactive(),它们用于声明响应式状态。通过这些工具,Vue 能够追踪状态的变化,并自动更新视图。

# 4.1 声明响应式状态

在 Vue 3 中,声明响应式状态的两种主要方式是通过 ref() 和 reactive():

  • ref() 用于声明基本数据类型(如字符串、数字、布尔值等)的响应式状态。
  • reactive() 用于将对象(包括嵌套对象和数组)转换为响应式状态。

# ref() 的使用

ref() 用于声明一个简单的响应式引用,它返回一个包含 .value 属性的对象。你可以通过 .value 访问或修改它的值。

import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0); // count 是一个响应式变量,初始值为 0

    const increment = () => {
      count.value++; // 修改 count 的值
    };

    return { count, increment };
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13

在模板中,ref 会自动解包,因此我们不需要直接访问 .value,而是可以直接使用 count:

<template>
  <button @click="increment">{{ count }}</button>
</template>
1
2
3

# 为什么要使用 ref()?

ref() 让 Vue 可以追踪基本数据类型的变化。例如,当你修改 count.value 时,Vue 会自动更新 DOM。这种设计让 Vue 具有高效的响应式更新能力。你可能会好奇,为什么要用 .value?这是因为 Vue 使用 Proxy 来追踪状态变化,而 ref() 则通过 .value 来检测变化。

# 深层响应性

ref() 本身支持深层响应性。即便你声明一个包含嵌套对象或数组的 ref,Vue 会追踪对象内部的每一个属性或数组元素的变化。

import { ref } from 'vue';

const state = ref({
  nested: { count: 0 },
  arr: ['apple', 'banana']
});

// 修改嵌套属性时,Vue 会触发视图更新
state.value.nested.count++;
state.value.arr.push('orange');
1
2
3
4
5
6
7
8
9
10

如果不希望 Vue 跟踪嵌套对象的每个变化,可以使用 浅层 ref(),它只会追踪 .value 的变化,而不会递归地追踪对象内部的变化。

# 4.2 reactive() 的使用

reactive() 是另一种声明响应式状态的方式,它用于将整个对象变成响应式对象。它返回一个 Proxy,能够代理对象的所有属性,包括嵌套属性。

import { reactive } from 'vue';

const state = reactive({
  count: 0,
  user: { name: 'Alice' }
});

// 修改对象的属性时,Vue 会触发视图更新
state.count++;
state.user.name = 'Bob';
1
2
3
4
5
6
7
8
9
10

reactive() 适用于处理复杂对象和嵌套数据结构,而 ref() 通常用于基本数据类型。如果你的数据是对象或数组,reactive() 会自动将其转换为响应式。

# Reactive Proxy vs. Original

需要注意的是,reactive() 返回的是一个 Proxy,它与原始对象并不相等。更改原始对象不会触发视图更新,只有通过 reactive() 返回的 Proxy 对象才会生效。

const raw = { count: 0 };
const proxy = reactive(raw);

console.log(proxy === raw); // false
1
2
3
4

这意味着你应该始终使用通过 reactive() 返回的代理对象,而不是原始对象来进行操作。

# 4.3 reactive() 的局限性

尽管 reactive() 很强大,但它也有一些局限性:

  1. 只能用于对象:reactive() 只能用于对象类型的值(包括数组、对象、Map、Set 等)。它不能用于原始类型(如 string、number 或 boolean)。
  2. 无法替换整个对象:由于 Vue 使用属性访问来追踪变化,替换整个对象会导致原始引用的响应性丧失。例如:
let state = reactive({ count: 0 });
state = reactive({ count: 1 }); // 这里丢失了原始的响应性引用
1
2
  1. 不适用于解构:如果你解构了一个响应式对象的属性,Vue 将无法追踪这些属性的变化。为了避免这种情况,你应该传递整个对象而不是解构后的属性。
const state = reactive({ count: 0 });
let { count } = state; // 这里解构会导致 count 不再是响应式的
count++; // 不会更新原始的 state
1
2
3

# 4.4 ref() 解包与 reactive() 的结合

当 ref() 被作为 reactive() 对象的属性时,它会自动解包其 .value。这意味着你可以直接访问 state.count,而无需显式地使用 .value。

const count = ref(0);
const state = reactive({
  count
});

console.log(state.count); // 0
state.count = 1;
console.log(count.value); // 1
1
2
3
4
5
6
7
8

但是,ref 只会在顶级属性中自动解包。如果它嵌套在对象或数组内,你需要显式访问 .value。

# 4.5 数组和集合的注意事项

当 ref() 被作为数组或原生集合(如 Map 或 Set)中的元素时,它不会被自动解包。这意味着你仍然需要使用 .value 来访问和修改其值。

const books = reactive([ref('Vue 3 Guide')]);
console.log(books[0].value); // 使用 .value 来访问

const map = reactive(new Map([['count', ref(0)]]));
console.log(map.get('count').value); // 使用 .value 来访问
1
2
3
4
5

# 4.6 在模板中解包的注意事项

在模板中,只有 顶级的 ref 属性会被自动解包。如果 ref 嵌套在对象中,Vue 不会自动解包它,因此你需要显式地解构或访问 .value。

const count = ref(0);
const object = { id: ref(1) };

// 这是有效的
{{ count + 1 }} 

// 这不会按预期工作
{{ object.id + 1 }} // 结果是 [object Object]1,因为 object.id 没有解包

// 正确的做法是解构 id
const { id } = object;
{{ id + 1 }} // 结果是 2
1
2
3
4
5
6
7
8
9
10
11
12

# 4. Pinia状态管理库

Vue2 中的 Vuex 是官方推荐的状态管理库。虽然 Vuex 提供了强大的功能,但其 API 相对繁琐,尤其是在大型应用中,很多时候需要大量的样板代码(boilerplate)。此外,Vuex 在 Vue3 中的 Composition API 支持并不完美,开发者需要编写大量的类型声明,且代码结构相对复杂。

# 4.1 Vue3 引入 Pinia 作为新的状态管理库

Vue3 官方推荐 Pinia 作为新的状态管理解决方案,Pinia 是 Vue3 的官方状态管理库,拥有简洁的 API,更好地与 Composition API 集成,并且原生支持 TypeScript。

Pinia 示例:

// 安装 Pinia
npm install pinia

// 创建 store
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++;
    }
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 更简洁的 API:通过 defineStore() 创建 store,而不是 Vuex 中的 state、mutations 和 actions 等繁琐的结构。
  • 与 Composition API 更加契合:Pinia 的 API 设计与 Vue3 的 Composition API 紧密结合,使得状态管理变得更加直观。

# 4.2 与 Vuex 的对比

特性 Vuex Pinia
API 复杂度 较复杂,尤其是 mutations 和 actions 简洁,采用 defineStore() 定义 store
TypeScript 支持 需要手动类型声明,较复杂 原生支持 TypeScript,自动类型推导
响应式支持 基于 Vue 2 的响应式系统 基于 Vue 3 的 Proxy 响应式系统,性能更好
开发体验 需要多层次的配置和管理,学习曲线较陡峭 轻量、易于上手,集成 Composition API
状态持久化 可以通过插件实现(如 vuex-persistedstate) 支持内置持久化功能

# 5. 更好的 TypeScript 支持

Vue2 支持 TypeScript,但需要手动配置类型声明,且 API 设计并不完全兼容 TypeScript。开发者需要额外编写大量类型定义文件来使 Vue 和 Vuex 支持 TypeScript,这在一定程度上降低了开发效率。

# 5.1 Vue3 原生支持 TypeScript

Vue3 在设计时就将 TypeScript 作为一个核心需求,所有的 API 都与 TypeScript 紧密集成。Vue3 的所有核心 API 都具备良好的类型推导,避免了 Vue2 中繁琐的类型声明工作。

Vue3 TypeScript 示例:

import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    const count = ref<number>(0);  // 使用 TypeScript 定义类型

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

    return { count, increment };
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 自动类型推导:在 Vue3 中,ref() 和 reactive() 都具有自动的类型推导,开发者无需手动声明类型。
  • TypeScript 更友好:Vue3 的 API 更加兼容 TypeScript,开发者可以在使用时获得更多的类型提示和静态检查,减少类型错误。

# 6. Vite 替代 Vue CLI

Vue2 使用 Vue CLI 作为脚手架工具,Vue CLI 基于 Webpack,配置复杂,构建速度较慢,尤其是在开发过程中,由于热更新(HMR)的效率较低,开发体验较差。

# 6.1 Vue3 引入 Vite 替代 Vue CLI

Vue3 推荐使用 Vite,Vite 是一个基于原生 ES 模块的构建工具,极大地提高了开发中的热更新和构建速度,尤其适合现代 JavaScript 和 Vue3 项目的开发。

Vite 示例:

# 使用 Vite 创建 Vue3 项目
npm create vite@latest my-vue-app --template vue
cd my-vue-app
npm install
npm run dev
1
2
3
4
5
  • 零秒冷启动:Vite 在开发模式下能够做到 零秒冷启动,大幅提高开发效率。
  • 原生支持模块化:Vite 使用浏览器原生的 ES 模块,而不是传统的打包方式,使得开发过程更加轻便。

# 7. 总结

Vue3 的发布带来了许多重要的变化,从 Composition API 到 Pinia,再到 TypeScript 和 Vite,每个变化都使得开发者能够编写更高效、简洁、易于维护的代码。如果你还在使用 Vue2,是时候考虑迁移到 Vue3 了。希望这篇文章能够帮助你深入理解 Vue3 的新特性,并为你的开发过程提供更多的指导和灵感。

编辑 (opens new window)
上次更新: 2025/04/01, 01:48:12

← Nginx Vue3数据双向绑定→

最近更新
01
操作系统
03-18
02
Nginx
03-17
03
后端服务端主动推送消息的常见方式
03-11
更多文章>
Theme by Vdoing | Copyright © 2023-2025 xiaoyang | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式