Aiden's blog Aiden's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • JavaScript教程
    • JavaScript高级程序设计
    • ES6 教程
    • Vue
    • Vue3.0
    • React
    • TypeScript 从零实现 axios
    • Git
    • TypeScript
    • JS设计模式总结
    • 小程序
    • 小程序云开发
    • Echarts
    • 微前端
    • H5
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 搜索引擎
  • ES系列
  • 经典面试题
  • 知识点总结
  • uni-app
  • 算法
  • Vue3实战
  • 小程序chatgpt
  • 小程序配网流程
  • 程序WIFI配网
  • 小程序WebSocket
  • H5 WebSocket
  • H5 TTS
  • Vue3实现OSS存储
  • 大文件分片上传
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Aiden Wu

前端界的小学生
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • JavaScript教程
    • JavaScript高级程序设计
    • ES6 教程
    • Vue
    • Vue3.0
    • React
    • TypeScript 从零实现 axios
    • Git
    • TypeScript
    • JS设计模式总结
    • 小程序
    • 小程序云开发
    • Echarts
    • 微前端
    • H5
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 搜索引擎
  • ES系列
  • 经典面试题
  • 知识点总结
  • uni-app
  • 算法
  • Vue3实战
  • 小程序chatgpt
  • 小程序配网流程
  • 程序WIFI配网
  • 小程序WebSocket
  • H5 WebSocket
  • H5 TTS
  • Vue3实现OSS存储
  • 大文件分片上传
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript文章

  • Vue文章

  • 学习笔记

    • JavaScript教程
    • JavaScript高级程序设计
    • ES6 教程
    • Vue
    • React
    • TypeScript 从零实现 axios
    • Git
    • TypeScript笔记
    • 小程序笔记
    • 小程序云开发
    • Vue3
      • Vue3.0是如何变快的
        • diff方法优化
        • hoistStatic静态提升
        • cacheHandlers事件侦听器缓存
      • 创建Vue3项目
        • 什么是Vite
        • 安装Vite
        • 利用Vite创建Vue3项目
        • 安装依赖运行项目
      • setup
        • setup本质
        • setup执行时机
      • reactive
      • ref
      • ref和reactive的区别
      • 递归监听
      • 非递归监听
      • toRaw
      • markRaw
      • toRef
      • toRefs
      • customRef
      • 通过Ref获取界面是上的元素
      • readonly
      • const和readonly的区别
      • 手写Proxy
      • shallowReactive
      • shallowRef
      • 计算属性
      • watch
      • watchEffect
      • 生命周期
      • provide/inject
      • 响应式数据的判断
      • Fragment
      • Teleport
      • Suspense
      • Vue.prototype迁移
    • JS设计模式总结笔记
    • Echarts
    • 微前端
    • H5
  • 前端
  • 学习笔记
wushengxin
2021-09-02
目录

Vue3.0

# Vue3.0

# Vue3.0是如何变快的

# diff方法优化

  • Vue2中的虚拟dom是进行全量的对比
  • Vue3新增了静态标记(PatchFlag)
    • 在创建虚拟DOM的时候,会根据DOM中的内容会不会发生变化,添加静态标记

# hoistStatic静态提升

  • Vue2中无论元素是否参与更新,每次都会重新创建,然后再渲染
  • Vue3中对于不参与更新的元素,会做静态提升,只被创建一次,在渲染时直接复用即可

# cacheHandlers事件侦听器缓存

  • 默认情况下onClick会被视为动态绑定,每次都会去追踪它的变化
  • 但是因为同一个函数,所以没有追踪变化,直接缓存起来复用即可

# 创建Vue3项目

# 什么是Vite

  • Vite是Vue作者开发的一款意图取代webpack的工具
  • 其实现原理是利用ES6的import会发送请求去加载文件的特性,拦截这些请求,做一些编译,省去webpack冗余的打包时间

# 安装Vite

  • npm i -g create-vite-app

# 利用Vite创建Vue3项目

  • create-vite-app projectName

# 安装依赖运行项目

  • cd projectName
  • npm install
  • npm run dev

# setup

setup函数是组合API(Composition API)的入口函数,setup只能是同步的函数

  • 两个参数

    • props :接受父组件传递过来的值
    • context
      • context.emit :向父组件传递数据,并类似于接受数据props一样要声明方法,如emits:['hello']
      • context.attrs :与vue2一样拿props不要的数据
      • context.slots :插槽语法 (vue2使用v-slot="名字",vue3使用v-slot:名字)
  • 要想让变量为动态的则需要导入ref

  • 在组合API中定义的变量/方法,要想在外界使用,必须通过return {xxx,xxx}暴露出去

import {ref} from 'vue'
setup(){
  let count = ref(0)
}
return {count}
1
2
3
4
5

注意:ref函数只能监听简单类型的变化,不能监听复杂类型的变化

  • reactive函数监听复杂类型的变化(对象/数组)
