【学习笔记】Vue3(Ⅰ)

本文介绍了Vue3的主要特点,包括使用Vite快速搭建项目,详细阐述了Vue3的setup函数、ref和reactive的区别与使用,以及如何创建响应式数据。还探讨了Vue3的生命周期、自定义Hook和状态管理,帮助读者掌握Vue3的基础知识。
摘要由CSDN通过智能技术生成

Vue3(Ⅰ)

1、 概述

      1.1、概述

         Vue.js 是一个流行的前端 JavaScript 框架,用于构建交互式的 Web 用户界面。Vue3 是 Vue.js 的下一个主要版本,带来了许多令人期待的新特性和改进

特性 描述
Composition API
(组合式 API)
Vue 3 引入了 Composition API,这是一种新的组件组织方式,使得组件更易于阅读、理解和维护。它允许将代码按逻辑功能组织,而不是按照生命周期函数
响应性系统的重写 Vue 3 中的响应性系统进行了重写,性能得到了显著提升。新的响应性系统采用了 Proxy 来实现,相比之前的 Object.defineProperty,Proxy 具有更好的性能
Teleport
(传送门)
Vue 3 引入了 Teleport 组件,使得在 DOM 中的任意位置渲染组件变得更容易。这对于在应用中实现模态框、通知、弹出菜单等功能非常有用
Fragment
(片段)
Vue 3 支持使用片段(Fragment),这允许组件返回多个根节点而无需包装元素。这样可以使得组件更加灵活
Suspense
(悬挂)
Vue 3 中引入了 Suspense 组件,用于优雅地处理异步操作。它能够在等待异步组件加载时显示备用内容,提高了用户体验
性能优化 Vue 3 在性能方面进行了多项优化,包括虚拟 DOM 的改进、Tree-shaking 支持、更高效的组件更新算法等,使得应用程序的性能得到了提升
TypeScript 支持 Vue 3 对 TypeScript 的支持更加友好,提供了更好的类型推断和类型检查,使得开发者在使用 TypeScript 时更加流畅

      1.2、使用 Vite 创建工程

            1.2.1 Vite 介绍

        Vite(法语意为“快速的”,发音 /it,发音同“veet”)是一个由 Vue.js 核心团队开发的新型前端构建工具(对标 Webpack)。它的目标是提供一种快速、简单的开发体验,特别是针对现代化的前端开发。它主要由两部分组成:① 开发服务器,它基于 原生 ES 模块 提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR)。② 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。Vite 意在提供开箱即用的配置,同时它的 插件 AP 和 javaScriptAPI 带来了高度的可扩展性,并有完整的类型支持

主要特点 描述
快速的冷启动 Vite 利用了 ES Module(ESM)的特性,在开发模式下不需要打包,而是直接使用原生 ES Module,因此具有非常快速的冷启动时间。这意味着在开发过程中,你可以更快地看到修改后的效果
按需编译 Vite 可以以模块为单位进行编译,只编译你实际需要的部分。这样,在开发过程中,不需要重新编译整个应用,而是只编译修改的部分,从而提高了开发效率
内置开发服务器 Vite 内置了一个开发服务器,支持热模块替换(HMR),并且使用原生 ES Module 运行代码,从而使得开发过程更加流畅
支持 Vue 3 和 TypeScript Vite 对 Vue 3 和 TypeScript 有很好的支持,可以让你在项目中轻松地使用它们
插件系统 Vite 提供了一个灵活的插件系统,可以轻松地扩展其功能,满足项目的特定需求

        Webpack 的构建:入口文件开始,然后分析路由、分析模块、打包,服务才可以启动,因此尝试过使用 webpack 去进行项目的构建时会感受到还是相对较慢的,特别是写的组件一多的时候这种感觉就更明显了
在这里插入图片描述
        Vite 的构建:Vite 一上来就直接可以启动服务,然后按需地进行分析、打包,因此在构建项目的时候会感觉到比 Webpack 快一些
