您现在的位置是:首页 >技术杂谈 >Vue笔记第七章vue3【动力节点】网站首页技术杂谈

Vue笔记第七章vue3【动力节点】

逗逗逗逗666 2023-05-31 16:00:03
简介Vue笔记第七章vue3【动力节点】

7 Vue3

7.1 了解Vue3

  1. vue3官网地址
    1. https://cn.vuejs.org/
  2. vue3发布时间
    1. 2020年9月18日。


翻译:
今天,我们很自豪地宣布Vue.js 3.0“海贼王”正式发布。这个新的主要版本的框架提供了改进的性能斜体样式、更小的捆绑包大小、更好的TypeScript集成、用于处理大规模用例的新API,以及为框架未来的长期迭代奠定了坚实的基础。
3.0版本代表了两年多的开发工作,包括30多个RFC、2600多个提交、来自99个贡献者的628个拉取请求,以及核心回购之外的大量开发和文档工作。我们要向我们的团队成员表示最深切的感谢,感谢他们接受了这一挑战,感谢我们提出的撤回请求,斜体样式感谢我们的赞助商和支持者提供的财政支持,感谢广大社区参与我们的设计讨论并为预发布版本提供反馈。Vue是一个为社区创建并由社区支持的独立项目,如果没有您的持续支持,Vue 3.0是不可能实现的。

  1. 版本迭代历史
    1. https://github.com/vuejs/core/releases
  2. vue3做了哪些改动
    1. 最核心的虚拟DOM算法进行了重写。
    2. 支持tree shaking:在前端的性能优化中,es6 推出了tree shaking机制,tree shaking就是当我们在项目中引入其他模块时,他会自动将我们用不到的代码,或者永远不会执行的代码摇掉
    3. 最核心的响应式由Object.defineProperty修改为Proxy实现。
    4. 更好的支持TS(Type Script:TypeScript是微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成。TypeScript通过TypeScript编译器或Babel转译为JavaScript代码,可运行在任何浏览器,任何操作系统。)
  3. vue3比vue2好在哪
    1. 翻译:
      1. 与Vue 2相比,Vue 3在捆绑包大小(通过树抖动可轻41%)、初始渲染(快55%)、更新(快133%)和内存使用(少54%)方面都有了显著的性能改进。
  4. Vue3的新特性
    1. 新的生命周期钩子
    2. 键盘事件不再支持keyCode。例如:v-on:keyup.enter支持,v-on:keyup.13不支持。
    3. 组合式API(Composition API)
    4. 新增了一些内置组件
    5. data必须是一个函数。

7.2 Vue3工程的创建

7.2.1 vue-cli创建Vue3工程

  1. 创建Vue3版本的工程,要求vue-cli最低版本4.5.0
    1. 可以使用以下命令升级你的脚手架版本
      1. npm install -g @vue-cli
  2. 创建Vue3工程
    1. vue create vue3_pro
  3. 启动工程
    1. 切换到工程根目录。
    2. npm run serve

7.2.2 vue-cli创建的vue3项目说明

  1. 目录结构以及文件和vue2相同。

  1. main.js文件说明

  1. 查看App.vue组件


vue3中template标签下可以有多个根标签了。

7.2.3 create-vue创建Vue3工程

  1. create-vue是什么?
    1. 和vue-cli一样,也是一个脚手架。
    2. vue-cli创建的是webpack+vue项目的脚手架工具。
    3. create-vue创建的是vite+vue项目的脚手架工具。
    4. webpack和vite都是前端的构建工具。
  2. vite官网
    1. https://vitejs.cn/
  3. vite是什么?(vite被翻译为:快)
    1. vite是一个构建工具,作者尤雨溪。

  1. 前端构建工具有哪些?

  1. vite和传统构建工具的区别?
    1. https://cn.vitejs.dev/guide/why.html 官方的说辞。

  1. 使用vite后,至少两方面是提升了:
    1. 服务器启动速度快。
    2. 更新速度快了。
  2. 使用create vue创建Vue3工程
    1. 官方指导:https://cn.vuejs.org/guide/quick-start.html
    2. 安装 create-vue脚手架并创建vue3项目:npm init vue@latest

执行时,如果检测到没有安装create-vue脚手架时会安装脚手架。如果检测到已经安装过脚手架,则直接创建项目。


一路选择No:

  1. cd vue3_pro
  2. npm install
  3. npm run dev

  1. 访问5173端口

7.2.4 create-vue创建的vue3工程说明

  1. 目录结构

  1. 和vue-cli脚手架创建的区别
    1. index.html文件不再放到public目录下了。
      1. vite官方的解释是:让index.html成为入口。(vue-cli脚手架生成的项目入口是:main.js)

  1. vue-cli的配置文件vue.config.js。create-vue脚手架的配置文件:vite.config.js
    1. vite.config.js 能配置什么?可以参考vite官网:https://cn.vitejs.dev/config/ 例如配置代理服务器和以前就不太一样了。

7.3 Proxy实现原理

Vue2的响应式核心:Object.defineProperty
Vue3的响应式核心:Proxy

