VUE3与VUE2区别 在VUE3+vite2+ <script setup>中的使用心得总结

292 阅读1分钟

本文主要介绍在使用过程中遇到的问题和知识点,开发环境是在vite2.0中,并且采用<script setup>语法糖进行开发

生命周期函数

Vue2.x 中含有8个生命周期函数:

  • beforeCreate

  • created

  • beforeMount

  • mounted

  • beforeUpdate

  • updated

  • beforeDestroy

  • destroyed Vue3中,新增了setup生命周期函数,其执行时期是在beforeCreate之前,因此此函数中是不能通过this来获取实例,将beforeDestroy改名为beforeUnmountdestroyed改名为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

  1. ref:主要处理基本数据结构,也是能处理对象和数组,在js中通过.value修改其值

  2. reactive:主要负责复杂数据结构

  3. toRef:将对象中的某个属性变为响应式数据,会影响原数据,但不会触发UI界面的更新

  4. toRefs:类似与toRef,将对象中的所有属性变为响应式数据

响应式监听

  1. 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

// 无打印

  1. 使用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-ifv-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接收两个参数todisabled

  • to - string:必须是有效的查询选择器或 HTMLElement,可以id或者class选择器等。

  • disabled - boolean:如果是true表示禁用teleport的功能,其插槽内容将不会移动到任何位置,默认false不禁用。