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

本文主要介绍作者在使用过程中遇到的问题和知识点,开发环境是在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. watchEffect
    watchEffect 不需要指定监听的属性,他会自动的收集依赖, 只要我们回调中引用到了 响应式的属性, 那么当这些属性变更的时候,这个回调都会执行。watch可以获取到新旧值,而watchEffect不行

props

使用props需要引用defineProps来定义,用法跟Vue2.xprops写法相似:

<script setup>
import { defineProps } from "vue";
const props = defineProps(['text1', 'object1']);
// 定义类型
const props = defineProps({
  text1: String,
  object1: {
      type: Object,
      default: null
  }
})
</script>

emits

使用emits需要引用defineEmits来定义,用法跟Vue2.xemits写法相似:

const emit = defineEmits(['clickFun'])
emit('clickFun', 'params')

context

上下文通过useContext来获取

import { useContext } from 'vue'
const { slots, attrs } = useContext()

异步组件

在Vue2.x中异步组件的写法为:

AsyncComponent: () => import("../components/AsyncComponent.vue"),

在Vue3中需要引入defineAsyncComponent来进行定义:

import { defineAsyncComponent } from "vue";
AsyncComponent: defineAsyncComponent(() => import("../components/AsyncComponent.vue"))

在Vue3中可以对异步组件进行更加细致的设置:

import { defineAsyncComponent } from "vue";
AsyncComponent: defineAsyncComponent(() => {
      delay: 100,
      timeout: 3000,
      loader: () => import("../components/defineAsyncComponent.vue"),
      errorComponent: ErrorComponent,
      onError(error, retry, fail, attempts) {
        if (attempts <= 3) {
          retry();
        } else {
          fail();
        }
      },
    })

如果需要使用resolvereject

const asyncComponent = defineAsyncComponent(
  () => new Promise((resolve, reject) => {
      /* ..todo.. */
  })
)

组件加载

对于异步组件在加载时,我们可以有一些后备的内容用于加载中的渲染fallback

<template>
  <div>
    <button @click="showButton">展示异步组件</button>
    <template v-if="isShowButton">
      <Suspense>
        <template #default>
          <AsyncComponent></AsyncComponent>
        </template>
        <template #fallback>
          <div>组件加载中...</div>
        </template>
      </Suspense>
    </template>
  </div>
</template>

$ref

在Vue3中已经没有了this,那么如何使用$ref,父组件如何调用子组件中的方法,注:以下方案是在setup语法糖中

  1. 子组件需defineExpose导出
// children
<script setup>
  import { defineExpose } from "vue"
  const refresh = () => {
  console.log("refresh");
  }
  defineExpose({
    refresh
  })
</script>
// father
<template>
  <children ref="childRef"/>
</template>
<script setup>
  import { onMounted } from "vue";
  import children from "./children.vue"
  ref: childRef = null
  onMounted(()=>{
    childRef.refresh();  // 打印: refresh
  })
</script>
  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不禁用。
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值