import {reactive} from 'vue'
setup(){
let state = reactive({
    stus:[]
  })
  return {state}
}
1
2
3
4
5
6
7

# setup本质

  • Composition API注入到Option API中(data,methods)

# setup执行时机

顺序:执行在beforeCreate之前

  • beforeCreate:表示组件刚刚被创建出来,组件的data和methods还没有初始化好
  • setup:不能够使用data和methods的,只能是同步的,不能是异步的
  • Created:表示组件刚刚被创建出来,并且组件的data和methods已经初始化好

# reactive

本质:就是将传入的数据包装成一个Proxy对象

  • reactive是Vue3中提供的实现响应式数据的方法
  • 在Vue2中响应式数据是通过defineProperty来实现的
  • 在Vue3中响应式数据是通过ES6的Proxy来实现的

注意:

  • reactive参数必须是对象(json/arr)
  • 如果reactive传递了其它对象(内置对象)
    • 默认情况下修改对象,界面不会自动更新
    • 如果想更新,可以通过重新赋值的方式

image-20210430175730202

# ref

本质:ref底层其实还是reactive

  • ref和reactive一样,也是实现响应式数据的方法
  • 系统会根据我们给ref传入的值将它转换成ref(xxx) -> reactive({value:xxx})

注意:

  • 在Vue中使用ref的值不用通过value获取,需要通过变量.value来更改值
  • 在JS中使用ref的值必须通过value获取
  • 如果是通过ref创建的数据,那么在template中使用的时候不用通过.value来获取,因为Vue会自动给我们添加.value

# ref和reactive的区别

  • 如果在template里使用的是ref类型,那么Vue会自动帮我们添加.value
  • 如果在template里使用的是reactive类型,那么Vue不会自动帮我们添加.value

Vue是如何决定是否需要添加.value的

  • Vue在解析数据之前,会自动判断这个数据是否是ref类型的
  • 如果是就自动添加.value,如果不是就不自动添加.value

Vue是如何判断当前的数据是否是ref类型的

  • 通过当前数据的__v_ref来判断的
  • 如果有这个私有的属性,并且取值为true,那么就代表是一个ref类型的数据
  • 可以通过isRef,isReactive来判断,import {isRef,isReactive} from 'vue'

# 递归监听

默认情况下,无论是通过ref还是reactive都是递归监听

注意:如果数据量较大,非常消耗性能

# 非递归监听

通过shallowRef和sallowReactive只能监听第一层数据

  • 只监听第一层(对象)数据,只有第一层更改为了Proxy对象
  • 只要第一层的数据改变,后面的也会改变
  • 如果是通过shallowRef创建的数据,那么Vue监听的是.value的变化,并不是第一层的变化
  • triggerRef能够主动更新数据,Vue3没有triggerReactive

注意:只有在需要监听的数据量比较大的时候,我们才使用shallowRef/shallowReactive

# toRaw

将响应式数据改为原始数据,只能处理reactive的响应式数据

  • 从Reactive或Ref中得到原始数据
  • 做一些不想被监听的事情(提高性能)
    • 获取reactive的原始数据let obj2 = toRaw(state)
    • 获取ref的原始数据let obj2 = toRaw(state.value)

image-20210501001732601

# markRaw

不想有响应式数据,不想被追踪

image-20210506155211584

# toRef

  • 如果利用ref将某一个对象中的属性变成响应式的数据,我们修改响应式的数据是不会影响到原始数据的
  • 如果利用toRef将某个对象中的属性变成响应式的数据,我们修改响应式的数据是会影响到原始数据的,但是如果响应式的数据是通过toRef创建的,那么修改了数据并不会触发UI界面的更新

使用:如果想让响应式数据和以前的数据关联起来,并且更新响应式数据之后还不想更新UI,那么就可以用toRef

image-20210506233446764

# toRefs

多个变量变成响应式数据

image-20210506234020044

# customRef

  • 返回一个ref对象,可以显示地控制依赖追踪和触发响应
  • 自定义Ref

image-20210507101322937

# 通过Ref获取界面是上的元素

  • 因为setup是在beforeCreate和Created之间执行的,所以获取不到元素,要用到生命周期函数onMounted获取

image-20210507102950613

image-20210507103130314

# readonly

  • readonly用于创建只读的数据,并且是递归只读(每一层都是只读的)

  • shallowReadonly用于创建第一层只读的数据

  • isReadonly用于判断是否为readonly

# const和readonly的区别

  • const:赋值保护,不能给变量重新赋值
  • readonly:属性保护,不能给属性重新赋值
const value = {name:'zs',age:123}
value.name = 'ls'
value.age = 666 //value的属性值都会改变
1
2
3

# 手写Proxy

传递对象

image-20210507104605585

传递数组

let arr = [1,3,5]

注意:修改完数组后必须要return true,因为数组长度会改变,否则会报错

image-20210507105240073

# shallowReactive

只处理对象最外层属性的响应式(浅响应式)

image-20210507105812679

# shallowRef

