本文主要介绍在使用过程中遇到的问题和知识点,开发环境是在vite2.0中,并且采用<script setup>语法糖进行开发
生命周期函数
Vue2.x 中含有8个生命周期函数:
-
beforeCreate
-
created
-
beforeMount
-
mounted
-
beforeUpdate
-
updated
-
beforeDestroy
-
destroyed Vue3中,新增了
setup生命周期函数,其执行时期是在beforeCreate之前,因此此函数中是不能通过this来获取实例,将beforeDestroy改名为beforeUnmount,destroyed改名为unmounted,总体来看Vue3的生命周期函数为: -
beforeCreate(建议使用setup代替)
-
created(建议使用setup代替)
-
setup
-
beforeMount
-
mounted
-
beforeUpdate
-
updated
-
beforeUnmount
-
unmounted 同时vue中的生命周期钩子是通过在生命周期函数前加
on来访问组件的生命周期,可以使用以下生命周期钩子: -
onBeforeMount
-
onMounted
-
onBeforeUpdate
-
onUpdated
-
onBeforeUnmount
-
onUnmounted
-
onErrorCaptured
-
onRenderTracked
-
onRenderTriggered
常用
相应式API
-
ref:主要处理基本数据结构,也是能处理对象和数组,在js中通过.value修改其值
-
reactive:主要负责复杂数据结构
-
toRef:将对象中的某个属性变为响应式数据,会影响原数据,但不会触发UI界面的更新
-
toRefs:类似与toRef,将对象中的所有属性变为响应式数据
响应式监听
- watch,引入:
import { watch } from 'vue'
2. ref定义的值
const test1 = ref(0);
watch(test1, (val, oldVal) => { console.log(val, oldVal, "watch"); });
test1.value++
// 1 0 watch
3. reactive定义的值
const test2 = reactive({ count: 0 });
//侦听时返回值得getter函数
watch(
() => test2.count,
(val, oldVal) => { console.log(val, oldVal, "watch"); }
)
test2.count++
// 1 0 watch
4. 将多个值放在一个数组中监听,返回值也是数组形式
const test1 = reactive({
count: 1,
});
const test2 = ref(2);
watch([() => test1.count, count], (newVal, oldVal) => { console.log(newVal, oldVal); });
test1.count = 3
//[3, 2] [1, 2]
test2.value = 4
//[3, 4] [3, 2]
5. 深度嵌套监听
const deepObj = reactive({ a: { b: { c: "1" } } })
watch(
() => _.cloneDeep(deepObj),
(val, old) => { console.log(val.a.b.c, old.a.b.c) },
{ deep: true }
);
deepObj.a.b.c = "2";
// 2 1, 注:如果不使用_.cloneDeep(deepObj)进行克隆那么打印结果为 2 2
6. 停止监听
const test = ref(0)
const stop = watch(test, (newVal, olVal) => { console.log(newVal, olVal); });
setTimeout(()=>{ test.value++ }, 1000);
stop(); // 停止watch
// 无打印
- 使用
export
// children
<script setup>
export const refresh = () => {
console.log("refresh");
}
</script>
// father
<template>
<Child ref="childRef" />
</template>
<script setup>
import { onMounted, ref } from "vue";
export { default as Child } from "./children.vue";
export const childRef = ref(null);
onMounted(() => {
childRef.value.refresh() // 打印: refresh
});
</script>
全局变量
以lodash为例子,定义全局变量使用globalProperties和$,使用全局变量需使用getCurrentInstance
注:据说ctx只在生产环境下可以,没试过欢迎尝试
// main.js中定义全局变量
app.config.globalProperties.$_= _
// .vue文件中
const { proxy, ctx } = getCurrentInstance();
onMounted(() => {
console.log(proxy.$_);
console.log(ctx.$_;
});
杂项
v-for和v-if优先级
Vue2.x中,v-for的优先级更高,所以官方不建议v-for和v-if一起使用
Vue3中,v-if比v-for的优先级更高
v-for和key
Vue2.x中,v-for循环需要给每个子节点一个唯一的key,还不能绑定在template标签上
而在Vue3中,key值可以直接写在template标签上,就不用每个子节点都设置key
v-model
在Vue2中,我们对父子组件传递基础数据进行双向绑定是通过 回调函数 或者 .sync 来实现
在Vue3中,可以通过v-model.msg1="msg1";v-model.msg2="msg2"的形式传递多个值进行双向绑定
补充
Teleport
它可以将插槽中的元素或者组件传送到页面的其他位置
<template>
<button @click="showDialog = true">打开遮罩层</button>
<teleport to="body">
<div v-if="showDialog" style="position: fixed">
我是一个遮罩
<button @click="showDialog = false">关闭</button>
</div>
</teleport>
</template>
<script setup>
const showDialog = ref(false)
const msg = ref("hello")
</script>
上面中的teleport中,会将div渲染到body的底部,虽然在DOM节点上脱离了父组件,但是其组件逻辑还是属于父组件,还是能和父组件通讯。Teleport接收两个参数to和disabled
-
to - string:必须是有效的查询选择器或 HTMLElement,可以id或者class选择器等。
-
disabled - boolean:如果是true表示禁用teleport的功能,其插槽内容将不会移动到任何位置,默认false不禁用。