
Vue3 基础技术总结一
2025年1月10日...大约 14 分钟Vue3基础技术总结
Vue3 基础技术总结一
ref
ref 用法详细案例
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ name }}</h2>
<h2>bb:{{ job.aa.bb }}</h2>
<button @click="changeInfo">修改人的信息</button>
</template>
<script>
import { ref } from "vue";
export default {
name: "App",
setup() {
let name = ref("张三");
let job = ref({
type: "前端工程师",
salary: "30k",
aa: {
bb: "bb",
cc: "cc",
},
});
function changeInfo() {
name.value = "李思";
job.value.aa.bb = "dd";
}
return {
name,
job,
changeInfo,
};
},
};
</script>
要点总结:
- 既可定义基本类型的数据又可定义对象类型数据。
- 变量赋值需要加 .value。
- ref 包装基本类型数据后变成了 RefImpl 类型。
- ref 包装对象类型数据后 RefImpl 中的 value 值变成了 Proxy(Object) 类型。
- 服务器返回的数据替换原始数据时,对于 ref 包装的对象类型,需要用
原始对象.value
=服务器对象
,将数据传递过去。
<script>
export default {
...
setup() {
let name = ref("张三");
...
function changeInfo() {
name.value = "李思";
}
},
};
</script>
reactive
reactive 详细用法案例
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>工作种类:{{ job.type }}</h2>
<h2>工作薪水:{{ job.salary }}</h2>
<h2>bb:{{ job.aa.bb }}</h2>
<h2>爱好1:{{ hobby }}</h2>
<h2>爱好2:{{ job.aa.cc.dd }}</h2>
<br />
=========================================================
<br />
<h2>姓名:{{ p.name }}</h2>
<h2>年龄:{{ p.age }}</h2>
<h2>工作种类:{{ p.job.type }}</h2>
<h2>工作薪水:{{ p.job.salary }}</h2>
<h2>爱好1:{{ p.hobby }}</h2>
<button @click="changeInfo">修改人的信息</button>
</template>
<script>
import { ref, reactive } from "vue";
export default {
name: "App",
setup() {
//数据=======================================================
let name = ref("张三");
let age = ref(29);
let job = reactive({
type: "前端工程师",
salary: "30k",
aa: {
bb: "bb",
cc: {
dd: ["抽烟", "喝酒", "烫头"],
},
},
});
let hobby = reactive(["抽烟", "喝酒", "烫头"]);
// 定义一个对象===============================================
let person = {
name: "王五",
age: 118,
job: {
type: "后端工程师",
salary: "50K",
},
hobby: ["看电影", "搞对象", "玩游戏"],
};
let p = reactive(person);
//方法
function changeInfo() {
//响应基本数据类型--------------------------------------------
name.value = "李思";
age.value = 32;
//响应object--------------------------------------------------
job.type = "UI设计师";
job.salary = "50K";
job.aa.bb = "dd";
//数组也能自动响应耶----------------------------------------------
job.aa.cc.dd[2] = "洗澡";
job.aa.cc.dd[0] = "摔跤";
hobby[1] = "学习";
hobby[0] = "运动";
//修改person对象属性值-----------------------------------------------
p.name = "互骂查";
p.age = 200;
p.job.type = "无业游民";
p.job.salary = "100k";
p.hobby[0] = "编程";
}
return {
age,
name,
job,
hobby,
p,
changeInfo,
};
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
要点总结:
- 定义对象类型数据。
- reactive 包装对象类型变量后变成了 Proxy(Object) 类型。
- 服务器返回的数据替换原始数据时,需要用
Object.assign
(原始对象
,服务器对象
) 将数据传递过去,千万不能直接赋值服务器返回的对象给原始对象。
<script>
export default {
...
setup() {
let person =reactive({
job: {
type: "后端工程师",
},
hobby: ["看电影", "搞对象", "玩游戏"],
});
...
function changeInfo() {
person.job.type = "无业游民";
person.hobby[0] = "编程";
}
...
},
};
</script>
注意
person = 服务器返回的对象。(错误写法)
Object.assign(person, 服务器返回的对象) (正确写法)
ref vs reactive
- 若需要一个基本类型的响应式数据,必须使用
ref
。- 若需要一个响应式对象,层级不深,
ref
、reactive
都可以。- 若需要一个响应式对象,且层级较深,推荐使用
reactive
。
toRefs & toRef
详细用法案例
<template>
<div class="person">
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>性别:{{ person.gender }}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeGender">修改性别</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref, reactive, toRefs, toRef } from "vue";
// 数据
let person = reactive({ name: "张三", age: 18, gender: "男" });
// 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
let { name, gender } = toRefs(person);
// 通过toRef将person对象中的gender属性取出,且依然保持响应式的能力
let age = toRef(person, "age");
// 方法
function changeName() {
name.value += "~";
}
function changeAge() {
age.value += 1;
}
function changeGender() {
gender.value = "女";
}
</script>
<template>
<h2>全部信息:{{ person }}</h2>
<h2>姓名:{{ name }}</h2>
<br />
<h2>年龄{{ age }}</h2>
<br />
<h2>薪资{{ job.j1.salary }}</h2>
<button @click="name += '~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
</template>
<script>
import { reactive, toRef, toRefs } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
return {
person,
...toRefs(person),
// name: toRef(person, "name"),
// age: toRef(person, "age"),
// salary: toRef(person.job.j1, "salary"),
};
},
};
</script>
要点总结:
- 作用:将一个响应式对象中的每一个属性,转换为
ref
对象。 - 备注:
toRefs
与toRef
功能一致,但toRefs
可以批量转换。
<script lang="ts" setup name="Person">
...
let person = reactive({name:'张三', age:18, gender:'男'})
let {name,gender} = toRefs(person)
// 通过 toRef 将 person 对象中的 age 属性取出,且依然保持响应式的能力
let age = toRef(person,'age')
...
</script>
<script>
import { reactive, toRef, toRefs } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: "张三",
job: {
j1: {
salary: 20,
},
},
});
return {
person,
...toRefs(person),
// salary: toRef(person.job.j1, "salary"),
};
},
};
</script>
setup & props & context & slots & emits
详细用法案例
<!-- 父组件 -->
<template>
<Demo msg="老杨同志" shcool="尚硅谷" @hello="showHelloMsg">
<template v-slot:qwe>
<span>尚硅谷好哈哈哈</span>
</template>
</Demo>
</template>
<script setup lang="ts" name="App">
import Demo from "./components/Demo.vue";
function showHelloMsg(value) {
alert(`你好啊,你触发了 hello 事件,我收到的参数是:${value}!`);
}
</script>
<!-- 子组件 -->
<template>
<h1>一个人的信息</h1>
<h2 v-show="p.name">姓名:{{ p.name }}</h2>
<h2>年龄:{{ p.age }}</h2>
<button @click="test">测试一下触发Demo组件的Hello事件</button>
</template>
<script lang="ts">
import { reactive } from "vue";
export default {
name: "Demo",
props: ["msg", "shcool"],
emits: ["hello"],
slots: [],
setup(props, context) {
console.log("-----setup------", context.attrs);
console.log("-----setup------", context.emit);
console.log("-----setup------", context.slots);
let person = reactive({
name: "王五",
age: 118,
});
function test() {
context.emit("hello", "尚硅谷");
}
return {
person,
test,
};
},
};
</script>
computed
详细用法案例
<template>
<h1>一个人的信息</h1>
<br />
姓:<input type="text" v-model="p.firstName" />
<br />
名:<input type="text" v-model="p.lastName" />
<br />
全名:<input type="text" v-model="p.fullName" />
</template>
<script>
import { reactive, computed } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
firstName: "王",
lastName: "八蛋",
age: 118,
});
person.fullName = computed({
// 添加 setter 后修改计算属性也会同步修改firstName和lastName
set(value) {
const nameArr = value.split("-");
if (nameArr.length == 2) {
p.firstName = nameArr[0];
p.lastName = nameArr[1];
}
},
get() {
return p.firstName + "-" + p.lastName;
},
});
return {
person,
};
},
};
</script>
要点总结:
- 计算属性里面有缓存,多次调用获取数据时只执行一次。
- 计算属性实质上其实是 ref 定义的响应式数据。
- 计算属性完整写法是可读可写的。请看详细用法案例中的代码。
watch
监视 ref 基本数据详细用法案例
<template>
<h1>当前求和为:{{ sum }}</h1>
<br />
<button @click="sum++">点我+1</button>
<hr />
<h1>当前的信息为:{{ msg }}</h1>
<button @click="msg += '!'">你好啊</button>
</template>
<script setup lang="ts" name="Demo">
import { ref, watch } from "vue";
let sum = ref(0);
let msg = ref("你好啊");
const stopWatch = watch([sum, msg], (newValue, oldValue) => {
console.log(`sum的值变化了!${newValue},${oldValue}`);
//条件满足后就停止监视
if (newValue[0] >= 10) {
stopWatch();
}
});
</script>
要点总结:
- 监视 ref 基本数据类型时,第一个参数不能是
变量.value
。
监视 ref 对象数据详细用法案例
<template>
<h1>当前求和为:{{ sum }}</h1>
<br />
<button @click="sum++">点我+1</button>
<hr />
<h2>当前的信息为:{{ msg }}</h2>
<button @click="msg += '!'">你好啊</button>
<hr />
<h2>姓名:{{ person.name }}</h2>
<br />
<h2>年龄{{ person.age }}</h2>
<br />
<h2>薪资{{ person.job.j1.salary }}</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script setup lang="ts" name="Demo">
import { ref, watch } from "vue";
let person = ref({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
//监视的实际上是变量的地址。
watch(
person,
(newValue, oldValue) => {
console.log(newValue, oldValue);
},
{ deep: true }
);
</script>
要点总结:
- 监视 ref 对象数据类型时,第一个参数不能是
变量.value
。监视的实际上是变量的地址。如果监视的是对象内部的属性,需要开启{deep:true}
选项。 {deep:true}
深度监视。{immediate:true}
立即监视。初始时就先执行监视一次。- 若修改的是
ref
定义的对象中的属性,newValue
和oldValue
都是新值,因为它们是同一个对象。 - 若修改整个
ref
定义的对象,newValue
是新值,oldValue
是旧值,因为不是同一个对象了。
监视 reactive 对象数据详细用法案例
<template>
<h1>当前求和为:{{ sum }}</h1>
<br />
<button @click="sum++">点我+1</button>
<hr />
<h2>当前的信息为:{{ msg }}</h2>
<button @click="msg += '!'">你好啊</button>
<hr />
<h2>姓名:{{ person.name }}</h2>
<br />
<h2>年龄{{ person.age }}</h2>
<br />
<h2>薪资{{ person.job.j1.salary }}</h2>
<button @click="changeName">修改姓名</button>
<button @click="addAge">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script setup lang="ts" name="Demo">
import { ref, reactive, watch } from "vue";
let sum = ref(0);
let msg = ref("你好啊");
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
// 监视对象,性能问题
// watch(person, (newValue, oldValue) => {
// console.log(`person的值变化了!`, newValue, oldValue)
// })
// 监视对象的某个属性,提升性能
// watch(() => person.age, (newValue, oldValue) => {
// console.log(`person的age值变化了!`, newValue, oldValue)
// })
// 监视对象的多个属性
// watch([() => person.age, () => person.name], (newValue, oldValue) => {
// console.log(`person的age和name值变化了!`, newValue, oldValue)
// })
// 监视嵌套深的属性,必须开启deep
// watch(
// () => person.job,
// (newValue, oldValue) => {
// console.log(`person的job值变化了!`, newValue, oldValue);
// },
// { immediate: true, deep: true }
// );
function changeName() {
person.name += "~";
}
function addAge() {
person.age++;
}
</script>
要点总结:
- 第一个参数直接传递 reactive 包裹的对象时,监视的是对象的多个属性,但是无法正确获取 oldValue。默认开启深度监视,并且无法关闭深度监视,即
{deep:false}
无效。 - 第一个参数可以传递一个函数,比如
() => person.age
,不能传递person.age
。只监视对象中的某个属性,附带着性能有所提升。 - 第一个参数传递多个函数,比如
[() => person.age,() => person.name]
时监视多个属性。 - 第一个参数在对象传递的属性值仍然是对象时,既可以写对象,又可以写函数,建议写成函数。
- 监视嵌套深的属性,必须开启
{deep:true}
。
watchEffect
详细用法案例
<template>
<h1>当前求和为:{{ sum }}</h1>
<br />
<button @click="sum++">点我+1</button>
<hr />
<h2>当前的信息为:{{ msg }}</h2>
<button @click="msg += '!'">你好啊</button>
<hr />
<h2>姓名:{{ person.name }}</h2>
<br />
<h2>年龄{{ person.age }}</h2>
<br />
<h2>薪资{{ person.job.j1.salary }}</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script setup lang="ts" name="Demo">
import { ref, reactive, watch, watchEffect } from "vue";
let sum = ref(0);
let msg = ref("你好啊");
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
// 函数里面用到的变量都会自动监视
watchEffect(() => {
const x1 = sum.value;
const x2 = person.job.j1.salary;
console.log("watchEffect监视了 sum 和 person.job.js.salary");
});
</script>
要点总结:
watchEffect
一上来就执行一次,同时响应式的追踪其依赖,并在依赖更改时重新执行该函数。
watch vs watchEffect
- 都能监听响应式数据的变化,不同的是监听数据变化的方式不同。
watch
:要明确指出监视的数据。watchEffect
:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。
生命周期钩子
详细用法案例
<script>
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
} from "vue";
export default {
name: "App",
setup() {
console.log("---setup-等价于beforeCreate和create------");
onBeforeMount(() => {
console.log("---onBeforeMount-------");
});
onMounted(() => {
console.log("---onMounted-------");
});
onBeforeUpdate(() => {
console.log("---onBeforeUpdate-------");
});
onUpdated(() => {
console.log("---onUpdated-------");
});
onBeforeUnmount(() => {
console.log("---onBeforeUnmount-------");
});
onUnmounted(() => {
console.log("---onUnmounted-------");
});
},
};
</script>
要点总结:
- 组件的生命周期有:创建、挂载、更新、销毁。
- 每个阶段都有钩子前和钩子完毕两个状态。
- vue3 没有 beforeCreate 和 create 两个钩子。被 setup 代替。
- 在有父子组件嵌套的地方,挂载钩子是子组件先执行,父组件后执行。APP 是最后挂载完毕的组件。
hooks
详细用法案例
使用钩子函数 usePoints.js
<template>
<h1>我是Test组件... ... ...</h1>
<h2>点击时鼠标的坐标是:{{ point.x }},{{ point.y }}</h2>
</template>
<script setup lang="ts" name="Test-Component">
import usePoint from "../hooks/usePoint";
const point = usePoint();
</script>
定一个钩子函数 usePoints.js
// hooks/usePoints.js
import { onMounted, reactive, onBeforeUnmount } from "vue";
export default function () {
let point = reactive({
x: 0,
y: 0,
});
function savePoint(event) {
point.x = event.pageX;
point.y = event.pageY;
console.log(event.pageX, event.pageY);
}
onMounted(() => {
window.addEventListener("click", savePoint);
});
onBeforeUnmount(() => {
window.removeEventListener("click", savePoint);
});
return point;
}
shallowRef & shallowReactive
详细用法案例
<template>
<h2>x:{{ x.y }}</h2>
<h2>全部:{{ person }}</h2>
<h2>姓名:{{ name }}</h2>
<br />
<h2>年龄{{ age }}</h2>
<br />
<h2>薪资{{ job.j1.salary }}</h2>
<button @click="name += '~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
<button @click="x.y++">x+++++</button>
</template>
<script>
import { reactive, ref, toRefs, shallowReactive, shallowRef } from "vue";
export default {
name: "Demo",
setup() {
let person = shallowReactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
let x = ref({
y: 0,
});
// let x = shallowRef({
// y: 0
// })
return {
x,
person,
...toRefs(person),
};
},
};
</script>
shallowReadonly & readOnly
详细用法案例
<template>
<h2>x:{{ x }}</h2>
<h2>姓名:{{ name }}</h2>
<br />
<h2>年龄{{ age }}</h2>
<br />
<h2>薪资{{ job.j1.salary }}</h2>
<button @click="name += '~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
<button @click="x++">x+++++</button>
</template>
<script>
import { reactive, ref, toRefs, readonly, shallowReadonly } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
let x = ref(0);
// person = readonly(person)
// x = shallowReadonly(x)
person = shallowReadonly(person);
x = readonly(x);
return {
x,
...toRefs(person),
};
},
};
</script>
raw & markRaw
详细用法案例
<template>
<h2>x:{{ x }}</h2>
<h2>姓名:{{ name }}</h2>
<br />
<h2>年龄{{ age }}</h2>
<br />
<h2>薪资{{ job.j1.salary }}</h2>
<button @click="name += '~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
<button @click="x++">x+++++</button>
<button @click="showRaw">输出最原始的person</button>
<br />
<h2 v-show="person.car">汽车{{ person.car }}</h2>
<button @click="addCar">给人添加一台车</button>
<button v-show="person.car" @click="person.car.name += '~'">换车名</button>
<button v-show="person.car" @click="person.car.price++">换价格</button>
</template>
<script>
import { reactive, ref, toRaw, toRefs, markRaw } from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
let x = ref(0);
function showRaw() {
const p = toRaw(person);
console.log(p);
// ref 对象不能使用
// const sum = toRaw(x)
// console.log(sum)
}
function addCar() {
const car = { name: "奔驰", price: 40 };
person.car = markRaw(car);
console.log(person.car);
}
return {
x,
person,
...toRefs(person),
showRaw,
addCar,
};
},
};
</script>
customRef
详细用法案例
<template>
<input type="text" v-model="keyWord" />
<h3>{{ keyWord }}</h3>
</template>
<script>
import { ref, customRef } from "vue";
export default {
name: "App",
setup() {
//let keyWord = ref('hello')//使用 vue 提供的 ref 来实现实时动态更新功能
function myRef(value, delay) {
let timer;
console.log("自定义的myRef", value);
return customRef((track, trigger) => {
return {
get() {
console.log("有人从myRef中读取数据了", value);
track(); //通知 vue 追踪 value
return value;
},
set(newValue) {
console.log("有人改数据了", newValue);
value = newValue;
clearTimeout(timer);
timer = setTimeout(() => {
trigger(); //通知 vue 重新解析模板
}, delay);
},
};
});
}
let keyWord = myRef("hello", 500); //使用自定义的 ref 来实现实时动态更新功能
return {
keyWord,
};
},
};
</script>
provide & inject
详细用法案例
父组件
<template>
<div class="app">
<h3>我是APP组件 祖 {{ name }}----{{ price }}</h3>
<Child />
</div>
</template>
<script>
import { reactive, toRefs, provide } from "vue";
import Child from "./components/Child.vue";
export default {
name: "App",
components: { Child },
setup() {
let car = reactive({
name: "奔驰",
price: 40,
});
provide("car", car); //给自己的后代组件传递数据
return {
...toRefs(car),
};
},
};
</script>
儿子组件
<template>
<div class="child">
<h3>我是child组件 子</h3>
<Son />
</div>
</template>
<script>
import Son from "./Son.vue";
export default {
name: "Child-c",
components: { Son },
setup() {},
};
</script>
孙子组件
<template>
<div class="son">
<h3>我是Son组件 孙 {{ name }}--vvvvv---{{ price }} www</h3>
</div>
</template>
<script>
import { inject, toRefs } from "vue";
export default {
name: "Son-c",
setup() {
let car = inject("car");
console.log(car, "son inject拿到数据了");
return {
...toRefs(car),
};
},
};
</script>
isRef 等
详细用法案例
<template>
<div class="app">
<h3>我是APP组件 祖 {{ name }}----{{ price }}</h3>
</div>
</template>
<script>
import {
ref,
reactive,
toRefs,
readonly,
isRef,
isReactive,
isReadonly,
isProxy,
} from "vue";
export default {
name: "App",
setup() {
let car = reactive({
name: "奔驰",
price: 40,
});
let sum = ref(0);
let car2 = readonly(car);
console.log(isRef(sum));
console.log(isReactive(car));
console.log(isReadonly(car2));
console.log(isProxy(car));
console.log(isProxy(car2));
return {
...toRefs(car),
};
},
};
</script>
telerport
详细用法案例
父组件
<!-- App.vue -->
<template>
<div class="app">
<h3>我是APP组件</h3>
<Child />
</div>
</template>
<script>
import Child from "./components/Child.vue";
export default {
name: "App",
components: { Child },
};
</script>
<style>
.app {
background-color: blueviolet;
padding: 10px;
}
</style>
儿子组件
<!-- child.vue -->
<template>
<div class="child">
<h3>我是child组件</h3>
<Son />
</div>
</template>
<script>
import Son from "./Son.vue";
export default {
name: "Child-c",
components: { Son },
};
</script>
<style>
.child {
background-color: rgb(58, 226, 43);
padding: 10px;
}
</style>
孙子组件
<template>
<div class="son">
<h3>我是Son组件</h3>
<Dialog></Dialog>
</div>
</template>
<script>
import Dialog from "./Dialog.vue";
export default {
name: "Son-c",
components: { Dialog },
};
</script>
<style>
.son {
background-color: rgb(226, 43, 58);
padding: 10px;
}
</style>
Dialouge 组件
<!-- Dialouge.vue -->
<template>
<div>
<button @click="isShow = true">点我谈个窗</button>
<Teleport to="body">
<div class="mask" v-if="isShow">
<div class="dialouge">
<h3>我是一个弹窗</h3>
<h4>一些数据内容呢</h4>
<h4>一些数据内容呢</h4>
<h4>一些数据内容呢</h4>
<button @click="isShow = false">关闭弹窗</button>
</div>
</div>
</Teleport>
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "Dialogue-c",
setup() {
let isShow = ref(false);
return {
isShow,
};
},
};
</script>
<style>
.dialouge {
background-color: rgb(43, 144, 226);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 10px;
width: 300px;
height: 300px;
text-align: center;
}
.mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
}
</style>
Suspense
详细用法案例
<template>
<div class="app">
<h3>我是APP组件</h3>
<Suspense>
<template v-slot:default>
<Child />
</template>
<template v-slot:fallback>
<h3>稍等,加载中... ...</h3>
</template>
</Suspense>
</div>
</template>
<script>
// import Child from './components/Child.vue';
import { defineAsyncComponent } from "vue"; //静态引入
const Child = defineAsyncComponent(() => {
//异步引入
return import("./components/Child.vue");
});
export default {
name: "App",
components: { Child },
};
</script>
<style>
.app {
background-color: blueviolet;
padding: 10px;
}
</style>
<!-- Child.vue -->
<template>
<div class="child">
<h3>我是child组件</h3>
{{ sum }}
</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "Child-c",
async setup() {
let sum = ref(0);
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ sum });
}, 5000);
});
return await p;
},
};
</script>
<style>
.child {
background-color: rgb(58, 226, 43);
padding: 10px;
}
</style>