一、computed
1.什么是computed
computed
表示计算属性,通常用于处理数据,简化书写在模板中的复杂逻辑。使用 computed
可以将数据处理成我们想要的格式,无需在模板中使用复杂冗长的计算表达式。
computed有两个方法,分别是set()和get()。它可以接受一个带有 get
和 set
函数的对象来创建一个可写的 ref 对象。
2.computed的使用
1)定义路由:
<!--routers/router.ts-->
{
path: '/test',
name: 'test',
component: () => import('~/views/test/index_computed.vue'),
meta: {
title: '测试computed'
}
}
复制代码
2)编写代码: 示例一:
<!--views/test/index_computed.vue-->
<template>
<div>{{ reverseMsg }}</div> //dlrowolleh
</template>
<script setup lang='ts'>
import { ref, reactive, computed } from "vue"; //1.引入computed
const msg = ref("helloworld");
const reverseMsg = computed(() => {
return msg.value.split("").reverse().join(""); //dlrowolleh
});
复制代码
示例2:
<!--views/test/index_computed.vue-->
<template>
<div>{{ plus }}</div> <!-- 8,触发plus1里的set函数 -->
<div>{{ count1 }}</div> <!-- 3,触发plus1里的set函数 -->
<div>{{ plus1 }}</div> <!-- 6,触发plus1里的get函数 -->
</template>
<script setup lang='ts'>
// 创建一个只读的计算属性ref对象
const count = ref(4);
const plus = computed(() => {
return count.value * 2; //8,此处只读取了count变量里的值
});
// 创建一个可写的计算属性ref对象。默认下触发get函数,set函数会将声明的变量值进行重置
const count1 = ref(4);
const plus1 = computed({
get: () => count1.value * 2, //4)打印plus1,再次触发get函数时,count1.value的值是新赋予的3,所以plus1的值为6,而非8
set: (val) => { //2)触发plus1里的set函数
count1.value = val - 1; //3)count1.value的值由4-->3
}
});
plus1.value = 4; //1)将plus1的val值设置为4
</script>
复制代码
3.为什么要有computed
模板中逻辑过重,不易维护,所以使用计算属性computed
来简化书写响应式状态的复杂逻辑。
二、Watch
作用:watch侦听器,可侦听响应式变量ref、reactive的数据变化。一旦数据发生变化,就自动执行监听回调。
语法
watch(source, (cur, pre) => {})
参数
watch有三个参数:
第一个参数是侦听器的源(source),用于指定要侦听的响应式变量。这个来源可以是一个 ref
、一个响应式对象
或是由以上类型的值组成的数组。
第二个参数是在发生变化时要调用的回调函数。该回调函数有三个参数,分别是cur(新值)、pre(旧值)以及一个回调函数。
第三个可选的参数是一个对象。如果需要深度监听,则deep:true。常见用法有{deep:true}、{ immediate: true }。
示例:当reactive对象嵌套对象时,此刻的deep生效。
const user = reactive({
name:"tom",
age:18,
gender:"male",
hobby:{
sing:"唱歌",
dangce:"跳舞"
}
})
watch(()=>user.hobby,(cur,pre)=>{
console.log(cur,pre);
},{deep:true})
复制代码
当watch 监听多个数据时需用中括号[ ]
括起来,值与值之间用逗号,
分隔。
watch的使用:
1.watch侦听ref响应式数据 (侦听单个数据源)
<template>
<div>
<p>
{{ message }}
</p>
<button @click="changeMsg">
改变message
</button>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const message = ref('helloWorld');
const changeMsg = () => {
message.value = '你好世界';
};
// 监听 message 变量,如果有发生变化,自动执行后面的回调函数
watch(message, (cur, pre) => {
changeMsg();
console.log(cur,pre); // 你好世界 helloWorld
},{deep:true});
</script>
复制代码
2.watch侦听reactive响应式数据中某个属性或某一些数据的变化
<template>
<div>
<p>
{{ user }} <!-- ['KoKo', 18, 'male']-->
{{ user.name }} <!-- KoKo -->
</p>
<button @click="changeName">
修改姓名
</button>
</div>
</template>
<script setup lang="ts">
import { reactive, watch } from 'vue';
const user = reactive({
name: 'tom',
age: 18,
gender: 'male'
});
const changeName = () => {
user.name = 'KoKo';
};
//监听 user 变量里的数据,如果有发生变化,自动执行后面的回调函数
//监听 [user.name, user.age,user.gender] 多个响应式数据,其中一个数据发生变化,就会触发 watch 回调函数
watch([() => user.name, () => user.age, () => user.gender], (cur, pre) => {
changeName();
console.log(cur,pre); // ['KoKo', 18, 'male'] ['tom', 18, 'male']
});
</script>
复制代码
3.stop停止监听
<script setup lang="ts">
//如果在组件销毁之前想要停止掉某个监听,可以使用stop停止监听
const stopWatch = watch(source,(cur,pre) => {
console.log("新值:", cur, "老值:", pre);
}, {deep:true});
// 当不再需要此侦听器时:
stopWatch()
//或使用定时器
//setTimeout(()=>{
// 停止监听
// stopWatch()
// }, 2000);
</script>
复制代码
watch进阶总结使用:
1.watch侦听ref响应式数据
<template>
<div>test</div>
</template>
<script setup lang='ts'>
import { ref, reactive, watch, onMounted } from 'vue';
// watch侦听ref响应式数据
const c = ref({
name: 'c',
prop: 'prop'
});
const d = ref({
name: 'd',
prop: 'prop'
});
const c1 = ref({
name: 'c1',
prop: {
name: 'c1',
prop: 'prop'
}
});
const d1 = ref({
name: 'd1',
prop: {
name: 'd1',
prop: 'prop'
}
});
onMounted(() => {
// watch侦听ref数据
c.value.name = 'c-1';
d.value.name = 'd-1';
c1.value.prop.name = 'c1-1';
d1.value.prop.name = 'd1-1';
});
// 1.watch侦听ref定义的一个或多个响应式数据,需要手动开启deep,否则无法侦听
watch(c, (cur, pre) => {
console.log(cur, pre); // {name: 'c-1', prop: 'prop'} {name: 'c-1', prop: 'prop'}
}, { deep: true });
watch([c, d], (cur, pre) => {
console.log(cur, pre); // [{name:'c-1',prop:'prop'},{name:'d-1',prop:'prop'}] [{name:'c-1',prop:'prop'},{name:'d-1',prop:'prop'}]
}, { deep: true });
// 2.watch侦听ref定义的一个响应式数据的一个或多个属性-基本数据
watch(() => c.value.name, (cur, pre) => {
console.log(cur, pre); // c-1 c
});
watch([() => c.value.name, () => d.value.name], (cur, pre) => {
console.log(cur, pre); // ['c-1', 'd-1'] ['c', 'd']
});
// 3.watch侦听ref定义的一个响应式数据的一个或多个属性-引用数据类型,无法获取preValue,需要手动开启deep,否则无法侦听
watch(() => c1.value.prop, (cur, pre) => {
console.log(cur, pre); // {name:'c1-1',prop:'prop'} {name:'c1-1',prop:'prop'}
}, { deep: true });
watch([() => c1.value.prop, () => d1.value.prop], (cur, pre) => {
console.log(cur, pre); // [{name:'c1-1',prop:'prop'},{name:'d1-1',prop:'prop'}] [{name:'c1-1',prop:'prop'},{name:'d1-1',prop:'prop'}]
}, { deep: true });
</script>
复制代码
2.watch侦听reactive响应式数据
<template>
<div>test</div>
</template>
<script setup lang='ts'>
import { ref, reactive, watch, onMounted } from 'vue';
// watch侦听reactive响应式数据
const c = reactive({
name: 'c',
prop: 'prop'
});
const d = reactive({
name: 'd',
prop: 'prop'
});
const c1 = reactive({
name: 'c1',
prop: {
name: 'c1',
prop: 'prop'
}
});
const d1 = reactive({
name: 'd1',
prop: {
name: 'd1',
prop: 'prop'
}
});
onMounted(() => {
// watch侦听reactive数据
c.name = 'c-1';
d.name = 'd-1';
c1.prop.name = 'c1-1';
d1.prop.name = 'd1-1';
});
// 1.watch侦听reactive定义的一个或多个响应式数据,会自动开启深度监听但无法获取preValue
watch(c, (cur, pre) => {
console.log(cur, pre); // {name: 'c-1', prop: 'prop'} {name: 'c-1', prop: 'prop'}
});
watch([c, d], (cur, pre) => {
console.log(cur, pre); // [{name:'c-1',prop:'prop'},{name:'d-1',prop:'prop'}] [{name:'c-1',prop:'prop'},{name:'d-1',prop:'prop'}]
});
// 2.watch侦听reactive定义的一个响应式数据的一个或多个属性-基本数据
watch(() => c.name, (cur, pre) => {
console.log(cur, pre); // c-1 c
});
watch([() => c.name, () => d.name], (cur, pre) => {
console.log(cur, pre); // ['c-1', 'd-1'] ['c', 'd']
});
// 3.watch侦听reactive定义的一个响应式数据的一个或多个属性-引用数据类型,无法获取preValue,需要手动开启deep,否则无法侦听
watch(() => c1.prop, (cur, pre) => {
console.log(cur, pre); // {name:'c1-1',prop:'prop'} {name:'c1-1',prop:'prop'}
}, { deep: true });
watch([() => c1.prop, () => d1.prop], (cur, pre) => {
console.log(cur, pre); // [{name:'c1-1',prop:'prop'},{name:'d1-1',prop:'prop'}] [{name:'c1-1',prop:'prop'},{name:'d1-1',prop:'prop'}]
}, { deep: true });
</script>
三、watchEffect
作用:深度监听响应式变量ref、reactive的数据变化。
语法
watchEffect(( ) => { })
参数
watchEffect有两个参数:
第一个参数是在发生变化时要调用的回调函数。
第二个参数是一个可选的选项。有{flush: 'post'}
、{flush: 'sync'}
watchEffect的使用
watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。
1.watchEffect侦听ref响应式数据
1)watchEffect侦听ref定义的一个或多个响应式数据,可以获取preValue
2)watchEffect侦听ref定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue
3)watchEffect侦听ref定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue。当没有具体到某个属性时,watchEffect可以侦听引用数据类型的所有属性,也能获取到preValue
<!--text.vue-->
<template>
<div>test</div>
</template>
<script setup lang='ts'>
import { ref, reactive, watchEffect, onMounted } from 'vue';
// watchEffect侦听reactive响应式数据
// 基本数据类型
const c = ref({
name: 'c',
prop: 'prop'
});
const d = ref({
name: 'd',
prop: 'prop'
});
// 引用数据类型
const c1 = ref({
name: 'c1',
prop: {
name: 'c1',
prop: 'prop'
}
});
const d1 = ref({
name: 'd1',
prop: {
name: 'd1',
prop: 'prop'
}
});
onMounted(() => {
// watchEffect侦听ref数据
c.value.name = 'c-1';
d.value.name = 'd-1';
c1.value.prop.name = 'c1-1';
d1.value.prop.name = 'd1-1';
});
// 1.watchEffect侦听ref定义的一个或多个响应式数据,可以获取preValue
watchEffect(() => {
// watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。
console.log(c.value); // {name: 'c', prop: 'prop'} {name: 'c-1', prop: 'prop'}
console.log(c.value.name); // c c-1
});
watchEffect(() => {
console.log([c.value.name, d.value.name]); // ['c', 'd'] ['c-1', 'd-1']
});
// 2.watchEffect侦听ref定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue
watchEffect(() => {
console.log(c.value.name); // c c-1
});
watchEffect(() => {
console.log([c.value.name, c.value.prop]); // ['c', 'prop'] ['c-1', 'prop']
});
// 3.watchEffect侦听ref定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue
// 当具体到引用数据类型的某个属性时,能获取preValue
watchEffect(() => {
console.log(c1.value.prop.name); // c1 c1-1
});
watchEffect(() => {
console.log([c1.value.prop.name, c1.value.prop.prop]); // ['c1','prop'}] ['c1-1','prop']
});
// 当没有具体到某个属性时,可以侦听引用数据类型的所有属性。能获取preValue
watchEffect(() => {
console.log(c1.value.prop); // {name: 'c1', prop: 'prop'} {name: 'c1-1', prop: 'prop'}
});
watchEffect(() => {
console.log([c1.value.prop, d1.value.prop]); // [{name: 'c1-1', prop: 'prop'} {name: 'd1-1', prop: 'prop'}]
});
</script>
复制代码
2.watchEffect侦听reactive响应式数据
1)watchEffect侦听reactive定义的一个或多个响应式数据,可以获取preValue
2)watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue
3)watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue。当没有具体到某个属性时,watchEffect可以侦听引用数据类型的所有属性,也能获取到preValue
<!--text.vue-->
<template>
<div>test</div>
</template>
<script setup lang='ts'>
import { ref, reactive, watchEffect, onMounted } from 'vue';
// watchEffect侦听reactive响应式数据
// 基本数据类型
const c = reactive({
name: 'c',
prop: 'prop'
});
const d = reactive({
name: 'd',
prop: 'prop'
});
// 引用数据类型
const c1 = reactive({
name: 'c1',
prop: {
name: 'c1',
prop: 'prop'
}
});
const d1 = reactive({
name: 'd1',
prop: {
name: 'd1',
prop: 'prop'
}
});
onMounted(() => {
// watchEffect侦听reactive数据
c.name = 'c-1';
d.name = 'd-1';
c1.prop.name = 'c1-1';
d1.prop.name = 'd1-1';
});
// 1.watchEffect侦听reactive定义的一个或多个响应式数据,可以获取preValue
watchEffect(() => {
// watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。
console.log(c); // {name: 'c', prop: 'prop'} {name: 'c-1', prop: 'prop'}
console.log(c.name); // c c-1
});
watchEffect(() => {
console.log([c.name, d.name]); // ['c', 'd'] ['c-1', 'd-1']
});
// 2.watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue
watchEffect(() => {
console.log(c.name); // c c-1
});
watchEffect(() => {
console.log([c.name, c.prop]); // ['c', 'prop'] ['c-1', 'prop']
});
// 3.watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue
// 当具体到引用数据类型的某个属性时,能获取preValue
watchEffect(() => {
console.log(c1.prop.name); // c1 c1-1
});
watchEffect(() => {
console.log([c1.prop.name, c1.prop.prop]); // ['c1','prop'}] ['c1-1','prop']
});
// 当没有具体到某个属性时,它可以侦听引用数据类型的所有属性,能获取preValue
watchEffect(() => {
console.log(c1.prop); // {name: 'c1', prop: 'prop'} {name: 'c1-1', prop: 'prop'}
});
watchEffect(() => {
console.log([c1.prop, d1.prop]); // [{name: 'c1-1', prop: 'prop'} {name: 'd1-1', prop: 'prop'}]
});
</script>
复制代码
注意:
1.当watchEffect侦听引用数据类型时,它可以不需要指明具体的某个属性,便能侦听到该对象的所有属性。
2.watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。
watchEffect的参数
- flush: 'post':默认情况下,侦听器将在组件渲染之前执行。通过设置 flush: 'post'可以使侦听器延迟到组件渲染之后再执行。
- flush: 'sync':通过设置flush: 'sync'可以在响应式依赖发生改变时立即触发侦听器。
四、defineProps
作用:父组件向子组件传值,子组件通过defineProps
接收该值。
//父组件index.vue
<template>
<div>parent</div>
<son :value1="toSonValue" :method1="toSonMethod" /> //声明变量value1,绑定父组件的变量名toSonValue
</template>
<script setup lang='ts'>
import { ref } from 'vue';
import son from './son.vue';
const toSonValue = ref('toSonValue');
const toSonMethod = () => {
console.log('toSonMethod');
}
</script>
//子组件son.vue
<template>
<div>son</div>
<div>{{ value1 }}</div>
</template>
<script setup lang='ts'>
import { onMounted } from 'vue';
// 父组件往子组件传值value1,method1,其中method1是可选的
const props = defineProps<{ //子组件通过defineProps接收父组件传过来的value1和method1
value1: string,
method1?: () => void //可选的
}>()
onMounted(() => {
props.method1!(); // toSonMethod
})
</script>
复制代码
defineProps步骤:
1.新增一个子组件son.vue
2.在父组件通过import son from './son.vue'; 引入子组件
3.在父组件中声明变量toSonValue和toSonMethod
4.在父组件引入的子组件标签中,声明变量value1、method1,来绑定父组件toSonValue、toSonMethod两个变量名
5.在子组件中,声明变量props,该变量通过defineProps接收父组件传过来的value1和method1
五、defineEmits
作用:子组件向父组件传值,通过defineEmits触发父组件的自定义事件进行传值。
//子组件son.vue
<template>
<div @click="sonClick">son</div> //1.对son进行事件绑定
</template>
<script setup lang='ts'>
// defineEmits 定义子组件的自定义事件,及参数
const emit = defineEmits<{ //3.emit函数通过defineEmits 定义子组件的事件名和参数类型去触发父组件的自定义事件getSonValue
(e: 'sonSelfEvent', sonValue: string): void //返回一个void类型的数据
}>()
const sonClick = () => { //2.当点击son,将会执行sonClick()
emit('sonSelfEvent', 'sonValue') //此处是自定义的事件名及参数
}
</script>
//父组件index.vue
<template>
<div>parent</div>
<son @son-self-event="getSonValue" /> //对父组件自定义的getSonValue()进行事件绑定
</template>
<script setup lang='ts'>
import son from './son.vue';
const getSonValue = (value: string) => { //4.触发父组件的自定义事件getSonValue
console.log(value); // sonValue //接收子组件传过来的value值并将它打印出来
}
</script>
复制代码
defineEmits步骤:
1.新增一个子组件son.vue
2.在父组件通过import son from './son.vue'; 引入子组件
3.在父组件中声明自定义事件getSonValue
4.在父组件引入的子组件标签中,声明变量son-self-event,来绑定父组件自定义的getSonValue()方法
5.在子组件中,声明变量emit,该变量通过defineEmits定义子组件的事件名和参数类型去触发父组件的自定义事件getSonValue(即:defineEmits接收父组件传过来的getSonValue()方法)
6.在子组件中,声明sonClick方法对son进行事件绑定
7.当点击son,将会执行sonClick方法里,emit函数自定义的事件名及参数
注意:在Vue3中不需要对defineProps、defineEmits进行引入,直接使用即可。
六、vue3的插槽 slot
作用:向一个组件传递内容,可使用插槽。通过插槽来分发内容,即插槽作为分发内容的出口。使用<slot>
作为想要插入内容的占位符。
插槽的基本使用:
<!--父组件index.vue-->
<template>
<div>parent</div>
<div>
//匿名插槽
<son><button>按钮</button></son> //插入什么内容由父组件决定
<son><input type="text"></son>
</div>
<div>
//具名插槽
<son>
<!--v-slot只能添加在<template>上-->
<template v-solt:button><button>按钮</button></template> //根据定义的名字找到子组件中对应的插槽,然后进行替换
<template v-solt:input><input type="text"></template>
</son>
</div>
</template>
<script setup>
import son from './son.vue';
</script>
<!--子组件son.vue-->
<template>
<div>son</div>
<div>
//匿名插槽使用方式
<slot></slot>
</div>
<div>
<!--如果有多个值,同时放入组件进行替换时,一起作为替换元素-->
//具名插槽使用方式
<slot name="button" />
<slot name="input" />
</div>
</template>
<script setup>
import { useSlots } from 'vue' //引入方式
const slots = useSlots() //使用方式
</script>
复制代码
在向具名插槽提供内容的时候,可以在一个<template>
元素上使用v-slot
指令,并以v-slot
指令参数的形式提供其名称。
如上例所示<template>
元素中的所有内容都将会被传入响应的插槽。
注意:v-slot
只能添加在<template>
上
七、vue的useSlots( )
示例:
<script setup>
import { useSlots } from 'vue' //引入方式
const slots = useSlots() //使用方式
</script>
复制代码
实际应用:
<template>
<slot v-if="slotDefault" />
<div v-else>
<el-icon v-if="props.type==='image'||props.type==='video'">
<Plus />
</el-icon>
<el-button
v-else
type="primary"
>
<slot name="icon" /> //匿名插槽
<div class="el-upload__btn">
{{ props.btnText }}
</div>
</el-button>
</div>
</template>
<script setup>
import { useSlots } from 'vue' //引入方式
const slotDefault = !!useSlots().default; //使用方式
</script>
八、Vue3的生命周期
生命周期的概念理解:vue实例从创建、挂载、更新到销毁这一整个过程叫做生命周期。
类型
选项式API | 组合式API生命周期钩子(setup) | |
---|---|---|
beforeCreate | Not needed | |
created | Not needed | |
beforeMount | onBeforeMount | 注册一个钩子 ,在组件被挂载之前被调用 |
mounted | onMounted | 注册一个回调函数,在组件挂载完成后执行 |
beforeUpdate | onBeforeUpdate | 注册一个钩子 ,在组件即将因为响应式状态变更而更新其 DOM 树之前调用 |
updated | onUpdated | 注册一个回调函数,在组件因为响应式状态变更而更新其 DOM 树之后调用 |
beforeUnmount | onBeforeUnmount | 注册一个钩子 ,在组件实例被卸载之前调用 |
unmounted | onUnmounted | 注册一个回调函数,在组件实例被卸载之后调用 |
-
钩子:表示一个函数
-
组合式API(即setup() 内部)调用的生命周期钩子里是没有
beforeCreate
和created
函数的。
原因是:
setup
选项在组件被创建之前执行,不需要使用this,this不会指向示例。beforeCreate
和 created
能做的事情在 setup
也能实现。
setup
是围绕 beforeCreate
和 created
生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup
函数中编写。
生命周期执行示例
<template>
<div class="count">
<!-- 使用v-if来演示卸载页面元素 -->
<div v-if="isShow">
<el-tag :key="count">数量显示:{{ count }}</el-tag>
<el-button type="primary" size="small" @click="count++">加 1</el-button>
</div>
<el-button type="danger" size="small" @click="isShow = false"
>卸载</el-button
>
</div>
</template>
<script setup lang="ts">
import {ref,beforeCreate,created,onBeforeMount,onMounted,onBeforeUpdated,onUpdated,onBeforeUnmount,onUnmounted} from 'vue';
const count = ref(0);
const isShow = ref(true);
beforeCreate(()=>{ //无调用
console.log("beforeCreate");
});
created(()=>{ //无调用
console.log("created");
});
onBeforeMount(()=>{ //进入页面时触发调用
console.log("onBeforeMount开始调用");
});
onMounted(()=>{ //进入页面时触发调用
console.log("onMounted开始调用");
})
onBeforeUpdated(()=>{ //点击“加1”按钮时调用
console.log("onBeforeUpdated开始调用");
})
onUpdated(() => {
console.log("onUpdated 开始调用"); //点击“加1”按钮时调用
});
onBeforeUnmount(() => {
console.log("onBeforeUnmount 开始调用"); //点击“卸载”按钮时触发
});
onUnmounted(() => {
console.log("onUnmounted 开始调用"); //点击“卸载”按钮时触发
});
</script>
<style></style>
九、nextTick
使用nextTick
获取最新的 DOM 元素内容
示例:
<template>
<div ref="test">{{name}}</div>
<el-button @click="changeName">按钮</el-button>
</template>
<script setup>
import { ref, nextTick } from 'vue'
const name = ref("tom")
const test = ref(null) //test.value是个DOM元素
function changeName(){
name.value = 'Jack' //既希望名字发生改变的同时又获取到内容,给div定义一个ref
console.log(test.value.innerText) //获取DOM元素里的内容,加.innerText即可获取 tom
//当数据发生改变时,页面上视图重新渲染展示出的Jack,但实际上控制台拿到的数据还是tom
}
//拿到最新的渲染结果,引入nextTick
//将函数定义为异步函数
async function changeName(){
name.value = 'Jack'
console.log('before',test.value.innerText) //tom
await nextTick() //在nextTick异步执行完之后,再去打印,便能获取到最新的渲染结果
console.log('after',test.value.innerText) // Jack
}
return { name, test, handleClick }
</script>