7.3.1 Object.defineProperty

get做数据代理。set做数据劫持。在set方法中修改数据,并且渲染页面,完成响应式。
Object.defineProperty(data, ‘name’, {
get(){
// 数据代理
},
set(val){
// 数据劫持
}
})
存在的问题:

  1. 通过数组下标修改数据,这个操作是没有响应式的。
  2. 后期给对象新增属性、删除属性,这些操作都是没有响应式的。

导致以上问题最根本原因是:Object.defineProperty只能捕获到读和修改。
Vue2中怎么解决以上问题?

  1. 对于数组来说调用数组的相关API。例如:push、shift、unshift…
  2. 新增属性、删除属性等操作通过:Vue.set或者this.$set

7.3.2 Proxy

Proxy是ES6新增特性。window.Proxy
Proxy是一个构造函数,参数传递一个目标对象,可以为目标对象生成代理对象。
通过访问代理对象上的属性来间接访问目标对象上的属性。
访问代理对象上的属性时,读属性、修改属性、删除属性、新增属性。Proxy都可以捕获到。

Vue3框架底层实际上使用了ES6的Reflect对象来完成对象属性的访问:

7.4 setup

  1. setup是一个函数,vue3中新增的配置项。
  2. 组件中所用到的data、methods、computed、watch、生命周期钩子…等,都要配置到setup中。
  3. setup函数的返回值:
    1. 返回一个对象,该对象的属性、方法等均可以在模板语法中使用,例如插值语法。
    2. 返回一个渲染函数,从而执行渲染函数,渲染页面。
      1. import {h} from ‘vue’ (引入渲染函数)
      2. return ()=>{h(‘h2’, ‘欢迎大家学习Vue3’)}
  4. vue3中可以编写vue2语法,向下兼容的。但是不建议。更不建议混用。

  1. setup中的this是undefined。所以setup中this是不可用的。

7.5 ref函数(实现响应式)

7.5.1 简单数据的响应式

  1. ref是一个函数。完成响应式的。
  2. ref使用时需要import
    1. import {ref} from ‘vue’
  3. 凡是要实现响应式的data,需要使用ref函数进行包裹
    1. let name = ref(‘李四’)
    2. 输出name,你会发现,它是RefImpl对象(引用实现的实例对象,简称引用对象),在这个引用对象当中有一个value属性,value属性的实现原理是:Object.defineProperty,通过它实现了响应式处理。
  4. 修改数据的话必须这样做:name.value = ‘王五’


7.5.2 对象数据的响应式


重点:如果ref函数中是一个对象,例如:ref({}),底层会为这个对象{}生成一个Proxy代理对象。通过这个代理对象完成了响应式。
如果代码是这样写,如下,实际上没有用到Proxy,还是使用了Object.defineProperty完成的响应式:

如果代码是这样写,如下,就是使用了Proxy完成的响应式:

7.6 Vue3中专门为对象做响应式的核心函数:reactive

以上代码中的Proxy是怎么创建的?底层是通过调用reactive函数来完成的。
当然这个函数我们也可以自己使用。
注意:这个函数不能为简单类型服务,只能为对象类型服务。

注意:reactive为响应式做了递归处理。对象中的对象中的对象的属性,也是响应式的。
重点1:
并且数组如果使用reactive函数包裹的话,数组中的数据,在通过下标去修改的时候,也是支持响应式的。(这个在Vue2中是不支持的。)
重点2:
在开发中一般很少使用ref,一般会使用reactive。即使是简单类型的数据,也会将其存放到一个对象中,使用reactive函数进行包括。

7.7 Vue3中的props

给组件User传数据

User组件使用props接收数据

在setup函数中如何使用props?
setup的第一个参数就是props。可以直接拿来用。

7.8 Vue3的生命周期

vue2的生命周期图:

vue3的生命周期图:

  1. vue2中
    1. beforeDestroy
    2. destroyed
  2. vue3中
    1. beforeUnmount
    2. unmounted
  3. vue3中仍然可以使用配置项方式提供生命周期钩子函数。但也可以使用组合式API方式。如果采用组合式API方式,API名称规律如下:
    1. beforeCreate => setup
    2. created => setup
    3. beforeMount => onBeforeMount
    4. mounted => onMounted
    5. beforeUpdate => onBeforeUpdate
    6. updated => onUpdated
    7. beforeUnmount => onBeforeUnmount
    8. unmounted => onUnmounted
  4. 当然如果需要使用beforeCreate和created钩子,可以采用vue2的语法:配置项形式。vue2和vue3语法可以共存,但不建议。

7.9 Vue3中的自定义事件

绑定事件

触发事件

7.10 Vue3的全局事件总线

  1. 安装mitt
    1. npm i mitt
  2. 封装event-bus.js文件
  3. 绑定事件

  1. 触发事件

  1. 移除所有事件和指定事件

7.11 vue3的计算属性

import {computed} from ‘vue’ //computed是一个组合式的API
setup(){
// 简写
let reversedName = computed(()=>{

})

// 完整写法
let reversedName = computed({
get(){},
set(value){}
})
}