在这里插入图片描述
        总的来说,Vite 的出现为前端开发提供了一种全新的开发体验,尤其适用于 Vue.js 项目,使得开发者可以更快、更简单地构建出现代化的 Web 应用程序

            1.2.2 创建工程

         首先执行nrm use npm切换成官方镜像,这样下载貌似快一点,然后执行npm create vue@latest创建项目(应该是要比 vue-cli 在创建 vue2 要快一些),执行完创建命令之后,可以进行自定义的配置如下
在这里插入图片描述

① JSX(JavaScript XML):是一种 JavaScript 的语法扩展,它允许在 JavaScript 代码中直接编写类似 XML 或 HTML 的标签。JSX 最初由 React 引入,并广泛用于 React 应用开发中,但它也可以在其他框架中使用
② Pinia 是一个用于 Vue.js 应用的状态管理库,被设计为 Vuex 的下一代替代品。Pinia 提供了一种更简单、更直观的方式来管理应用状态,同时保持与 Vue 生态系统的良好集成

         然后按照下方的绿色字体来启动项目,分别是:进入刚创建的项目目录cd vue_test、安装依赖npm i、启动npm run dev(Vite 魅力时刻,可以体验下其构建的速度多快),执行之后就可以看到项目跑起来了
在这里插入图片描述
         访问蓝字指示的服务器地址,就可以访问到内置的示例了
在这里插入图片描述

      1.3、项目文件结构

        新创建的 Vue3 项目可以看到其大致有如下的文件结构

vue_test/						# 根目录
├── .vscode/					# 存放 VsCode 的配置文件
│   └── extensions.json			# Vue3 推荐开发者在该项目中使用的 VsCode 扩展 
├── node_modules/				# 包存放目录
├── public/						# 静态资源目录
│   └── favicon.ico				# 浏览器标签页图标
├── src/						# 源代码目录
│   ├── assets/					# 静态资源文件,如样式表、图片等
│   ├── components/				# Vue 组件文件夹,存放项目的组件
│   ├── App.vue					# 根组件,是整个应用的主入口
│   └── main.ts					# 入口文件,初始化并挂载 Vue 实例
├── .gitignore					# git忽略文件
├── env.d.ts					# TS 的声明文件,相当于 Webpack 配置文件中 resolve.extensions的作用,让 TS 能够识别其它后缀的文件
├── index.html					# 项目的入口文件
├── package.json				# 项目的配置文件
├── README.md					# 项目的说明文件(可删)
├── tsconfig.app.json			# 该文件常用于 Angular 项目中,用于配置 Angular 应用的 TS 编译选项
├── tsconfig.json				# TS 的主要配置文件
├── tsconfig.node.json			# 该文件常用于 NodeJS 项目中,用于配置 Node.js 应用的 TS 编译选项
└── vite.config.ts				# Vite 构建工具的配置文件,用于配置 Vite 项目的构建选项、插件、中间件等

2、 基础

      2.1、setup

            2.1.1 初识 setup

        使用 setup 有如下一些基本的注意点
        ① setup 函数是组件内部的一个特殊选项,它用于替代 Vue 2 中的 data、computed、methods 等选项,用于配置组件的状态和行为
        ② vue2 中 data 配置中的变量在 vue3 中作为 setup 函数中的普通变量,同理 vue2 中 methods 配置中的函数在 vue3 中作为 setup 函数中的普通函数
        ③ setup 函数中的 this 是 undefined,弱化了 this 的使用
        ④ setup 函数的执行时机先于 beforeCreate 钩子函数

<!-- src/components/Person.vue -->
<template>
    <h2>姓名:{
  { name }}</h2>
    <h2>年龄:{
  { age }}</h2>
    <button @click="changeName">改变名字</button>
    <button @click="changeAge">改变年龄</button>
</template>

<script>
export default {
     
    // 组件名
    name: "Person",
    // setup 函数
    setup() {
     
    	console.log(this); // undefined
        let name = "niki";
        let age = 18;
        function changeName() {
     
            name = "pyy";
        }
        function changeAge() {
     
            age += 1;
        }
        return {
     name, age, changeName, changeAge};
    },
};
</script>

