vue3.0基础语法总结
vue3.0基础语法总结前言大家好!我叫椰_季,是一个刚入行不久得前端工程师,本着在提升自我学习能力为前提和认识一些前端方面得朋友为主要任务。准备发布一篇自己学习vue3.0基础语法的总结。学习途径来源于B站张天禹老师。vue2.0的一些缺陷我们先来说一说vue2.0存在的一些缺陷,大家都知道vue2.0中数据的代理方式是使用的defineProperty来实现响应式的。那么definePrope
vue3.0基础语法总结
前言
大家好!我叫椰_季,是一个刚入行不久得前端工程师,本着在提升自我学习能力为前提和认识一些前端方面得朋友为主要任务。准备发布一篇自己学习vue3.0基础语法的总结。学习途径来源于B站张天禹老师。
vue2.0的一些缺陷
我们先来说一说vue2.0存在的一些缺陷,大家都知道vue2.0中数据的代理方式是使用的defineProperty来实现响应式的。那么defineProperty存在什么样的问题呢
-
不能监听数组的变化
-
必须遍历对象的每个属性
-
必须深层遍历嵌套的对象
-
1、数据规模是否庞大。创建Vue实例的时候,一旦对象是一个深层的引用(老千层饼了),递归进行Observer的创建显然会花很多时间;
2、对所有属性的变化进行监听,也需要消耗不小的内存;
3、新增/删除属性的时候,怎么调用/卸载defineProperty;
4、vue2的官方文档,对开发者说明了defineProperty的一些限制,比如说数组在两种情况下是无法监听的:
1、利用索引直接设置一个数组项时,例如:arr[indexOfItem] = newValue;
2、修改数组的长度时,例如:arr.length = newLength;
当我们的项目需求变得更复杂时,watch,computed,inject,provide等配置,这个.vue文件也会逐渐增大
以上图片来源于花果山大圣,具体了解v2的option以及v3的composition,参考大圣这篇文章
vue3给我们带来了什么
一、性能的提升
- 打包大小减少了41%
- 初次渲染快55%, 更新渲染快133%
- 内存减少54%
二、源码的升级
- 使用Proxy代替defineProperty实现响应式
- 重写虚拟DOM的实现和Tree-Shaking
三、拥抱TypeScript
- Vue3可以更好的支持TypeScript
四、一些新特性 Composition API(组合API)
1、setup是Vue3.0中一个新的配置项,值为一个函数,setup是所有Composition API(组合API)表演的舞台
2、组件中所用到的:数据、方法等等,均要配置在setup中
3、若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用
此处需要将setup 中定义的值 return 返回出去,模板中才能使用
4、setup的一些注意点:
1、在vue3中是可以继续使用vue2中的语法的,但是官方不推荐这样使用。
2、Vue2.x配置(data、methos、computed...)中可以访问到setup中的属性、方法。但在setup中不能访问到Vue2.x配置(data、methos、computed...)。
3、如果有重名, setup优先。
4、setup执行的时机,在beforeCreate之前执行一次,this是undefined
5、setup的参数:
props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性
context:上下文对象
attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 `this.$attrs`
slots: 收到的插槽内容, 相当于 `this.$slots`
emit: 分发自定义事件的函数, 相当于 `this.$emit`
作用:定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
语法:const 代理对象 = reactive(源对象)接收一个对象(或数组),对象(proxy对象)
reactive定义的响应式数据是 深层次的
内部基于ES6的 Proxy实现,通过代理对象操作源对象内部数据进行操作
`
//reactvie处理对象是深层次的
let job2 = reactive({
type:'php',
salary:'40k'
})
let hobby = reactive(['吃饭','睡觉','写代码'])
function change(){
// name.value = "李四"
// age.value = 20
// job.value.type = "java工程师"
// job.value.salary = "30k"
// // 如果创建的对象是通过reactive创建的,那么修改直接通过对象.里面的属性就好,不需要像ref那样 多加一层.value
// job2.type = "go开发"
// job2.salary = "60k"
// console.log(name,age,job.value);
// 在vue3中 可以直接通过 这样修改
hobby[0] = '学习'
}
`
-
reactive对比ref
-
从定义数据角度对比:
- ref用来定义:基本类型数据。
- reactive用来定义:对象(或数组)类型数据。
- 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过
reactive
转为代理对象。
-
从原理角度对比:
- ref通过
Object.defineProperty()
的get
与set
来实现响应式(数据劫持)。 - reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
- ref通过
-
从使用角度对比:
- ref定义的数据:操作数据需要
.value
,读取数据时模板中直接读取不需要.value
。 - reactive定义的数据:操作数据与读取数据:均不需要
.value
。
- ref定义的数据:操作数据需要
-
computed
与Vue2.x中computed配置功能一致
`import { reactive, computed } from “vue”;
setup() {
let person = reactive({
name: “张三”,
finame: “狂徒”,
});// 计算属性的简写形式,是只读的没有考虑修改
// person.quanc = computed(() => {
// return person.name + “-” + person.finame;
// });
person.quanc = computed({
get() {
// 用户读取数据
return person.name + “-” + person.finame;
},
set(value) {
// 这里获取的value是有 - 的 通过截取-将值拆分成数组,然后再进行 索引的第0 和第 1 个获得对应的姓 和名
const qwe = value.split(“-”);
person.name = qwe[0];
person.finame = qwe[1];
},
});
return {
person,
};
},
`
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
},{immediate:true})
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log('sum或msg变化了',newValue,oldValue)
})
/* 情况三:监视reactive定义的响应式数据
若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!!
若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
*/
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效
//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//情况五:监视reactive定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//特殊情况
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
如果都是利用ref创建的,利用watch来监视的话。基本类型的值 直接在第一个参数内传入定义的变量名。
如果是对象类型的话:
一、可以在变量名的后方加上.value 那么v3中他内部会借助reactive 来实现深层次监听。
二、可以不添加.value ,可以在第三个参数内加上deep:true也可以开启深度监听
watch的套路是:既要指明监视的属性,也要指明监视的回调
watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那么它就监视哪个属性
watchEffect有点像computed:
但是computed注重的是计算出来的值(回调函数的返回值),所以必须要写返回值
而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
import { ref, watch, reactive, watchEffect } from "vue";
setup() {
let qwe = ref(0);
let www = ref("你哈");
let person = reactive({
name: "张三",
age: 18,
fn: {
j1: {
st: 20,
},
},
});
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(() => {
let f1 = qwe.value;
let f2 = person.fn.j1.st;
console.log("haha");
});
return {
qwe,
www,
person,
};
},
}
setup(){
//数据
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})
const x = toRefs(person)
console.log('******',x)
//返回一个对象(常用)
// 一般我们要将响应式对象中的某个属性单独提供给外部使用时使用toRef
return {
person,
// name:toRef(person,'name'),
// age:toRef(person,'age'),
// salary:toRef(person.job.j1,'salary'),
...toRefs(person)
}
}
}
五、新的内置组件
-
Fragment
- 在Vue2中: 组件必须有一个根标签
- 在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
- 好处: 减少标签层级, 减小内存占用
-
Teleport
- 主要就是用在类似遮罩弹框这种,可以在子组件控制逻辑,但是DOM对象却是在body下的这种效果,能够将我们的组件html结构移动到指定位置的技术。
- Teleport就是一种将代码组织逻辑依旧放在组件中,这样我们能够使用组件内部的数据状态,控制组件展示的形式,但是最后渲染的地方可以是任意的,而不是局限于组件内部
<div id="hell">
</div>
<teleport to="#hell">
<div v-if="isShow" class="mask">
<div class="dialog">
<h3>我是一个弹窗</h3>
<button @click="isShow = false">关闭弹窗</button>
</div>
</div>
</teleport>
- Suspense
- 等待异步组件时渲染一些额外内容,让应用有更好的用户体验
- 异步引入组件
```
import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
```
- 使用Suspense包裹组件,并配置好default 与 fallback
<template>
<div class="app">
<h3>我是App组件</h3>
<Suspense>
<template v-slot:default>
<Child/>
</template>
<template v-slot:fallback>
<h3>加载中.....</h3>
</template>
</Suspense>
</div>
</template>
总结
学习是一辈子的事,不光指学习计算机技术,生活的方方面面都需要保持一个学习的心,祝大家学习愉快。
第一次总结写文章,文中如有错误,欢迎码友在评论区指正。
更多推荐
所有评论(0)