我正在参加「掘金·启航计划」
💡 Tips:本文主要以vue2和vue3相比不同的角度出发,快速上手vue3
1.Suspense组件
💡 Tips: vue2中异步组件 需要用v-if来判断 如loading状态显示加载 请求结束显示图表
Suspense是带插槽的组件,只是它的插槽指定了default 和 fallback 两种状态。
<Suspense>
<template #default>
<!-- 异步组件-默认渲染的页面 -->
<Children :msg="msg" :list="list" @changeMsg="changeMsg"></Children>
</template>
<template #fallback>
<!-- 页面还没加载出来展示的页面 -->
<div>loading...</div>
</template>
</Suspense>
2.defineAsyncComponent
💡 Tips: 通过defineAsyncComponent 包裹组件实现异步组件
<template>
<Children :list="list"></Children>
</template>
import { defineAsyncComponent } from 'vue'
const Children = defineAsyncComponent(() => import('./Children.vue'))
3.Teleport传送组件
💡 Tips: Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术,不受父级style、v-show等属性影响,但data、prop数据依旧能存在父子关系
场景:像 modals,toast 等这样的元素
参数:
1.to 挂载地方: 期望接收一个 CSS 选择器字符串或者一个真实的 DOM 节点。挂载时,传送的 to 目标必须已经存在于 DOM 中
2.禁用Teleport的传送功能
<Teleport to="body" :disabled="true">
<p>我是被 teleport 包裹的元素</p>
</Teleport>
多个 组件可以将其内容挂载在同一个目标元素上,顺序以此添加在老元素后面
<Teleport to="#customDom">
<p>1</p>
</Teleport>
<Teleport to="#customDom">
<p>2</p>
</Teleport>
//1
//2
4.provide/inject传值
💡 Tips:provide 可以在祖先组件中指定我们想要提供给后代组件的数据或方法,而在任何后代组件中,我们都可以使用 inject 来接收 provide 提供的数据或方法。
//父
<template>
<Children></Children>
</template>
<script setup lang="ts">
import { ref, provide } from 'vue'
import Children from "./Children.vue"
const msg = ref('hello')
provide('msg', msg)
</script>
//子
<template>
<div>
<p>msg:{{msg}}</p>
</div>
</template>
<script setup lang="ts">
import { inject, Ref, ref } from 'vue'
const msg = inject<Ref<string>>('msg',ref('hi'))
</script>
5.v-bind CSS使用变量
💡 Tips: 让css使用定义的变量
<script lang="ts" setup>
import { ref } from 'vue'
const color = ref('red')
</script>
<style scoped>
span {
color: v-bind('color');
}
</style>
6.自定义指令
生命周期:
- created 元素初始化的时候
- beforeMount 指令绑定到元素后调用 只调用一次
- mounted 元素插入父级dom调用
- beforeUpdate 元素被更新之前调用
- updated:update这个周期方法被移除 改用updated
- beforeUnmount 在元素被移除前调用
- unmounted 指令被移除后调用 只调用一次。
<template>
<div v-move class="box">
</div>
</template>
<script setup lang='ts'>
import { Directive } from "vue";
const vMove: Directive = {
mounted(el: HTMLElement) {
//xxx
},
};
</script>
7.toRef、toRefs、toRaw
1.toRef
💡 Tips:将响应式对象中的某个属性单独提供给外部使用。
注意:响应式数据经过toRef返回的值仍具有响应性,非响应式数据经过toRef返回的值仍没有响应性,只会改变数据不会改变视图。
import { reactive, toRef } from 'vue'
const obj = {
age: 18
}
//此时不具有响应式
const state = toRef(obj, 'age')
const obj = reactive({
age: 18
})
//此时具有响应式
const state = toRef(obj, 'age')
2.toRefs
💡 Tips: 相当于对对象内部每个属性都调用 toRef,批量版的toTef
主要用于解决 解构赋值失去响应式
toRefs只会将第一层转换为ref基本类型
const obj = reactive({
name: 'name',
age: 18
})
let { name, age } = toRefs(obj)
const change = () => {
age.value++//使用时候需要加上.value
}
3.toRaw
💡 Tips:将响应式对象修改为普通对象
数据变化,视图不更新 失去响应式
const obj = reactive({
name: 'name',
age: 18
})
const data = toRaw(obj)
8.$ref
💡 Tips:可以让ref省去.value 步骤
$ref() 方法是一个编译时的宏命令,它不是一个真实的、在运行时会调用的方法
全局可用的、无需手动导入
//import { $ref } from 'vue/macros' 如果非要引入 显得明显的话
let count = $ref(0)
可以在vite这种打包工具中配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue({
refTransform: true // 开启ref转换
})
]
})
9.watch
💡 Tips:监听,和vue2不同的是参数,以及可以监听多个,不会立即指向
watch(data,()=>{},{})
参数一,监听的数据,如果是非基本数据类型,使用()=>使用回调函数,多个数据使用数组[()=>x.x,()=>x.y]
参数二,数据改变时触发的回调函数(newVal,oldVal),多个数据使用数组[(newVal,oldVal),(newVal,oldVal)]
参数三,options配置项,为一个对象,deep深度监听和immediate立即监听, 两个选项
//监听一个ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
//监听多个
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
},
{
deep: true, // 深度监听
//immediate:true, // 初始化之前就监听
}
)
10.watchEffect
💡 Tips: 副作用函数,会根据其中的属性,自动监听其变化
、watcheffect初始化时,一定会执行一次(收集要监听的数据,不然不知道监听的是什么)
const numberRef = ref(100)
const state = reactive({
name: 'test',
age: 20
})
watchEffect(() => {
// 监听的是state.name 不会监听state.age
console.log('state.name', state.name)
})
继续更新中
原文链接:https://juejin.cn/post/7246293244636299321 作者:街头炒河粉