当前位置:   article > 正文

最全的 Vue3 快速上手指南【值得收藏】

vue3

Vue3简介

面临的问题:随着功能的增长,复杂组件的代码变得难以维护,Vue3 就随之而来,TypeScript 使用的越来越多,Vue3就是 TS 写的所以能够更好的支持 TypeScript

在这里介绍就这么简单

vue2 的绝大多数的特性 在 Vue3 都能使用,毕竟 Vue 是渐进式的

响应式原理进行使用 Proxy 实现,v-model 可以传参了等等新特性

基础工作

使用Vue3的话,那么必须通过使用构建工具创建一个 Vue3 项目

安装 vue-cli

  1. # npm
  2. npm install -g @vue/cli
  3. # yarn
  4. yarn global add @vue/cli

创建一个项目

使用 create 命令行创建 或者 用 ui 可视化创建

大家用 Vue 都用了这么久,我就不一一说怎么去创建了

  1. # create
  2. vue create 项目名
  3. # 可视化
  4. vue ui

当然也可以选择 vite ,vite 创建的速度比 上面的方法快了一些

  1. npm init vite-app 项目名
  2. cd 项目名
  3. npm install
  4. npm run dev

Vue3入门

Composition API

Vue3 提出了 Composition API

在 Vue2.X 我们使用的是 OptionAPI 里面有我们熟悉的 datacomputedmethodswatch...

在 Vue3 中,我们依旧可以使用 OptionAPI当然不建议 和 Vue3 混用

在 Vue2 中,我们实现一个功能得分到不同的地方,把数据放在 data ,computed 方法放在 methods 里面,分开的太散乱了,几个功能还好,几十个上百个,那就有点...

所以 Vue3 提出了 Composition API ,它可以把 一个逻辑的代码都收集在一起 单独写个hook,然后再引入,这样就不到处分布,显得很乱了

Fragment

在 template 中不再需要一个根元素包裹

  1. <template>
  2.   <img alt="Vue logo" src="./assets/logo.png" />
  3.   <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
  4. </template>

实际上内部会将多个标签包含在一个Fragment虚拟元素中

好处: 减少标签层级, 减小内存占用

script 差异

来看看 script 和 Vue2 的区别

  1. <script lang="ts">
  2. import { defineComponent} from 'vue'
  3. export default defineComponent({
  4.   name: 'App',
  5.   setup() {
  6.     return {
  7.         // 这里的属性 和 方法 会合并到 data 函数 和 methods 对象里
  8.     }
  9.   },
  10. })
  11. </script>
  • 可以再 script 使用 ts 只需 设置 lang 即可

  • defineComponent 方法创建一个组件

  • export default 直接导出一个组件

setup

setup 是 Composition API的入口

setup 执行顺序

它在beforeCreate之前执行一次beforeCreate这个钩子 的任务就是初始化,在它之前执行,那么 this 就没有被初始化 this = undefined 这样就不能通过 this 来调用方法 和 获取属性

setup 返回值

setup 返回的是一个对象,这个对象的属性会与组件中 data 函数返回的对象进行合并,返回的方法和 methods 合并,合并之后直接可以在模板中使用,如果有重名的情况,会使用 setup 返回的属性方法methods 和 data 能够拿到 setup 中的方法应该进行了合并,反之 setup 不能拿到它们的属性和方法,因为这个时候 this = undefined

Suspense 组件

setup 使用 async/await

我们需要 setup 返回数据那么它肯定就不能使用 async 修饰,这样返回 promise 是我们不想看见情况,如果我们硬要用 async 修饰,我们就得用的在它的父组件外层需要嵌套一个suspense(不确定)内置组件,里面放置一些不确定的操作,比如我们就可以把异步组件放入进去

1.子组件

  1. <template> 
  2.   {{ res }}
  3. </template>
  4. <script lang="ts">
  5. import { defineComponent } from 'vue'
  6. export default defineComponent({ 
  7.   name'Son'
  8.   async setup() {   
  9.     const res = await axios.get('地址')   
  10.     return {    
  11.       res, 
  12.     } 
  13.   },
  14. })
  15. </script>