计算属性最重要的特征是:只要计算属性关联的数据发生变化,计算属性的回调函数就会执行。所以计算属性关联的数据必须是具有响应式的。

7.12 自定义hook函数

将组合式API拿出来,封装成一个函数,在需要复用的位置,使用这个hook函数。
一般创建一个hooks目录,在hooks目录当中放hook函数。
代码复用。

在需要使用的位置导入:

7.13 vue3的监视属性

import {watch} from ‘vue’ //watch就是组合式API

  1. 监视ref定义的一个响应式数据
    1. watch(数据, (newValue, oldValue)=>{})
  2. 监视ref定义的多个响应式数据
    1. watch(数据1, (newValue, oldValue)=>{})
    2. watch(数据2, (newValue, oldValue)=>{})

或者

  1. watch([数据1,数据2], (newValue, oldValue)=>{})
  2. immediate在哪里写?
  3. 在watch的第三个参数位置上使用一个对象:{immediate : true, deep:true}
  4. 监视reactive定义的响应式数据。注意:oldValue拿不到
    1. watch(数据, (newValue, oldValue)=>{})
  5. 如果监视的reactive定义的响应式数据。强制开启了深度监视,配置deep无效。默认就是监视对象的全部属性。
  6. 如果要监视对象中的某个属性怎么办?被监视的数据必须是一个函数,将要监视的数据返回
    1. watch(()=>user.age, (newValue,oldValue)=>{})
  7. 如果要监视对象中的某些属性怎么办?
    1. watch([()=>user.age, ()=>user.name], (newValue,oldValue)=>{})
  8. 如果要监视reactive定义的响应式数据中的某个属性,这个属性是一个对象形式,那么开启deep:true是可以的。
    1. watch(()=>user.address, (newVal, oldVal)=>{})
  9. 关于ref包裹对象时的value
    1. watch(name.value, (newVal, oldVal){}) //监视无效
    2. watch(user.value, (newVal, oldVal)=>{})//监视有效
    3. watch(user,(newVal, oldVal)=>{}, {deep:true}) // 深度监视生效

7.14 watchEffect函数

  1. watchEffect函数里面直接写一个回调
    1. 回调中用到哪个属性,当这个属性发生变化的时候,这个回调就会重新执行。
    2. watchEffect(()=>{const a = data.counter1; const b = data.counter2 逻辑代码…}) 当counter1和counter2被修改后,这个回调就会执行。
  2. computed和watchEffect的区别?
    1. computed注重返回结果。
    2. watchEffect注重逻辑处理。
  3. 示例代码

7.15 shallowReactive和shallowRef

浅层次的响应式。
shallowReactive:对象的第一层支持响应式,第二层就不再支持了。
shallowRef:只给基本数据类型添加响应式。如果是对象,则不会支持响应式。

以下是演示shallowRef


以下是演示shallowReactive

7.16 组合式API和选项式API对比

组合式API:Composition API
选项式API:Options API

选项式API:特点是 分散。

组合式API:特点是 集中 (一个hook是一个独立的功能,一个hook中有自己的data、methods、computed、watch)


7.17 深只读与浅只读

组合式API:readonly与shallowReadonly
应用场景:其它组件传递过来的数据,如果不希望你修改,你最好加上只读,以防以后不小心改了人家的数据。
深只读:


浅只读:

7.18 响应式数据的判断

isRef:检查某个值是否为 ref。
isReactive:检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。
isProxy:检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。
isReadonly:检查传入的值是否为只读对象。

7.19 toRef和toRefs


通过以上写法,可以看到模板语法中都有“data.”,这个是可以改善的。
大家可以看一下,下面的这个改善是否可以?

我们发现这样修改是不行的。丢失了响应式。什么原因?主要原因是因为以上的这种写法等同于:

显然这种写法和响应式对象data无关了。
再修改为以下这样行不行?


我们发现功能实现了。但是存在的问题是:data不会变。例如:

怎么解决这个问题:toRef,它可以让数据具有响应式,并且修改toRef生成的对象时,还能关联更新data:

测试结果:

还有一个更简单的:toRefs

运行结果:

7.20 转换为原始&标记为原始

toRaw与markRaw
toRaw:将响应式对象转换为普通对象。只适用于reactive生成的响应式对象。
markRaw:标记某个对象,让这个对象永远都不具备响应式。比如在集成一些第三方库的时候,比如有一个巨大的只读列表,不让其具备响应式是一种性能优化。

toRaw:

markRaw:

7.21 Fragment组件

fragment翻译为:碎片。片段。
在Vue2中每个组件必须有一个根标签。这样性能方面稍微有点问题,如果每一个组件必须有根标签,组件嵌套组件的时候,有很多无用的根标签。
在Vue3中每个组件不需要有根标签。实际上内部实现的时候,最终将所有组件嵌套好之后,最外层会添加一个Fragment,用这个fragment当做根标签。这是一种性能优化策略。

7.22 Teleport组件

teleport翻译为:远距离传送。用于设置组件的显示位置。




风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。