只处理基本数据类型的响应式,不进行对象的响应式处理

# 计算属性

import {computed} from 'vue'

setup(){
  //计算属性简写
  let fullName = computed(() => {
    return person.firstName + '-' + person.lastName
  })
  //计算属性完整写法
  let fullName = computed({
    get(){
      return person.firstName + '-' + person.lastName
    }
    set(value){
      const nameArr = value.spilt('-')
      person.firstName = nameArr[0]
      person.lastName = nameArr[1]
    }
  })
  return {person}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# watch

  • ref定义的数据可以获取newValue、oldValue
  • reactive定义的数据只能获取newValue,无法获取oldValue
  • reactive强制开启了深度监视=>deep:true(多层嵌套,即多个对象,深度监视),配置了deep也无效
import {ref,watch} from 'vue'

setup(){
  let sum = ref(0)
  let msg = ref('你好啊')
  
  //情况一:监听ref所定义的一个响应式数据(页面刚进去immediate参数为直接监听)
  watch(sum,(newValue,oldValue) => {
    console.log('sum变了',newValue,oldValue)
  },{immediate:true,deep:true})
  //情况二:监听ref所定义的多个响应式数据
  watch([sum,msg],(newValue,oldValue) => {
    console.log('sum或msg变了',newValue,oldValue)
  },{immediate:true})
  //情况三:监视reactive所定义的一个响应式数据的全部属性
  watch(person,(newValue,oldValue) => {
    console.log('person变了',newValue,oldValue)
  },{deep:true}) //此处的deep配置无效
  //情况四:监视reactive所定义的一个响应式数据的某个属性
  watch(()=>person.age,(newValue,oldValue) => {
    console.log('age变了',newValue,oldValue)
  })
  //情况五:监视reactive所定义的一个响应式数据的某些属性
  watch([()=>person.name,()=>person.age],(newValue,oldValue) => {
    console.log('person的name和age变了',newValue,oldValue)
  })
  //特殊情况,job是一个对象
  watch(()=>person.job,(newValue,oldValue) => {
    console.log('person的job变了',newValue,oldValue)
  },{deep:true}) //此处必须加deep深度监视
  return {sum,msg}
}
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
31
32

# watchEffect

  • 不用指明监视哪个属性,监视回调用到哪个属性,那就监视哪个属性
  • watchEffect有点像computed:
    • computed注重计算出来的值,所以必须要写返回值
    • watchEffect更注重的是过程,所以不用写返回值
import {watchEffect} from 'vue'
setup(){
      watchEffect(() => {
      const x1 = sum.value  //监视了
      const x2 = person.job.j1.salary   //监视了
      console.log('watchEffect所指定的回调执行了')
  }) 
}
1
2
3
4
5
6
7
8

# 生命周期

setup(){
  //组合式API的形式去使用生命周期钩子
  onBeforeMount(()=>{})
  onMounted(()=>{})
  onBeforeUpdate(()=>{})
  onUpdate(()=>{})
  onBeforeUnmount(()=>{})
  onUnmounted(()=>{})
}
//通过配置项形式使用生命周期钩子
  beforeCreate(){},
  created(){},
  beforeMount(){},
  mounted(){},
  beforeUpdate(){},
  updated(){},
  beforeUnmount(){},
  Unmounted(){}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# provide/inject

祖与后代组件间的通信

1、祖组件中

setup(){
  let car = reactive({name:'奔驰',price:'40万'})
  provide('car',car)
}
1
2
3
4

2、后代组件中

setup(){
  const car = inject('car')
  return {car}
}
//调用
car.name
car.price
1
2
3
4
5
6
7

# 响应式数据的判断

  • isRef
  • isReactive
  • isReadonly
  • isProxy:检查一个对象是否是由reactive或者rendonly方法创建的代理

# Fragment

  • 在Vue3中,组件可以没用根标签,内部会将多个标签包在一个Fragmenet虚拟元素中
  • 好处:减小标签层级,减小内存占用

# Teleport

将teleport里面的内容移动到body下

<teleport to="body">
  //内容
</teleport>
1
2
3

# Suspense

  • 等待异步组件时渲染一些额外内容,让应用有更好的用户体验

  • 使用步骤

    • 异步引入组件
    import {defineAsyncComponent} from 'vue'
    const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
    
    1
    2
    • Suspense引用
    <Suspense>
      <template v-slot:default>
        <Child/>
      </template>
      <template v-slot:fallback>
        <h3>加载中</h3>
      </template>
    </Suspense>
    
    1
    2
    3
    4
    5
    6
    7
    8

# Vue.prototype迁移

Vue.prototype=>app.config.globalProperties

编辑 (opens new window)
上次更新: 2021/09/23, 22:40:40
小程序云开发
JS设计模式总结笔记

← 小程序云开发 JS设计模式总结笔记→

最近更新
01
大文件分片上传
08-05
02
Vue3实现OSS存储
08-05
03
H5 TTS
08-05
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Aiden Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×