Vue3和Vue2的一些区别
目录
一、main.js文件的不同
我们先分析vue3里main.js文件
注意:vue3的main.js里面不能再写vue2的写法了。
保险起见,还是将Vue3的完整main.js代码贴在这里
二、app.vue组件的不同
我们首先打开一个崭新的vue3 app.vue文件
我们可以清晰的看到<template>标签下没有根div,也就是说:
<vue3组件中的模板标签可以没有根标签>
但是,为了给组件加上样式,我们还是习惯于写上根标签
三、添加了新的配置项——setup
setup是所有组合式api(composition API)表演的舞台
他的值是一个函数
- 组件中的数据(data)、方法(methods)、生命周期等都要配置在setup中
- setup函数的返回值有两种情况:返回一个对象,返回一个渲染函数
- 返回一个对象时,对象里面的东西可以再模板函数里面不加this直接使用(重点关注)
- 返回一个渲染函数时,可以自定义渲染函数的内容(仅作了解)
我们对app.vue文件做如下修改
<template>
<h1>一个人的信息</h1>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<button @click="sayHello">说话</button>
</template>
<script>
export default {
name: 'App',
setup(){
// 再setup里面直接写数据和方法
// 数据
let name = '张三'
let age = 18
//方法
function sayHello(){
alert(`我叫${name}, 我今年${age}岁了,你好啊!`)
}
return {
name,
age,
sayHello
}
}
}
</script>
这里面就可以看出setup函数的基本用法,注意alert里面的既不是单引号也不是双引号,
注意点:
- vue2的配置不要和vue3混用,会出现问题:
-
- vue2的配置中可以访问到setup的属性和方法
- 但Vue3的setup配置中不能访问到Vue2的配置(data、methods、computed等)
- 如果Vue2和Vue3的属性名字有重名的,以vue3配置的数据优先
- setup函数不能是一个async函数,因为返回值不再是return的对象,而是promise,模板函数看不到return对象中的属性
四、ref函数
在上一节中,我们这样定义属性:
这不是一个响应式的属性定义方式,如果我们此时用一个函数修改name和age的值,值可以修改,但是页面不会渲染更新之后的内容
使用ref需要先引入
import {ref} from 'vue'
ref封装好的属性会变成一个对象,
这个对象叫做引用实例的实现对象,我们的属性值并不是直接通过对象名字访问的,而是要 对象名.value 访问
但是在模板函数里面 Vue3会帮我们自动.value,所以模板函数里面还是跟原来的差值表达式一样
请看响应式代码
<template>
<h1>一个人的信息</h1>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<button @click="changeInfo">改变内容</button>
</template>
<script>
import {ref} from 'vue'
export default {
name: 'App',
setup(){
// 再setup里面直接写数据和方法
// 数据
let name = ref('张三')
let age = ref(18)
function changeInfo(){
name.value = '李四'
age.value = 48
console.log(name,age);
}
return {
name,
age,
changeInfo
}
}
}
</script>
用ref处理对象的信息,几乎没什么特别的
就不再赘述了
五、reactive函数
在上一节中,我们使用ref函数时们需要不停的使用.value来访问
现在,对于对象数据类型,我们可以使用reactive替换ref, 当然之前还需要引入
在后面访问的时候就不需要加上.value了
我们使用reactive处理数组来简单的示范下
1.先引入
2.给数组添加响应式
3.在setup函数中return给模板函数
4.在函数中修改
优雅,实在是太优雅了
尽管reactive处理数组和对象非常轻松,但是它不能处理基本数据类型(Number, String 等)
解决方法
把所有的数据都封装在一个类里面,面向对象式的存储数据
六、Vue3里面的响应式使用
尚硅谷的老师详细讲解了Vue3的响应式原理以及他和Vue2的不同,方便以后查阅,这里只给出连接
在vue3里面,基本数据类型的响应式的使用使用跟vue2没有太大的差别,但是对于数组和对象数据,Vue3的使用方法比vue2要更加简单。
代码
<template>
<h1>一个人的信息</h1>
<h3 v-show="person.name">姓名:{{ person.name }}</h3>
<h3>年龄:{{ person.age }}</h3>
<h3 v-show="person.sex">性别:{{ person.sex }}</h3>
<h3>爱好: {{ hobby }}</h3>
<button @click="addSex">添加性别属性</button>
<button @click="deleteName">删除name属性</button>
<button @click="changeInfo">改变内容</button>
</template>
<script>
import {reactive} from 'vue'
export default {
name: 'App',
setup(){
//reactive给对象数据添加响应式
let person = reactive({
name : '张三',
age : 18
})
//用ref处理对象信息
let job = reactive({
type:'前端工程师',
salay:"30K"
})
// reactive处理数组属性
let hobby = reactive(['抽烟','喝酒','烫头'])
// 方法
function changeInfo(){
hobby[0] = '学习'
}
function addSex(){
person.sex = '男'
}
function deleteName(){
// 从对象里面删除属性
delete person.name
}
return {
person,
job,
hobby,
addSex,
deleteName,
changeInfo
}
}
}
</script>
七、setup函数的注意事项
1.setup函数的执行时间
setup函数的会在beforeCreate生命周期函数之前执行一次,此时this的值时undefined
也就是说,在setup函数里面,我们不能通过this访问到任何东西
2.setup函数的参数
setup函数可以接受两个参数,
- 第一个参数时props对象,用于接收父组件传递过来的数据,单数props对象必须先调用
我们先演示第一个参数:在传递给setup函数之前必须先接收
页面控制台:
这就证明props传递进来的数据是响应式的
接下来演示第二个参数
值得注意的是,在vue3里面,对于具名插槽,我们使用 v-slot:而不是#或者slot="",这只是一个API兼容的问题
我们先从自定义事件开始说起
在App.vue组件里面
在Demo_1.vue组件里面
<template>
<h1>一个人的信息</h1>
<h3 v-show="person.name">姓名:{{ person.name }}</h3>
<h3>年龄:{{ person.age }}</h3>
<h3 v-show="person.sex">性别:{{ person.sex }}</h3>
<h3>爱好: {{ hobby }}</h3>
<button @click="addSex">添加性别属性</button>
<button @click="deleteName">删除name属性</button>
<button @click="changeInfo">改变内容</button>
</template>
<script>
import {reactive} from 'vue'
export default {
name: 'App',
setup(){
//reactive给对象数据添加响应式
let person = reactive({
name : '张三',
age : 18
})
//用ref处理对象信息
let job = reactive({
type:'前端工程师',
salay:"30K"
})
// reactive处理数组属性
let hobby = reactive(['抽烟','喝酒','烫头'])
// 方法
function changeInfo(){
hobby[0] = '学习'
}
function addSex(){
person.sex = '男'
}
function deleteName(){
// 从对象里面删除属性
delete person.name
}
return {
person,
job,
hobby,
addSex,
deleteName,
changeInfo
}
}
}
</script>
注意context组件的写法,context.emit('hello',666);后面是传递的参数
在看vue3组件里面的插槽,这里以具名插槽为例
在Demo.vue组件里面
在App.vue组件里面
具体的使用方法跟vue2没有太大的差别
至于第一项,个人感觉意义不大,毕竟父组件传递参数我们都是要写props来接收的。
八、computed计算属性
跟Vue2的原理基本相同,用法请看代码,不再赘述
<template>
<h1>一个人的信息</h1>
姓:<input type="text" v-model="person.firstName"><br>
名:<input type="text" v-model="person.lastName"><br>
<span>全名:{{ fullName }}</span><br>
全名:<input type="text" v-model="person.fullName">
</template>
<script>
import {computed,reactive} from 'vue'
export default {
name: 'Demo_1',
setup(){
let person = reactive({
firstName:'张',
lastName:'三'
})
//计算属性
//简写版,不考虑计算属性被修改的情况
// person.fullName = computed(()=>{
// return person.firstName + '-' + person.lastName
// })
//完整版,计算属性被修改了还可以返回去渲染
person.fullName = computed({
get(){
return person.firstName + '-' + person.lastName
},
set(value){
const NameArr = value.split('-')
person.firstName = NameArr[0]
person.lastName = NameArr[1];
}
})
return {
person,
}
}
}
</script>
get和set实现响应式的原理需要注意
九、watch监视函数
在Vue3中,watch监视函数也是一个组合式API(使用前需先调用),这个函数有三个参数
- 第一个参数是监视的元素
- 第二个参数是监视的回调
- 第三个参数是监视的配置
1.watch监视ref定义的基本数据类型
先简单看一下代码:
<template>
<div>
<h3>count的值为:{{ count }}</h3>
<button @click="count += 1">点我增加count的值</button>
<button @click="count -= 1">点我减少count的值</button>
<hr>
<h3>此时的数据为:{{ msg }}</h3>
<button @click="msg += '!'">点击修改数据</button>
</div>
</template>
<script>
import { ref,watch } from 'vue'
export default{
setup(){
//数据
let count = ref(0)
let msg = ref('你好啊')
//watch监视
//因为setup里面没有this,所以我们用回调函数
//watch函数第一个参数是监视的元素,第二个参数是监视的回调,第三个参数是监视的配置
//情况一,监视ref所定义的响应式数据
// watch(count,(NewValue,OldValue)=>{
// console.log(`count的值变了,新值为${NewValue},旧值为${OldValue}`);
// })
//情况二,监视ref定义的多个数据,同时监视多个数据的变化
watch([count,msg],(NewValue, OldValue)=>{
// console.log(`count或msg的值变了,新值为${NewValue},旧值为${OldValue}`);
console.log("count或msg的值变了",NewValue, OldValue);
},{immediate:true})
return{
count,
msg
}
}
}
</script>
跟vue2不同的是,Vue3里面的watgch函数可以不断的被调用,也就是说,在监视多个元素时,我们不仅可以写成数组的形式,还可以直接写还几个watch函数
2.watch监视reactive定义的对象和数组类型
watch监视reactive定义的数据时会出现两个bug,
- watch不能正确的获得OldValue的值,目前这个bug无法解决。
- watch强制开启深度监听,也就是deep配置无效
我们只看第一个bug
我们还是直接看代码、
<template>
<div>
<h3>姓名: {{ person.name }}</h3>
<h3>年龄:{{ person.age }}</h3>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">修改年龄</button>
</div>
</template>
<script>
import { reactive,watch } from 'vue'
export default{
setup(){
//数据
let person = reactive({
name:'张三',
age:18
})
watch(person,(NewValue,OldValue)=>{
console.log("person的值变了",NewValue,OldValue);
})
return{
person
}
}
}
</script>
加入我们要是想单独监视对象里面的某一个属性怎么办呢?
聪明的小伙伴也许已经想到应该怎么办了
但是如果这样写,vue会报出一个警告
并且我们修改age的值时watch也没有监听到
我们应该把这玩意写成一个函数。
这样就成了
3.watchEffect智能监视(Vue3里面新添加的)
watchEffect函数也是一个组合式的api,它不需要指定监视的对象,在他的回调函数里面用了谁他就监视谁,在实际操作中非常方便
简单演示一下
请看下列说明
十、生命周期
在Vue3里面的生命周期钩子既可以写配置项(跟Vue2里面一样),也可以写成组合式API(写在setup 里面)
但是组合式API的优先级更高
具体的跟vue2的差不多,用的也少,所以就不再赘述了.
图示
十一、toRef函数
vue3里面非常重要的一个API
先看问题:
我们在实现上面几节的代码时,总觉得 person. 写起来很繁琐
所以我们可以在return时对数据做一些处理
我们的意思是在return里面将 person. 写完,在模板函数里面就不用写了。
可是,这样一下,我们发现模板函数里面的响应式功能没了,这是为什么呢?
仔细一想不难发现,我们给name赋值,只是将一串字符串赋值给一个变量而已,跟person里面的属性没有半毛钱关系,也就是说上面的写法就相当于:
我们对name、age、salay变量做修改,根本不会影响到person里面的属性值,这就是页面不渲染响应式的原因
解决办法,那肯定是要使用我们的toRefAPI了
附上完整代码
<template>
<h3>一个人的信息</h3>
<h3>姓名:{{ name }}</h3>
<h3>年龄:{{ age }}</h3>
<h3>薪资:{{ salay }}K</h3>
<hr>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="salay++">涨薪</button>
</template>
<script>
import { reactive, toRef } from 'vue'
export default{
setup(){
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salay:20
}
}
})
return {
//使用toRef关键字就可以解决问题
name: toRef(person,'name'),
age : toRef(person,'age'),
salay : toRef(person.job.j1,'salay')
}
}
}
</script>
关于这个API的原理,尚硅谷有很详细的解释
有时候我们需要展出的数据很多,一个一个写又很麻烦了。所以出现了toRefs
值得注意的是,这里的展开只有一层,也就是模板函数里面的salay要这样写
也很方便
十二、其他组合式API
1.shallowReactive
顾名思义,这个就是浅层次的reactive
他只确保第一层响应式数据,对于第一次数据里面有对象或数组的,对象或数组里面的属性值就不是响应式的
2.shallowRef
跟上面的shallowReactive一样
当传入的是基本数据类型的时候,shallowRef和ref没有区别,但是当传入的是对象或数组类型的时候,shallowRef不做处理
也就是:shallowRef不处理对象或数组类型
3.readonly和shallowreadonly
readonly是只读的意思,有点类似于const将变量保护起来,不让别人对变量做修改。
可以看看控制台的警告
readonly是深层次的保护,不管是基本数据类型还是对象、数组,只要是再readonly的包裹下都不允许做修改
shallowReadonly是浅层次的保护,对于对象或数组的属性值shallowReadonly不做处理
4.toRaw和markRaw
- toRaw把某个·数据从响应式转化为不是响应式(将响应式的数据还原为其原始的数据)
- markRaw把某个数据标记为非响应式,使其永远也不能成为响应式数据
注意:
- toraw只能处理reactive定义的响应式对象,若是处理ref定义的数据,会变成undefined
十三、vue3里面新的组件
1.fragment组件
原谅孩子太多了敲不下去了~~~
也就是说,vue3自带一个根标签叫做frangment,可以节省空间,提高效率
2.Teleport传送组件
这是我个人很喜欢的一个组件,使用它可以实现弹窗+遮罩层的效果。在很多UI组件库里面也用到了
这个组件的应用我写了另外的一篇博客,请大家移步:
(1条消息) 使用VUE3+teleport组件实现遮罩层和弹窗效果_CTGU_ 21_ emo~~~~的博客-CSDN博客_vue遮罩效果
希望和大家共勉,最后祝大家程序员节快乐~~~~
更多推荐
所有评论(0)