<style scoped>
button {
     
    margin-right: 10px;
}
</style>

Tip
1、Vue3 的模板做了改进,现在不需要在 template 标签中再套一层 div 了,可以直接将内容写在 template 下
2、上面给出的例子中,在数据在变更之后不会响应式地渲染到页面中

            2.1.2 setup 的返回值

        当 setup 的返回值不是一个对象,而是一个返回了字符串的函数时,这个字符串将作为该组件的模板,即替换掉 template 中所写的内容

<!-- src/components/Person.vue -->
<template>
    <h2>姓名:{
  { name }}</h2>
    <h2>年龄:{
  { age }}</h2>
</template>

<script>
export default {
     
    name: "Person",
    setup() {
     
        let name = "niki";
        let age = 18;
        return () => "Hello World"; // 返回一个字符串
    },
};
</script>

            2.1.3 setup 的触发时机

        在组件实例化时,setup 函数是最先执行的代码之一,它比 beforeCreate 生命周期钩子执行的还要更早

<!-- src/components/Person.vue -->
<template></template>

<script>
export default {
     
    name: "Person",
    beforeCreate() {
     
        console.log("this is beforeCreate");
    },
    setup() {
     
        console.log("this is setup");
    },
};
</script>

        我们知道数据代理、数据监测工作在 created 生命钩子调用时才完成,因此,如果 setup 函数和 OptionsAPI (data、methods这些配置项)同时出现时,OptionsAPI 可以访问 setup 的内容。相反,由于 setup() 在 beforeCreate 之前就已经解析完毕,它不可能知道 data、methods… 中有什么东西,因此 setup() 不能访问 OptionsAPI 中的数据

<!-- src/components/Person.vue -->
<template>
    <h2>姓名:{
  { myname }}</h2>
    <h2>年龄:{
  { getAge() }}</h2>
</template>

<script>
export default {
     
    name: "Person",
    data() {
     
        return {
     
            myname: this.name,
        };
    },
    methods: {
     
        getAge() {
     
            return this.age;
        },
    },
    setup() {
     
        let name = "niki";
        let age = 18;
        return {
     name, age};
    },
};
</script>

Tip:setup 函数需要将数据、函数 return 出来算是被挂载到组件实例身上,此时 data、methods 中才可以通过 this.xxx 来访问 setup 中的内容,没有 return 的话是访问不到的

            2.1.4 setup 语法糖

        由于在 setup 函数中每次定义完要进行 return 才能使用,有时候可能会忘记直到项目报错才想起来是忘记 return 了,会比较烦,因此可以采用 setup 语法糖来简写

<!-- src/components/Person.vue -->
<template>
    <h2>姓名:{
  { name }}</h2>
    <h2>年龄:{
  { getAge() }}</h2>
</template>

<script>
export default {
     
    name: "Person",
};
</script>

<script setup>
let name = "niki";
let age = 18;
function getAge() {
     
    return age;
}
</script>

        这样的写法会有一个普通的 script 用来进行组件的配置,还有一个带有 setup 字眼的 script 标签用来承载组合式 API 的(因此组件名要是在这里配置会出错),如果觉得这样写很难受,想合并到一起的话,可以借助插件来解决这个问题

安装:npm i vite-plugin-vue-setup-extend -D

// 修改 vite.config.ts 文件

// 引入
import VueSetupExtend from 'vite-plugin-vue-setup-extend'

// 添加插件
plugins: [
	... // 其它插件
    VueSetupExtend() // 添加这个
]

         然后现在组件的名字可以通过 name 属性来指明

<!-- src/components/Person.vue -->
<template>
    <h2>姓名:{
  { name }}</h2>
    <h2>年龄:{
  { getAge() }}</h2>
</template>

<script setup name="Person">
let name = "niki";
let age = 18;
function getAge() {
     
    return age;
}
</script>

      2.2、ref 函数

            2.2.1 概述

         在 Vue 3 中,ref 是一个用于创建响应式数据的 API,它主要用于定义基本类型(如数字、字符串、布尔值)和对象类型的响应式引用。与 reactive API 不同,ref 更适用于单个值或引用的场景

