Vue3新增的知识
本文默认你已经掌握了Vue2所有知识,从而让你了解Vue2到Vue3的改变
Vue3特点
- 新增组合API。作用:可有更好的逻辑复用和代码组织;统一功能的代码不再像Vue2那样分散,虽然Vue2可以用mixin来实现复用代码,但是也存在问题;比如:方法或者属性名冲突;代码来源不清楚等
- 用Proxy代替Object.defined=Property重构了响应系统,可以监听到数组下标变化以及对象新增属性。因为监听的不是对象属性而是对象本身;还可以拦截apply、has等13种方法
- v-if和v-for优先级已经更改,但是仍然不推荐同时使用
- 新增了setup生命周期钩子,setup代替了Vue2的beforeCreate、created两个生命周期时机,其他的,例如:mounted等钩子函数,使用时需要加on前缀,即是onMounted
- 使用props或者时emits需要使用defineProps()、defineEmits()进行接收声明
- 新增了三个组件:Fragment支持多个根节点;Suspense可以在组件渲染之前的等待时间显示指定内容;Teleport可以让子组件能够在视觉上跳转父组件
- 新增指令v-memo,可以缓存html模板;使用内存换取渲染时间
- 重构了虚拟DOM,
- 支持在style使用v-bind,给CSS绑定js变量;
- 全局函数set、delete以及实例方法 s e t 、 set、 set、delete移除
- o n , on, on,off和$once实例方法移除
- 不再支持IE11
Vue3中响应式数据的使用
- ref()实现数据双向绑定
// 1、 基本类型使用ref 此时0就是num的初始值,且是响应式的
let num = ref(0)
// 在Vue模板中使用num
{{num}}
// 在脚本中使用num
num.value
// 2、引用类型使用ref
let zhw = ref({
name : 'zhw',
age : 18
});
// 在Vue模板中使用
{{zhw.name}}
// 在脚本中使用
zhw.value.name
**注意:**一般项目开发中,ref只用于实现基本数据类型的响应式
- reactive() 实现数据绑定
// reactive只用于实现引用数据类型的响应式
let zhw = reactive({
name : 'zhw',
age : 18
});
// 在Vue模板中使用
{{zhw.name}}
// 在脚本中使用
zhw.value.name
一般项目开发中,是如何使用响应式数据的呢?
// 1、把当前组件所有用到的响应式数据,包括基本数据类型和复杂数据类型
// 都放在state对象中
const state = reactive({
num : 0,
zhw : {
name : 'zhw',
age 18
}
})
// 使用toRefs解构,让解构后的也是响应式
const {num,zhw} = toRefs(state);
// 在Vue模板中使用
{{zhw.name}}---{{num}}
// 在脚本中使用
zhw.value.name
Vue3的响应式原理Proxy
let zhw = {
name : 'zhw',
age : 18
};
// new Proxy 创建了参数一zhw 的代理对象
// 该代理对象上的属性和属性值 和 被代理对象一样
let zhwProxy = new Proxy(zhw,{
// 访问zhwProxy 代理对象的属性时执行 zhwProxy.name
// target : 被代理对象
// prop :访问的属性
get(target,prop) {
return target[prop]
},
// zhwProxy.name = value 时执行
sat(target,prop,value) {
target[prop] = value
}
})
Vue3中获取DOM元素对象或者组件实例
- 使用ref获取
// Vue模板中
<p ref='myRef'>ref测试<p>
// 脚本中
// 注意1、这里的变量需要和模板中的ref属性值保持一致 都是myRef
let myRef = ref();
// setup里的代码执行时期 相当于Vue2的beforeCreate created,所以不能直接获取DOM元素
// 需要使用nextTick 或者 onMounted 获取DOM
// 在下一次DOM更新的时候执行,只会调用一次
nextTick(()=>{
// 因为myRef初始值被ref包裹,所以需要value
console.log(myRef.value)
})
// 如果以上代码不是写在setup语法糖里,则最后还需要return
return {
myRef
}
setup语法糖
setup语法糖格式如下:
<script setup> //加上setup:script之间的代码,会被Vue内部自动添加到原先的setup方法中
// 之前写在setup()钩子的内容,都可以直接写在这块,且不用return
</script>
观察者:Vue3中的数据监听watch
import {watch,watchEffect} from 'vue';
// watch(要监听的响应式数据,数据更新时执行的回调)
// 在页面刷新的时候,立即监听,相当于Vue2中的immediately属性
watchEffect(要监听的响应式数据,数据更新时执行的回调)
计算属性
import {computed} from 'vue';
// computed返回值就是计算属性的值,接受返回值之后,可以直接在模板使用
const val = computed(()=>{
return 处理过的值
})
Vue3中的组件传值
一、父组件给子组件传值
// 父组件中
<Child :msg="msg"/>
import Child from '子组件所在的位置'
let msg = ref('我是父组件')
// 子组件中
const props = defineProps<{
msg : string
}>()
// 模板中使用
{{props.msg}}
二、子组件给父组件传值
// 父组件中
<Child @autoEvent="fn"/>
import Child from '子组件所在的位置'
const fn = (msg) => {
console.log(msg) // 我是子组件
}
// 子组件中
<button @click="forFather">给父组件传值</button>
const emit = defineEmits<{
(event:'autoEvent',msg:string) : void
}>()
// 点击按钮 触发方法
const forFather = ()=> {
emit('autoEvent','我是子组件')
}
插槽:作用域父子组件
一、匿名插槽
// 父组件中
import Child from '子组件所在的位置'
<Child>
// 填充插槽的内容
// 匿名插槽不需要template
<p>我是匿名插槽的显示者</p>
</Child>
// 子组件Child中
<div>
<slot></slot>
</div>
二、具名插槽
v-slot:zhw是写在template上的,他的语法糖是:#zhw
// 父组件中
import Child from '子组件所在的位置'
<Child>
// 填充插槽的内容
<template v-slot:zhw>
<p>我是名字为zhw插槽的显示者</p>
</template>
<template #whl>
<p>我是名字为whl插槽的显示者</p>
</template>
</Child>
// 子组件Child中
<div>
<slot name="zhw"></slot>
<slot name="whl"></slot>
</div>
三、作用域插槽
插槽的作用域:在父组件中的子组件标签内部操作子组件数据
// 父组件中
import Child from '子组件所在的位置'
<Child>
// 填充插槽的内容
// 这里的scope是自定义的,用来收集子组件内部slot上所有的标签属性的值,除了name属性
<template #zhw="scope">
<p>我是子组件的tit:{{scope.tit}}</p>
</template>
</Child>
// 子组件Child中
<div>
<slot name="zhw" tit="我是子组件"></slot>
</div>
更换Vue模板插件
之前在Vue2中,使用的是Vetur插件,使得Vue模板代码高亮; 现在,在Vue3中,应该禁用Vetur插件,从而使用Volar,即是Vue Language Features,从而使得Vue模板代码高亮