2.父组件

  1. <template>  
  2.     <Suspense>     
  3.         <!-- 子组件-->  
  4.       <Son></Son> 
  5.   </Suspense>
  6. </template>

setup 参数

setup(propscontext)

setup 函数中的第一个参数是 props。它接收父组件传递的值,是的就是父子组件信息传递的 props

第二个参数是 context 里面包含3个属性 { attrs, slots, emit },这三个属性大家看名字就应该知道是什么吧 分别对应 this.$attrsthis.$slotsthis.$emit

  • attrs: 除了 props 中的其他属性

  • slots: 父组件传入插槽内容的对象

  • emit: 和用于父子组件通信

ref

定义/转为 响应式

在上面 setup 写的数据都不是响应式的,修改了数据,视图并不会更新

在 Vue3 中提供了两种方式定义响应式数据,先来介绍下 ref

导入 ref 方法

import { defineComponent, ref } from 'vue'
  • 你可以先声明一个基本类型变量后再当做 ref 的形参穿进去

  • 或者直接在 ref 中传入

  1.   setup() {   
  2.     // 方式一  
  3.     let number1 = ref(10
  4.     let num = 0   
  5.     // 方式二  
  6.     let number2 = ref(num)  
  7.     return {} 
  8.   },

来查看一下 number1 是什么吧

可以看见的是 number1 是一个 Ref 对象,我们设置的 10 这个值在这个对象的 value 属性上

也就是说我们修改的时候必须要修改的是 number1.value

通过给value属性添加 getter/setter 来实现对数据的劫持

但是在模板上使用的时候 不用写 number1.value 直接写 number1 即可

在模板编译的时候回自动加上 value

  1. <template> 
  2.   {{ number1 }} 
  3.   <button @click="updateNum">+</button>
  4. </template>
  5. <script lang="ts">
  6. import { defineComponent, ref } from 'vue'
  7. export default defineComponent({ 
  8.   name: 'Son'
  9.   setup() {  
  10.     let number1 = ref(10)  
  11.   
  12.     // 修改 number1  
  13.     function updateNum() {   
  14.       number1.value++   
  15.     }  
  16.     return {  
  17.       number1,   
  18.       updateNum,  
  19.     } 
  20.   },
  21. })
  22. </script>

使用起来完全没有问题

刚才强调了说 ref 接收 基本类型的数据,那么它可以接收 复杂类型吗,object 类型等,当然可以

给 ref 传入复杂类型,其实它是调用 reactive 来实现的

reactive 下面会提到

ref 获取元素

同样的 ref 还可以用了获取元素

大家在 Vue2.X 中是怎么获取的呢,先在 标签上定义 :ref='XXX' 然后 this.$refs.XXX 来获取

在 Vue3 上获取元素就有些许不同了

1.首先在 模板元素上 ref='XXX' 这里不用 v-bind

  1. <template> 
  2.   <div id="haha" ref="haha"></div>
  3. </template>

2.在 setup 中

得给 ref 指定类型 HTMLElement

  1. setup() { 
  2.   let haha = ref<HTMLElement|null>(null
  3.   console.log(haha)  
  4.   
  5.   return {  
  6.     haha, 
  7.   }
  8. },

如果在组件中需要使用到 haha ,就必须把 haha return 出去合并 data

我们来看看打印的是什么

可以看见的是 haha 是个 Ref 对象,value 值就是我们想要获取到的元素

然后我们可以对 haha 这个 DOM 元素进行操作,比如这个

haha.style.fontSize = '20px'

reactive

reactive 接收一个普通对象然后返回该普通对象的响应式代理对象

没错 它的底层就是使用 Proxy 进行代理

简单写个Vue3响应式例子来说下 Proxy

new Proxy(target, handler)

  • target :要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)

  • handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p

  1. // 模拟 Vue data
  2. let data = {  
  3.     msg: '',   
  4.     age: '',
  5. }
  6. // 模拟 Vue 的一个实例
  7. // Proxy 第一个
  8. let vm = new Proxy(data, {   
  9.     // get() 获取值  
  10.     // target 表示需要代理的对象这里指的就是 data  
  11.     // key 就是对象的 键  
  12.     get(target, key) {  
  13.         return target[key]  
  14.     },  
  15.     // 设置值  
  16.     // newValue 是设置的值   
  17.     set(target, key, newValue) {     
  18.         // 也先判断下是否和之前的值一样 节省性能    
  19.         if (target[key=== newValue) return    
  20.         // 进行设置值    
  21.         target[key= newValue   
  22.         document.querySelector('#app').textContent = target[key]    
  23.     },
  24. })

reactive 基础用法

导入,当然写的时候,vscode 会自动帮你引入

import { defineComponent, reactive } from 'vue'

简单使用

  1. setup() {  
  2.     let obj = reactive({    
  3.         name'小浪',    
  4.         age21,  
  5.     })  
  6.     return {     
  7.         obj,  
  8.     }
  9. }

来看看返回的 Proxy 对象吧

数据都在 target 中,

在模板使用直接 {{obj.name}} 即可

修改直接修改 obj[name] = ‘xxx’

操作代理对象,obj中的数据也会随之变化,同时如果想要在操作数据的时候,界面也要跟着重新更新渲染,那么也是操作代理对象

响应式的数据是深层次的(递归深度响应式)

对于多层嵌套的数据也是响应式的

  1. setup() {  
  2.     let obj = reactive({   
  3.         name'小浪',     
  4.         age21,     
  5.         phone: {       
  6.             p_name'小米',    
  7.             p_apps: {        
  8.                 app_name'小米运动',       
  9.             },      
  10.         },  
  11.      })  
  12.      function upadateName({    
  13.          obj.phone.p_apps.app_name = '掘金'   
  14.      }  
  15.      console.log(obj)  
  16.      
  17.      return {     
  18.          obj,     
  19.          upadateName, 
  20.     }
  21. },

shallowReactive

它是一个简单的 reactive ,只把第一层的对象改为响应式,这里就不多说了

使用 ref 传入对象

  1. setup() {  
  2.     let obj = ref({    
  3.         name'小浪',   
  4.         age21,  
  5.     }) 
  6.     console.log(obj)   
  7.     
  8.     return {     
  9.         obj,   
  10.     }
  11. }

实际上是 ref 使用 reactive 来进行操作的

toRefs

这个方法可以把 reactive 响应式对象,转化为 普通对象,普通对象的每个属性都是 Ref 对象,这样的话保证了 reactive 的每个属性还是响应式的,我们还可以把每个属性进行分解使用,这样在组件就不用 obj[属性],代码量减轻了,yyds

  1. setup() { 
  2.   const user = reactive({   
  3.     name'小浪',  
  4.     age21
  5.   }) 
  6.   
  7.   let userObj = toRefs(user) 
  8.   console.log(userObj) 
  9.   
  10.   return {}
  11. }

可以看见 name 和 age 已经变成了 Ref 对象

我们可以解构 出 name 和 age 单独使用

  1. setup() { 
  2.   const user = reactive({  
  3.     name'小浪',  
  4.     age21
  5.   }) 
  6.   
  7.   let userObj = toRefs(user) 
  8.   
  9.   return { 
  10.     ...userObj, 
  11.   }
  12. }

toRef

还有一个 toRef 方法,它的作用和 toRefs 差不多,但是它只能把响应式对象/普通对象的某一个属性变为 Ref 对象

可以用来为源响应式对象上的 property 性创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。

  1. export default { 
  2.   setup(props) {  
  3.     useSomeFeature(toRef(props, 'foo'))  
  4.   }
  5. }
  6. function useSomeFeature(foo: Ref) { 
  7.   // ...
  8. }

拷贝了一份新的数据值单独操作, 更新时相互不影响

当您要将 prop 的 ref 传递给复合函数时,toRef 很有用

可以从官方文档看出,用于在于组件之前的传递数据 从 props 拿出 'foo' 属性给复合函数,复合函数 useSomeFeature,接收的参数 foo 为 Ref 类型,刚好可以使用toRef 来进行转化

判断响应式

几个判断是否哪种响应式创建的方法

1.isRef: 检查一个值是否为一个 ref 对象

  1. let ref1 = ref(1)
  2. console.log(isRef(ref1))  // true

2.isReactive: 检查一个对象是否是由 reactive 创建的响应式代理

  1. let ref2 = reactive({name: '小浪'})
  2. console.log(isReactive(ref2))  // true

3.isReadonly: 检查一个对象是否是由 readonly 创建的只读代理

  1. let ref3 = readonly({name: '小浪'})
  2. console.log(isReadonly(ref3))  // true

4.isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

  1. let ref2 = reactive({name: '小浪'})
  2. console.log(isProxy(ref2))  // true
  3. let ref3 = readonly({name: '小浪'})
  4. console.log(isProxy(ref3))  // true

customRef

上面提到了这么多的 Ref 都是 Vue 帮我们内置的,

我们可以通过 customRef 实现我们自己的 Ref

创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track 和 trigger 函数作为参数,并应返回一个带有 get 和 set 的对象。

官方文档给了一个防抖的例子,我们也写个来看

  1. <template>
  2.   <h2>App</h2> 
  3.   <input v-model="keyword"/> 
  4.   <p>{{keyword}}</p>
  5. </template>
  6. <script lang="ts">
  7. import { 
  8.   customRef
  9. from 'vue'
  10. // 不确定类型所以这里使用泛型
  11. function useDebouncedRef<T>(value: T, delay = 200) { 
  12.   // 定时器
  13.   let timeout: number 
  14.   return customRef((track, trigger) => {   
  15.     return {    
  16.       get() {    
  17.         // 告诉Vue追踪数据     
  18.         track()     
  19.         return value   
  20.       },   
  21.       set(newValue: T) {    
  22.         clearTimeout(timeout)      
  23.         timeout = setTimeout(() => {  
  24.           value = newValue     
  25.           // 告诉Vue去触发界面更新     
  26.           trigger()     
  27.         }, delay)    
  28.       }   
  29.     } 
  30.   })
  31. }
  32. export default {  
  33.   setup () {  
  34.     const keyword = useDebouncedRef(''
  35.     return {  
  36.       keyword   
  37.     } 
  38.   },
  39. }
  40. </script>

shallowRef 和 shallowReactive

浅的响应式,一般用的不多,我们使用 ref 和 reactive 比较多

shallowReactive

对象结构多层嵌套,但是我们的需求只需要修改最外层的数据,就不用把里面的嵌套结构都转为响应式,这样使用浅的响应式提高性能,只有最外一层是响应式

比较容易理解,我这就里就不举例子了

shallowRef

我们之前说过 ref 也能传入一个对象,实际上还是调用 reactive 返回 Proxy 代理对象,如果内层还有对象,还是使用 reactive 进行处理

  1. ref({ name: '小明' })
  2. // 实际上是调用 reactive 去完成的,把 ref的 value 当作 key ,value的值,当作 key 的值 给 reactive
  3. reactive({ value: { name: '小明' } })

同样的 shallowRef 处理 对象类型,是交给 shallowReactive 去完成

  1. shallowRef({ name: '小明' })
  2. // 实际上是调用 reactive 去完成的,把 ref的 value 当作 key ,value的值,当作 key 的值 给 reactive
  3. shallowReactive({ value: { name: '小明' } })

这样子我们就明白了,为啥 只处理了 value 的响应式,不进行对象的 reactive 处理,适用于会被替换的数据

【注意】shallowRef 创建一个 ref ,将会追踪它的 value 更改操作,但是并不会对变更后的 value 做响应式代理转换

  1. setup() {
  2.   let info1 = ref({ 
  3.     name: '小浪',  
  4.     notebook: {  
  5.       name: '小米笔记本',  
  6.     }, 
  7.   }) 
  8.   let info2 = shallowRef({ 
  9.     name: '小明',  
  10.     notebook: {    
  11.       name: '小米笔记本',  
  12.     }, 
  13.   }) 
  14.   
  15.   console.log(info1, info2)  
  16.   return {  
  17.     info1,  
  18.     info2,  
  19.   }
  20. },

我们来打印下两个对象

可以看见的是 Ref 的 value 值是用 reactive 返回的 Proxy 对象,

shallowRef 的 value 是普通对象

readonly 和 shallowReadonly

readonly 深度只读

设置普通对象或者是响应式对象为只读,不能进行修改,看上面的名字就知道是深度的,深度是什么概念大家差不多都清楚,递归把内层的每一个属性都设置为只读,进行修改操作就会报错,提高了安全性

基本使用:

用什么就导入什么

import { defineComponent, readonly } from 'vue'复制代码

果然在编译之前就报错了 Error无法分配到 "name" ,因为它是只读属性

无论是内层还是外层都只读,是深度检测的

shallowReadonly 浅度只读

浅度的话只针对最外面一层不关心 内层

可以看下面的例子 只有外层的 name 报错,修改内层没有错误

toRaw 和 markRaw

这两个用的还是比较少

我这里就简单的过一下

toRaw: 将一个响应式对象转为普通对象

简单使用:

  1. setup() { 
  2.   let info1 = reactive({ 
  3.     name'小浪',   
  4.     notebook: {    
  5.       name'小米笔记本'
  6.     }, 
  7.   })
  8.   const rawInfo = toRaw(info1) // 返回普通对象  
  9.   console.log(info1) 
  10.   console.log(rawInfo)  
  11.   
  12.   return {}
  13. },

两个打印出来,一个是响应式对象,通过 toRaw 后变成了普通对象

markRaw: 标记一个对象,让它永远不会转为响应式对象,返回值是本身

比如:一些不变的数据死数据,还有一些第三方类实例,不用转为响应式对象,提高性能

简单使用:

这里使用 两个一样的对象,一个进行 markRaw 处理,一个不进行 markRaw 处理

然后同样使用 reactive 转为 响应式

  1. setup() { 
  2.   let obj = {  
  3.   name: '小浪',  
  4.   notebook: {     
  5.     name: '小米笔记本',  
  6.   }, 
  7.  } 
  8.  // 进行标记 
  9.  let markRawObj = markRaw(obj)
  10.  // 尝试转为响应式 
  11.  let reactObj = reactive(markRawObj) 
  12.  let obj2 = {  
  13.    name: '小浪',  
  14.    notebook: {   
  15.      name: '小米笔记本',  
  16.    }, 
  17.  } 
  18.  // 转为响应式 
  19.  let reactObj2 = reactive(obj2
  20.  console.log(reactObj) 
  21.  console.log(reactObj2
  22.  return {}
  23. }

可以看看打印的,被标记过的 obj 并没有转为 Proxy 响应式代理对象

computed 计算属性

Vue3中使用computed 和Vue2.X 有些不同,这里 computed是一个方法

首先还是得导入 computed 方法

import { defineComponent, computed } from 'vue'

参数为一个回调 默认为 get

  1. <template> 
  2.   <div class="box">  
  3.     <input type="text" v-model="name" />  
  4.     <br />  
  5.     <input type="text" v-model="age" />  
  6.     <br />  
  7.     <input type="text" v-model="getInfo" /> 
  8.   </div>
  9. </template>
  1. setup() {  
  2.     let name = ref('小浪')   
  3.     let age = ref(21)  
  4.     
  5.     //计算属性   
  6.     let getInfo = computed(() => {    
  7.         return `我的名字:${name.value},今年 ${age.value},请多多指教`  
  8.     })  
  9.     return {    
  10.         name,    
  11.         age,     
  12.         getInfo,   
  13.     }
  14. }

这里没有实现 set 方法,所以修改下面没有用

参数为一个对象 在这里写 get set

模板和上面一样

  1. setup() {  
  2.     let name = ref('小浪')  
  3.     let age = ref(21
  4.     
  5.     let getInfo = computed({   
  6.         // get 方法   
  7.         get() {       
  8.             return `${name.value},${age.value}`      
  9.         },      
  10.         // set 方法    
  11.         set(val: string) {     
  12.             let arr = val.split(',')     
  13.             name.value = arr[0]      
  14.             age.value = parseInt(arr[1])     
  15.         },  
  16.     })    
  17.     return {     
  18.         name,     
  19.         age,     
  20.         getInfo, 
  21.     }

watch 侦听器

Vue2.X 的 Watch 使用方法差不多

介绍

watch(data,handler,object)

  1. data:可以是返回值的 getter 函数,也可以是 ref

  2. handler:回调函数

  3. object:可选配置项 { immediate: true }

引入

import { defineComponent, watch } from 'vue'

data 为一个 ref

回调函数的参数是 (新值,旧值)

  1. setup() {  
  2.     let name = ref('小浪')  
  3.     let age = ref(21)  
  4.     
  5.     let watchName = ref('')  
  6.     watch(name, (newName, oldName) => {     
  7.         watchName.value = `我是新姓名 ${newName} 
  8.                 我是老姓名 ${oldName}`  
  9.     })   
  10.     return {    
  11.         name,       
  12.         age,     
  13.         watchName,  
  14.     }
  15. },

可以看见页面第三栏没有显示,因为 name 值没有变化,所以就不用改变,watch的第三个参数是 配置对象,我们在里面可以设置 立即执行 { immediate: true }

就会执行一次 当然这个时候 oldName 为 undefined

  1. watch(
  2.   name, 
  3.   (newName, oldName) => {  
  4.     watchName.value = `我是新姓名 ${newName}  
  5.   我是老姓名 ${oldName}
  6.   }, 
  7.   { immediatetrue }
  8. )

data 为一个 getter

  1. watch(()=>haha,(newName, oldName)=>
  2.   // 处理...
  3. })

()=> haha 直接返回一个值,相当于 getter 简写,haha可以不是响应式数据

data 为多个 ref

模板还是之前那个

  1. <template> 
  2.   <div class="box">  
  3.     <input type="text" v-model="name" />  
  4.     <br />  
  5.     <input type="text" v-model="age" />  
  6.     <br />  
  7.     <input type="text" v-model="getInfo" /> 
  8.   </div>
  9. </template>

我们可以把多个 ref 放进一个数组里面

newNameAndAgeoldNameAndAge为一个数组保存着 新 和 旧的 [name,age]

  1. setup() {  
  2.     let name = ref('小浪')   
  3.     let age = ref(21)  
  4.     
  5.     let watchName = ref('')  
  6.     watch(   
  7.       [name, age],    
  8.       (newNameAndAge, oldNameAndAge) => {    
  9.         watchName.value = `new: ${newNameAndAge}    
  10.         old: ${oldNameAndAge}`    
  11.       },   
  12.       { immediatetrue }   
  13.     )  
  14.     return {    
  15.         name,   
  16.         age,    
  17.         watchName, 
  18.     }
  19. },

data 为 reactive

  1. setup() { 
  2.   let user = reactive({  
  3.     name: '小浪',  
  4.     age: 21
  5.   }) 
  6.   
  7.   let watchInfo = ref('')
  8.   watch( 
  9.     user,  
  10.     (newInfo, oldInfo) => {    
  11.       console.log(newInfo === oldInfo)  // true   
  12.     }
  13.   )
  14. }

这里是对象 会出现问题,立即执行后,

如果加上 立即执行 除了第一次 newInfo为 {name: '小浪',age: 21}

oldInfo 为 undefined ,之后始终返回该对象的当前值

所以 newInfo = oldInfo

对于这个问题,我们得加上配置对象 {deep: true}进行深度检测

深度检测还可以判断多重嵌套

  1. watch( 
  2.   user, 
  3.   (newInfo, oldInfo) => {  
  4.     console.log(newInfo === oldInfo) // false 
  5.   },  
  6.   { deep: true }
  7. )

watchEffect

这个也是用来监听数据变化,默认就会执行一次所以这里就不需要配置,而且不用指定 data,使用哪些响应式数据就监听哪些

  1. let user = reactive({  
  2.     name: '小浪',  
  3.     age: 21,
  4. })
  5. // 只有 user.name 发生改变这个就会执行
  6. watchEffect(() => {  
  7.     console.log(user.name)
  8. });

provide / inject

提供 和 注入 是很简单理解的

实现跨层级组件(祖孙)间通信

在多层嵌套组件中使用,不需要将数据一层一层地向下传递

可以实现 跨层级组件 通信

在 父组件中

  1. setup() {   
  2.     const info reactive({    
  3.         title'Vue3学习'     
  4.         date'2021/7/23'  
  5.     }) 
  6.     // 提供数据 提供的数据名,数据值 
  7.     provide('info', info)     
  8.     
  9.     return {    
  10.         info  
  11.     }
  12. }

在 子孙 层级组件使用注入就能够获取到了

  1. setup() {   
  2.     //获取对应数据的值  
  3.     const color = inject('info')   
  4.     
  5.     return {     
  6.         info  
  7.     }
  8. }

Teleport 传送组件

这个组件特别有趣,可以把组件进行传送

  1. <teleport v-if="flag" to=".test"> 
  2.     <div class="dog">狗子</div>
  3. </teleport>

to 是目标的地址 body , #XXX , .XXX 这些都是 css 选择器

下面写个例子大家看下就明白了

模板

  1. <template> 
  2.   <ul>    
  3.     <li class="li_1"></li>  
  4.     <li class="li_2"></li>  
  5.     <li class="li_3"></li>
  6.   </ul> 
  7.   <teleport :to="target">  
  8.     <img src="https://img0.baidu.com/it/u=3077713857,1222307962&fm=26&fmt=auto&gp=0.jpg" /> 
  9.   </teleport> 
  10.   <div class="btnGroup">  
  11.     <button @click="target = '.li_1'">传送1</button>  
  12.     <button @click="target = '.li_2'">传送2</button>   
  13.     <button @click="target = '.li_3'">传送3</button> 
  14.   </div>
  15. </template>

setup

  1. setup() { 
  2.   // target 
  3.   let target = ref('.li_1')  
  4.   return { 
  5.     target, 
  6.   }
  7. },

利用 按钮 点击来控制 teleport 是否显示, teleport 一渲染,就会跑到 li 下面

Vue3 生命周期

Vue2.X 对应 Vue3组合API

Vue2.XVue3
beforeCreate--->setup()
created--->setup()
beforeMount--->onBeforeMount
mounted--->onMounted
beforeUpdate--->onBeforeUpdate
updated--->onUpdated
beforeDestroy--->onBeforeUnmount
destroyed--->onUnmounted
activated--->onActivated
deactivated--->onDeactivated
errorCaptured--->onErrorCaptured
onRenderTriggered
onRenderTracked

可以看出

beforeCreate 和 created 在Vu3还是能正常使用,在Vue3我们可以用更好更快的 setup 代替

on开头的 生命周期需要 通过 import 导入,在 setup 函数中使用

Vue3 的生命周期 比 Vue2.X 的生命周期快

举个例子:   onBeforeMount 比 beforeMount 快 其他同理

还多个两个钩子:

  • onRenderTriggered 跟踪虚拟 DOM 重新渲染时调用

  • onRenderTracked 当虚拟 DOM 重新渲染被触发时调用

全局API转移

Vue2.X 中 Vue 上面的全局API ,比如自定义指令 Vue.directive,全局组件 Vue.component 在Vue3都进行改变,不再提供 Vue ,而是提供 app

具体改变可以看下面

Vue2.XVue3
Vue.configapp.config
Vue.config.productionTip移除
Vue.config.ignoredElementsapp.config.isCustomElement
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use
Vue.prototypeapp.config.globalProperties
new Vue().$mount('#app')createApp(App).mount('#app')

结语

到了这里我们基本都了解了 Vue3 的一些特性

  • 新的脚手架工具vite

  • 在 Vue3 仍然支持 Vue2 中的大多数特性

  • Vue 组合APi代替了Vue2中的option API ,同一逻辑集中起来,复用性更强了

  • Vue3 使用 TS 编写更好的支持TS

  • Vue3 使用Proxy 代替了Vue2Object.defineProperty() 实现响应式原理

  • 介绍了新的组件: Fragment Teleport Suspense

这里还没有提到的 Vue3 重写了 虚拟DOM ,提高了性能

希望这篇笔记能够帮助到大家,如果我写的不清楚,具体的还得看 官方文档 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/215457?site
推荐阅读
相关标签
  

闽ICP备14008679号