注意:ref 可以用于创建单个基本类型的响应式数据,也可以用于创建对象类型的响应式数据,只不过更适用于前者

            2.2.2 创建单个基本类型的响应式数据示例

<!-- src/components/Person.vue -->
<template>
    <h2>姓名:{
  { name }}</h2>
    <h2>年龄:{
  { age }}</h2>
</template>

<script setup name="Person">
    import {
      ref } from "vue";
    let name = ref("niki"); // 响应式数据,一个 RefImpl 实例
    console.log(name); 
    let age = 18; // 普通字符串
    console.log(age);
    function changeName() {
     
        name.value = "pyy";
    }
</script>

         运行结果如下,可见使用 ref 创建响应式数据得到的是一个 RefImpl 实例,RefImpl 是 Vue 内部实现的一种机制,用来管理响应式引用的行为
         此时在 script 标签中要访问、修改响应式数据需要调用 RefImpl 实例的 value 属性,而在模板中可以直接使用变量名即可,因为在背后会自动帮我们去调取其 value 值
在这里插入图片描述

            2.2.3 RefImpl

         RefImpl 是 Vue 3 中用来实现 ref 的基础类。它的主要作用是封装一个值,并通过 value 属性来访问和修改这个值,同时确保这个值在修改时能够触发依赖它的响应式更新

主要特性 描述
value 属性 RefImpl 的核心特性是其 value 属性,通过这个属性可以访问和修改被封装的值
响应式更新 当 value 被修改时,会触发依赖于这个 ref 的响应式更新

         RefImpl 类的简要实现有如

class RefImpl {
   
  // 属性 
  public dep;
  private _value;  // 原始值
  // 构造函数
  constructor(value) {
   
    this._value = value;
    this.dep = new Map(); // 用来存储依赖
  }
  // 对 _value 的数据监视
  get value() {
   
    track(this, 'get', 'value'); // 收集依赖
    return this._value;
  }
  set value(newValue) {
   
    if (newValue !== this._value) {
   
      this._value = newValue;
      trigger(this, 'set', 'value', newValue); // 触发依赖更新
    }
  }
}

// 暴露 
function ref(value) {
   
  return new RefImpl(value);
}
export {
    ref }

            2.2.4 Proxy 类

        Proxy 是一个用于定义基本操作(如属性查找、赋值、枚举、函数调用等)的自定义行为的对象。Proxy 是 ES6(ECMAScript 2015)引入的一个强大的特性,它允许开发者拦截并自定义对象的操作,从而实现更灵活和强大的功能

实例化:new Proxy(target, handler)
1、target:目标对象,即被代理的对象
2、handler:处理程序对象,一个包含捕获器(trap)的对象

捕获器 描述
get 拦截属性访问操作
set 拦截属性设置操作
has 拦截 in 操作符
deleteProperty 拦截属性删除操作
ownKeys 拦截对象自身属性的枚举操作
apply 拦截函数调用操作
construct 拦截 new 操作符
getOwnPropertyDescriptor 拦截 Object.getOwnPropertyDescriptor 操作
defineProperty 拦截 Object.defineProperty 操作
preventExtensions 拦截 Object.preventExtensions 操作
getPrototypeOf 拦截 Object.getPrototypeOf 操作
setPrototypeOf 拦截 Object.setPrototypeOf 操作
isExtensible 拦截 Object.isExtensible 操作

        示例如下,可以看到 Proxy 其实就是用来做对象代理的

// 定义处理程序对象
const handler = {
   
    // get捕获器
    // target:被代理的对象,property:被访问的键,receiver:代理或继承代理的对象
    get(target, property, receiver) {
   
        console.log("正在获取数据...");
        return Reflect.get(target, property, receiver);
    },
    // set捕获器
    // value:要设置的新值
    set(target, property, value, receiver) {
   
        console.log("正在设置新的值...");
        return Reflect.
  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值