Vue3的新特性变化,上手指南!

news2024/9/29 9:30:38

文章目录

  • 一、Vue3相比Vue2,更新了什么变化?
  • 二、Proxy 代理响应式原理
  • 三、组合式 API (Composition API)
    • setup()函数:
      • ref()函数
      • reactive()函数
      • 组合式 setup 中使用 Props 父向子传递参数
      • 计算属性
      • watch(数据监视)
      • watchEffect()函数
      • Vue3 生命周期钩子函数
      • 自定义 Hook 函数()
      • toRef 和 toRefs 钩子函数
      • shallowReactive 和 shallowRef 函数
      • readonly 和 shallowReadonly 函数
      • toRaw 和 markRaw 函数
      • customRef 自定义Ref 函数
      • 依赖注入 ( provide(), inject() )
        • provide() 函数
        • inject() 函数
      • defineAsyncComponent 函数
  • 总结

一、Vue3相比Vue2,更新了什么变化?

  • 新增 响应式数据劫持的Api,在Vue2 中,数据响应式劫持更新采用的是 Object.defineProperty(),但是 Object.defineProperty(),会有一些缺陷,例如监听不到对象属性的新增或者删除,以及数组通过下标索引,直接更改数据后,无法响应式更新。,所以Vue3中,新增了 Proxy 作为响应式数据劫持的Api,响应式数据监听更加高效。
  • 友好的支持了 TypeScript 的语法。
  • 以及新增了组合式API 的编码风格!

二、Proxy 代理响应式原理

        let arr = {
            name: "张三",
            age: 18
        }
        let Responsivedata = new Proxy(arr, {      //通过 Proxy 实例实现代理对象
            get(target, attributeName) {   //   收到两个参数  用来捕获读取代理对象属性时的数据
                // target:代理的源数据
                // attributeName : 操作当条数据的key
                console.log(target, attributeName);
                return Reflect.get(target, attributeName);  //  使用  Reflect 反射对象 把数据 返回出去
            },
            set(target, attributeName, value) {   //捕获修改新增对象属性时,拿到新增修改的值
                // target:代理的源数据
                // attributeName : 操作当条数据的key
                // value :新增 修改的 value 值
                console.log(target, attributeName, value);
                Reflect.set(target, attributeName, value); //   使用  Reflect 反射对象  在这里真正操作修改源数据的变化
            },
            deleteProperty(target, attributeName) {    //捕获 源数据 ,以及删除当前数据的key。
                // target:代理的源数据
                // attributeName : 操作当条数据的key
                console.log(target, attributeName);
                return Reflect.deleteProperty(target, attributeName); //  使用  Reflect 反射对象  在这里真正操作删除源数据。
            }
        });

点击了解 Reflect

三、组合式 API (Composition API)

概念:

组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,也需要你对 Vue 的响应式系统有更深的理解才能高效使用。相应的,它的灵活性也使得组织和重用逻辑的模式变得更加强大。

setup()函数:

setup是vue3新增的生命周期函数,setup的加入就是为了让vue3使用组合式API(Composition API)。使用组合式API更符合大型项目的开发,通过setup可以将该部分抽离成函数,让其他开发者就不用关心该部分逻辑。
————————
setup内部可以定义数据和方法,如果想在模板中使用,必须通过return进行返回。
————————
setup函数内,要使用的Api方法配置项,采用按需映入 如 computed、watch等。

<script>
import { computed, watch} from 'vue';   //按需映入
export default {
  name: 'HelloWorld',
  setup() {
    let name = "张三";   //直接定义数据
    let arr = [{ a: 1 }, { b: 2 }];
    const addnum = () => name = "李四";  //直接定义数据的方法
    return {
      name,
      arr,
      addnum 
    }
  }
}
</script>

注意:如上在setup中定义的数据,页面中虽然能够读取,但是数据发生改变时,不会触发响应式更新。需要借助 ref() 函数 以及 reactive() 函数实现响应式

ref()函数

<script>
import { ref } from 'vue'  //按需映入ref
export default {
  name: 'HelloWorld',
  setup() {
    let name = ref("张三");  //直接定义数据
    const addnum = () => name.value = "李四";  //通过.value 操作数据
    console.log(name);   //见下图
    return {
      name,
      addnum 
    }
  }
}
</script>

请添加图片描述

在setup函数中 ref() 函数 通常用来 包裹 基本数据类型 ,为该数据提供响应式监听,操作该数据时,需要通过点. value 拿取到数据。

reactive()函数

<script>
import { ref, reactive } from 'vue'
export default {
  name: 'HelloWorld',
  setup() {
    let arr = reactive([{ a: 1 }, { b: 2 }]);
    console.log(arr);   //通过 reactive 函数包裹的 数据结构见下图
    const addnum = () => arr[0].a = 456;  //直接更改数据的方法
    return {
      addnum,
      arr
    }
  }
}
</script>

请添加图片描述

reactive 函数 通常用来包裹 引用数据类型,为引用数据类型提供响应式。

ref 函数 和 reactive 函数 总结

  • ref() 函数 用来定义基本数据类型。
  • reactive () 函数 用来定义 引用数据类型。
    -备注: ref函数也能用来定义 引用数据类型( 但reactive () 函数不能用来定义基本数据类型),它内部会自动 调用 reactive 函数 转为代理对象=》 但是不推荐。
  • ref 函数 响应式原理 依然采用的是 Object.defineProperty 的get 和set 方法 通过 数据劫持来完成响应式。
  • reactive() 函数 通过 ES6 的 Proxy 代理对象的数据劫持来实现响应式 (见上节 Proxy 响应式原理。
  • ref 函数定义的数据 操作 数据时 需要通过 .value 模板中读取 则不需要。
  • reactive 函数 定义的数据 操作数据或 模板读取时,均不需要 .value

组合式 setup 中使用 Props 父向子传递参数

setup 可以接收两个参数
第一个参数Props

export default {
  name: 'HelloWorld',
  props:["masg"],  //父组件中,按v2 正常传递参数,子组件这里正常接收
  setup(props,context) {
   //  setup 这里的第一个参数 就是 Props ,不过被setup包裹成了 代理对象数据,具有响应式
    console.log(props,context);
    return {
     props
    }
  }
}

第一个参数
第二个参数 context (上下文对象)

context 主要接收三个参数

  • attrs:值为对象,包含组件外部传递过来的参数,但是并没有在 Props 中声明接收,则会出现在这里,Props 中如果接受了参数,则就不会再出现在 这里 和 V2中 this.$attrs 同理
  • emit:分发自定义事件的函数 同 v2 this.$emit
  • slots:接收到外部组件传入的 插槽内容。

请添加图片描述

计算属性

在Vue3.x 中,计算属性属性不再通过配置项操作,而是通过引用一个计算属性函数。
点击查看Vue2中计算属性

import { ref, reactive, computed } from 'vue'   //引入 computed  计算属性函数,函数回调 return  返回处理后的数据
export default {
  name: 'HelloWorld',
  setup() {
    let name = ref("张三");
    let age = ref(18);

    // let calculation = computed(() => {        //常见写法,读取 计算属性
    //   return `${name.value}++++${age.value}`
    // });

    let calculation = computed({    //完整写法。可读取,也可修改
      get() {
        return `${name.value}++++${age.value}`
      },
      set(value) {
        return `${name.value}++++${age.value}++++${value}`
      }
    });
    return {                  //提示: 别忘了 所定义的 数据 以及函数方法 ,记得 return 出去,页面才能使用。
      name,
      age,
      calculation,
    }
  }
}
</script>

watch(数据监视)

同样在Vue3.x 中,watch 属性不再通过配置项操作,而是通过引用一个 watch 函数。
点击查看Vue2 中watch

import { ref, reactive, watch } from 'vue'   //引入  watch  函数
export default {
  name: 'HelloWorld',
  setup() {
    let age = ref(18);
    let num = ref(22);
    let arr = reactive([{ a: 1, b: 2, c: 3 }, { b: 2 }, { c: 5 }]);
    let obj = reactive({
      age: 14,
      name: "张三",
      job: {
        a: 1,
        b: 2
      }
    })

   //监听ref 基本数据类型!
   //使用场景一:
    watch(num, (a, b) => {    // watch 函数监听 可以接收三个参数, 第一个参数 为 要监听的值 ,第二个参数为 回调函数,且回调函数 也能 接收两个参数,为新值和旧值。 第三个 参数 为一个配置对象  
      console.log("检测到数据被修改");
    },{ immediate: true });  //  immediate 为true时,可以开启 页面初始化 时就执行一次监听
    
//使用场景二:
    watch([age, num, arr], (a, b) => {    // watch 函数也可以一次性监听多个数据,第一个参数设置为一个数组,里面配置 多个需要监听得数据。
      console.log("检测到数据被修改", a, b);
    })
    let ick = () => age.value++;


/*  监听  reactive  引用数据类型!    

注意:watch 函数监听  reactive  数据时,存在两个问题 !
   1.  无法正确获取 旧的值;
   2. 强制开启了深度监视模式(配置 deep:false   无效)
*/

// 场景三 : 监听   reactive  所定义数据的全部属性
    let ickbtn = () => arr[0].a++
    watch(arr, (a, b) => {
      console.log("监听到arr更改了", a, b);
    }, { immediate: true })

//场景四:   监听   reactive  所定义数据的某个属性,watch 函数第一个参数是一个函数 返回值就是需要监听的值
    let ick = () => arr[0].a++
    watch(() => arr[0].a, (a, b) => {
      console.log("监听到arr[0].a 更改了", a, b);
    }, { immediate: true })

//场景五       监听   reactive  所定义数据的某一些属性,watch 函数第一个参数是一个数组 数组中返回多个函数,监听项。
 	 let ick = () => {
     	 arr[0].a++;
      	arr[0].b++;
     }
    watch([() => arr[0].a, () => arr[0].b], (a, b) => {
      console.log("监听到arr[0].a 和 b 更改了", a, b);
    }, { immediate: true })

// 特殊场景
    let ick = () => {
      obj.job.b++
    }
    watch(() => obj.job, (a, b) => {
      console.log("监听到arr[0].a 和 b 更改了", a, b);
    }, { immediate: true, deep: true })   //此处如果 监听的是 reactive   所定义数据中的某个 属性,同时所操作更改的值又 位于所监听的 属性下面,这时候 ,默认是监听不到更改的,所以这里需要手动 配置 deep:true ,开启深度监视


    return {
      age,
      arr,
      ick,
      num,
      ickbtn,
      obj
    }
  }
}
</script>

watchEffect()函数

在这里插入图片描述

在这里插入图片描述

Vue3 生命周期钩子函数

生命周期图例

注明:

在Vue3中,依然可以通过配置项使用Vue2中的 生命周期钩子函数,但是有两个钩子函数名称 被更名:


beforeDestroy =》更名为 beforeUnmount
destroyed =》 更名 为 unmounted

官方推荐在Vue 3中 使用 组合式 API (Composition API) ,所以Vue3 也提供了 一套 组合式 API (Composition API) 形式的生命周期钩子函数,与Vue2中的 函数钩子对应 如下:

Vue2Vue3(setup)描述
beforeCreatesetup() 实例创建前调用
createdsetup() 实例创建后调用
beforeMountonBeforeMountDOM挂载前调用
mountedonMountedDOM挂载成功后调用
beforeUpdateonBeforeUpdate数据更新之前调用
updatedonUpdated数据更新之后调用
beforeUnmountonBeforeUnmount组件卸载之前调用
unmountedonUnmounted组件卸载完成后调用

自定义 Hook 函数()

其本质是一个函数,把 setup 函数中使用的 Composition API 放到一个文件中进行了封装,然后在需要用到的地方,进行引入,类似于 vue2.x 中的 Mixin。总结就是,把多个地方都会用到的 组合式api 方法进行抽离化,封装。

toRef 和 toRefs 钩子函数

使用场景:当结构模板中使用到 reactive 对象类型数据的时候,如果数据结构嵌套过深的时候, 会出现 大量 xxx.xxx.xxx 的赋值现象
————————————————————————————————————————————————————
作用:代理创建一个 Ref 对象,其 Value 值 映射到 一个指定对象中的某个属性
————————————————————————————————————————————————————
语法:let name = toRef(obj, "name"); obj是所要代理的对象,name是obj身上所要具体映射的 key。
————————————————————————————————————————————————————
应用:要将响应式数据中的某个属性,单独提供给外部使用时,并且需要依然保持 响应式
————————————————————————————————————————————————————
扩展:toRefs 和 toRef 功能基本一致,但是可以批量创建 ref对象 语法: toRefs (obj)

shallowReactive 和 shallowRef 函数

shallowReactive处理对象形式的数据时,只进行浅层次监听响应式,只处理最外层数据
————————————————————————————————————————
shallowRef当传入基本数据类型的时候,作用和 ref 一样,如果传入的是对象类型数据时,则不会进行响应式监听处理。
在这里插入图片描述
在这里插入图片描述

readonly 和 shallowReadonly 函数

readonly把一个响应式数据,限制为只读的(深层次的)
shallowReadonly把一个响应式数据,限制为只读的(浅层次的)
在这里插入图片描述
在这里插入图片描述

toRaw 和 markRaw 函数

toRaw将 reactive 生成的响应式对象 转化成普通的原始对象,如果传入的是 ref 数据 ,之前会报出 undefined ,vue最新版修复后 则不会进行转化处理,也不会报 undefined
markRaw标记一个对象,使其被标记后的对象,不会被转换成响应式 数据对象。
在这里插入图片描述
在这里插入图片描述

customRef 自定义Ref 函数

概念:创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。,使其能够使开发者更加灵活地操作响应式数据。

  setup() {
    let myref = (val) => {
      return customRef((track, trigger) => {
        return {
          get() {
            console.log("读取数据");
            track()
            return val
          },
          set(newval) {
            console.log("修改数据");
            val = newval
            trigger()
          }
        }
      })
    }
    let keywordname = myref(500)
    return {
      keywordname
    }
  }

在这里插入图片描述

依赖注入 ( provide(), inject() )

作用:用来实现跨级组件间的数据通讯

provide() 函数

在这里插入图片描述

inject() 函数

在这里插入图片描述

defineAsyncComponent 函数

作用:定义一个异步组件的的导入, 不过需要 搭配 组件使用。
在这里插入图片描述

总结

上手章节到此结束:

本文 为 Vue 2 开发者提供 Vue3 的开发过度上手手册,Vue3 的变化 不止于这些,更多的 新特征,还需要 开发者自己去发现 !下面附上

点击访问Vue3 官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/370979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言数据结构初阶(2)----顺序表

目录 1. 顺序表的概念及结构 2. 动态顺序表的接口实现 2.1 SLInit(SL* ps) 的实现 2.2 SLDestory(SL* ps) 的实现 2.3 SLPrint(SL* ps) 的实现 2.4 SLCheckCapacity(SL* ps) 的实现 2.5 SLPushBack(SL* ps, SLDataType x) 的实现 2.6 SLPopBack(SL* ps) 的实现 2.7 SLP…

“XXX.app 已损坏,打不开。您应该将它移到废纸篓”,Mac应用程序无法打开或文件损坏的处理方法(2)

1. 检查状态 在sip系统完整性关闭前&#xff0c;我们先检查是否启用了SIP系统完整性保护。打开终端输入以下命令【csrutil status】并回车&#xff1a; 你会看到以下信息中的一个&#xff0c;用来指示SIP状态。已关闭 disabled: System Integrity Protection status: disabl…

学习 Python 之 Pygame 开发魂斗罗(四)

学习 Python 之 Pygame 开发魂斗罗&#xff08;四&#xff09;继续编写魂斗罗1. 创建子弹类2. 根据玩家方向和状态设置子弹发射的位置(1). 站立向右发射子弹(2). 站立向左发射子弹(3). 站立朝上发射子弹(4). 蹲下发射子弹(5). 向斜方发射子弹(6). 奔跑时发射子弹(7). 跳跃时发射…

ARM uboot 源码分析8 - uboot的环境变量

一、uboot 的环境变量基础 1、环境变量的作用 (1) 让我们可以不用修改 uboot 的源代码&#xff0c;而是通过修改环境变量&#xff0c;来影响 uboot 运行时的一些数据和特性。譬如说&#xff0c;通过修改 bootdelay 环境变量&#xff0c;就可以更改系统开机自动启动时倒数的秒…

【MindSpore】安装和使用MindSpore 2.0.0版本简单实现数据变换Transforms功能

本篇文章主要是讲讲MindSpore的安装以及根据官方提供的例子实现数据变换功能。 昇思MindSpore是一款开源的AI框架&#xff0c;旨在实现易开发、高效执行、全场景覆盖三大目标。 目录1、加入MindSpore社区2、安装前准备2.1、获取安装命令2.2、安装pip2.3、确认系统环境3、安装Mi…

JavaWeb--Web概述

Web概述1 Web概述1.1 Web和JavaWeb的概念1.2 JavaWeb技术栈1.2.1 B/S架构1.2.2 静态资源1.2.3 动态资源1.2.4 数据库1.2.5 HTTP协议1.2.6 Web服务器1.3 Web核心课程安排今日目标&#xff1a; 了解JavaWeb开发的技术栈 1 Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网&#…

阿里软件测试二面:adb 连接 Android 手机的两种方式,看完你就懂了

前言 随着现在移动端技术的突飞猛进&#xff0c;导致现在市场上&#xff0c;APP 应用数不胜数&#xff0c;那对于测试工程师而言&#xff0c;对于 APP 的测试&#xff0c;那基本就是一个必修课了。 今天&#xff0c;我就来给大家介绍一下&#xff0c;adb 连接 Android 手机的两…

Spring(Bean生命周期)

目录 1. 生命周期简图2. 扩展接口介绍 2.1 Aware接口2.2 BeanPostProcessor接口2.3 InitializingBean2.4 DisposableBean2.5 BeanFactoryPostProcessor接口3. spring的简化配置 3.1 项目搭建3.2 Bean的配置和值注入3.3 AOP的示例 1. 生命周期简图 2. 扩展接口介绍 2.1 Aware接…

Redis实现分页和多条件模糊查询方案

导言 Redis是一个高效的内存数据库&#xff0c;它支持包括String、List、Set、SortedSet和Hash等数据类型的存储&#xff0c;在Redis中通常根据数据的key查询其value值&#xff0c;Redis没有模糊条件查询&#xff0c;在面对一些需要分页、排序以及条件查询的场景时(如评论&…

PolarDB数据库的CSN机制

背景 对postgres数据库熟悉的同学会发现在高并发场景下在获取快照处易出现性能瓶颈&#xff0c;其原因在于PG使用全局数组在共享内存中保存所有事务的状态&#xff0c;在获取快照时需要加锁以保证数据一致性。获取快照时需要持有ProcArraryLock共享锁比遍历ProcArray数组中活跃…

[计算机网络(第八版)]第二章 物理层(学习笔记)

网络层是网络体系结构的最低层&#xff0c;不是具体的传输媒体&#xff0c;也不是连接计算机的具体物理设备 2.1 物理层的概念 物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。物理层的作用&#xff1a; 要尽可能地屏…

面试题:Android 中 Intent 采用了什么设计模式?

答案是采用了原型模式。原型模式的好处在于方便地拷贝某个实例的属性进行使用、又不会对原实例造成影响&#xff0c;其逻辑在于对 Cloneable 接口的实现。 话不多说看下 Intent 的关键源码&#xff1a; // frameworks/base/core/java/android/content/Intent.java public cla…

阅读笔记9——DenseNet

一、DenseNet DenseNet的网络结构如图1-1所示&#xff0c;其核心是Dense Block模块&#xff0c;Dense Block中的一个黑点就代表一个卷积模块&#xff08;不是一个卷积层&#xff0c;而是DenseNet提出的一个BottleNeck模块&#xff0c;后文有讲解&#xff09;&#xff0c;每条黑…

ClassPathResource遇到的坑:class path resource

读取文件--ClassPathResource前言一、使用ClassPathResource.getFile()的坑二、通过流读取文件内容总结前言 需求&#xff1a;拿到一个小程序的皮肤文件夹&#xff0c;放在resource目录下 1:根据皮肤的style.json&#xff0c;获取json内的${xxx.png}变量&#xff08;获的图片名…

「2」指针进阶——详解

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 目录 &#x1f430;指向函数指针数组的指针(很少用&#xff0c;了解) &#x1f430;回调函数&…

【Arduino 无刷电机控制教程】

【Arduino 无刷电机控制教程】 1. 概述2. 试验准备3. 实验原理4. Arduino 无刷电机控制 – 电路图4.1 实验组件4.2 用于 BLDC 电机控制的 Arduino 代码5. 实验验证5.1 电位计控制无刷电机速度5.2 电调校准在本教程中,我们将学习如何使用 Arduino 和 ESC 控制无刷电机。如果您想…

建议将com.alibaba:fastjson升级至1.2.83

问题 升级了gradle&#xff0c;改了文件存储位置&#xff0c;项目需要重新构建下载依赖文件&#xff0c;发现fastjson 1.2.66一直下载不下来一直卡在下载&#xff0c;就想着手动下载下试试&#xff0c;就去了mvnrepository网站找到fastjson时&#xff0c;发现了fastjson2 Note…

一文让你彻底了解Linux内核文件系统

一&#xff0c;文件系统特点 文件系统要有严格的组织形式&#xff0c;使得文件能够以块为单位进行存储。文件系统中也要有索引区&#xff0c;用来方便查找一个文件分成的多个块都存放在了什么位置。如果文件系统中有的文件是热点文件&#xff0c;近期经常被读取和写入&#xf…

数学不好,英语不行,非本专业,可以学IT吗?

很多小伙伴&#xff0c;都会问小青一些比较类似的问题。比如&#xff1a;不是计算机专业的&#xff0c;可以学编程吗&#xff1f;数学一直就不好&#xff0c;可以转行学IT吗&#xff1f;学编程开发&#xff0c;对英语的的要求会不会很高&#xff1f;01计算机不是计算机专业的&a…

C/C++开发,无可避免的内存管理(篇三)-规划好内存

一、用内存空间换效率 1.1 allocatoe类模板 在前面简述模板顺序容器时&#xff0c;就提到过&#xff0c;标准库中的 vector 类是通过预先分配额外内存以换取不不用每次添加元素都要重新分配内存和移动元素&#xff0c;而是将元素直接保存加入的预先分配的内存区域。在预先分配…