vue3带来的新变化
-
性能提升
-
首次渲染更快
-
diff算法更快
-
内存占用更少
-
打包体积更小
-
更好的typescript支持
-
Composition API(组合式api)
在使用vue2.*版本开发逻辑复杂的组件时,逻辑难以复用,组合式api解决了这个问题
vue3破坏性语法更新
1.实例方法$on移除(eventBus)现有实现模式不在支持,可以使用第三方插件实现
2.过滤器filter移除(差值表达式不能在使用过滤器。可以用methods替代)
3…sync语法移除(和v-model合并)
组合式api
1.compostition vs options
1)options API开发出来的vue应用如左图所示,它的特点是理解容易,因为各个选项都有固定的书写位置,比如响应式数据就写到data选择中,操作方法就写到methods配置项中等,应用大了之后,相信大家都遇到过来回上下找代码的困境
2)composition API开发的vue应用如右图所示,它的特点是特定功能相关的所有东西都放到一起维护,比如功能A相关的响应式数据,操作数据的方法等放到一起,这样不管应用多大,都可以快读定位到某个功能的所有相关代码,维护方便,设置如果功能复杂,代码量大,我们还可以进行逻辑拆分处理
特别注意
1.选项式api和组合式api俩种风格是并存的关系 并不是非此即彼
2.需要大量的逻辑组合的场景,可以使用compition API进行增强
setup入口函数
1.setup 函数是一个新的组件选项,作为组件中组合式API 的起点(入口)
2.从生命周期角度来看,setup 会在 beforeCreate 钩子函数之前执行
3.setup 中不能使用 this, this 指向 undefined
下面我们来验证一下
验证代码
export default {
setup(){
console.log('setup执行了');
console.log(this);
},
beforeCreate () {
console.log('beforeCreate执行了');
console.log(this);
}
}
响应式系统api
1.reactive 函数
作用:reactive是一个函数,接收一个普通的对象传入,把对象数据转化为响应式对象并返回
使用步骤:
1.从vue框架中导入reactive函数
2.在setup函数中调用reactive函数并将对象数据传入
3.在setup函数中把reactive函数调用完毕之后的返回值以对象的形式返回出去
代码验证
<template>
<div>
<div>{{userInfo.username}}</div>
<div>{{userInfo.age}}</div>
<button @click="userInfo.username='ls'">修改名字</button>
<button @click="userInfo.age=25">修改年龄</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
setup(){
const userInfo=reactive({
username:'zs',
age:18
})
return {userInfo} //注意必须得return出去 不然模板里不能使用
}
}
</script>
<style>
</style>
2.ref函数
作用:ref是一个函数,接受一个简单类型或者复杂类型的传入并返回一个响应式且可变的 ref 对象
使用步骤
1.从vue框架中导出ref函数
2.在setup函数中调用ref函数并传入数据(简单类型或者复杂类型)
3.在setup函数中把ref函数调用完毕的返回值以对象的形式返回出去
4.注意:在setup函数中使用ref结果,需要通过.value 访问,模板中使用不需要加.value
代码验证
> <template>
<div>
<span>{{age}}</span>
<button @click="changeAge">修改年龄</button>
</div>
</template>
<script>
import {ref} from 'vue'
export default {
setup(){
const age =ref(18)
//修改年龄的方法
function changeAge(){
//如果想在方法里修改ref的值 必须加value
age.value=20
}
return {age,changeAge}
}
}
</script>
总结:1.ref 函数可以接收一个简单类型的值,返回一个可改变的 ref 响应式对象,从而弥补reactive函数不支持简单类型的问题
2.reactive和ref函数都可以提供响应式数据的转换,具体什么时候需要使用哪个API社区还没有最佳实践,大家暂时可以使用自己熟练的API进行转换
3.推荐一种写法:只有我们明确知道要转换的对象内部的字段名称我们才使用reactive,否则就一律使用ref,从而降低在语法选择上的心智负担
3.toRefs函数
经过reactive函数处理之后返回的对象,如果给这个对象解构或者展开,会让数据丢失响应式的能力,为了解决这个问题需要引入toRefs函数,使用 toRefs函数 可以保证该对象展开的每个属性都是响应式的
修改前
<template>
<div>{{ state.name }}</div>
<div>{{ state.age }}</div>
<button @click="state.name = 'ls'">改值</button>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const state = reactive({
name: 'zs',
age: 18
})
return {
state
}
}
}
</script>
修改后
<template>
<div>{{ name }}</div>
<div>{{ age }}</div>
<button @click="name = 'ls'">改值</button>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
const state = reactive({
name: 'zs',
age: 18
})
return {
...state
}
}
}
</script>
点击按钮修改的时候发现数据不是响应式的了
这就是我们所说的,如果解构reactive的返回值,将破坏调用响应式特性,就需要我们使用toRefs方法进行处理了
用toRefs修改后
<template>
<div>{{ name }}</div>
<div>{{ age }}</div>
<button @click="name = 'ls'">改值</button>
</template>
<script>
import { reactive,toRefs } from 'vue'
export default {
setup() {
const state = reactive({
name: 'zs',
age: 18
})
return {
...toRefs(state)
}
}
}
</script>
总结:如果想要在模板中省略对象名,直接使用属性名访问数据,可以使用toRefs包裹使用
4.computed
作用:根据现有响应式数据经过一定的计算得到全新的数据
1.使用步骤:从vue框架中导入computed 函数
2.在setup函数中执行computed函数,并传入一个函数,在函数中定义计算公式
3.把computed函数调用完的执行结果放到setup的return值对象中
代码验证
<template>
<div>
<div>原始数组:{{list}}</div>
<div>计算属性处理后的数组:{{filterList}}</div>
<button @click="addList">添加数据</button>
</div>
</template>
<script>
import { computed, ref } from 'vue'
//引入computed 和ref
// import {computed ,ref} from 'vue'
export default {
setup(){
const list =ref([1,2,3,4,5,6])
function addList(){
list.value.push(7,8,9,5)
}
const filterList = computed(()=>{
//注意list后一定要加value 因为使用了ref
return list.value.filter(item=>item>3)
})
return{list,filterList,addList}
}
}
</script>
计算属性特性:
1.依赖的值变化后,会立即进行求值
2.缓存特性
5.watch属性
作用:基于响应式数据的变化执行回调逻辑,和vue2中的watch的功能完全一致
1.普通监听
2.立即执行
3.深度监听
使用步骤
1.从vue框架中导入watch函数
2.在setup函数中执行watch函数开启对响应式数据的监听
3.watch函数接收三个常规参数
(1)第一个参数为函数,返回你要监听变化的响应式数据
(2)第二个参数为响应式数据变化之后要执行的回调函数
(3)第三个参数为一个对象,在里面配置是否开启立刻执行或者深度监听
简单的监听代码
<template>
<div>
{{age}}
<button @click="age++">点击自增</button>
</div>
</template>
<script>
import {watch,ref} from 'vue'
export default {
setup(){
const age = ref(18)
watch(()=>{
// 返回你想要监听的响应式属性(ref产生的对象必须加.value)
return age.value
},
()=>{
// 数据变化之后的回调函数
console.log('age发生了变化');
})
return {age}
}
}
</script>
立即执行
```bash
<template>
<div>
{{age}}
<button @click="age++">点击自增</button>
</div>
</template>
<script>
import {watch,ref} from 'vue'
export default {
setup(){
const age = ref(18)
watch(()=>{
// 返回你想要监听的响应式属性(ref产生的对象必须加.value)
return age.value
},
()=>{
// 数据变化之后的回调函数
console.log('age发生了变化');
},
{
//开启立即监听
immediate:true
}
)
return {age}
}
}
</script>
开启深度监听
<template>
{{ name }}
{{ info.age }}
<button @click="name = 'ls'">change name</button>
<button @click="info.age++">change age</button>
</template>
<script>
import { reactive, toRefs, watch } from 'vue'
export default {
setup() {
const state = reactive({
name: 'zs',
info: {
age: 18
}
})
watch(() => {
return state
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
}, {
deep: true
})
return {
...toRefs(state)
}
}
}
</script>
更好的写法
<template>
{{ name }}
{{ info.age }}
<button @click="name = 'ls'">change name</button>
<button @click="info.age++">change age</button>
</template>
<script>
import { reactive, toRefs, watch } from 'vue'
export default {
setup() {
const state = reactive({
name: 'zs',
info: {
age: 18
}
})
watch(() => {
// 详细的告知你要监听谁
return state.info.age
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
})
return {
...toRefs(state)
}
}
}
</script>
生命周期函数
使用步骤
1.先从vue中导入以on打头的生命周期钩子函数
2.在setup函数中调用生命周期函数并传入回调函数
3.注:生命周期钩子函数可以调用多次
代码验证
<template>
<div>生命周期函数</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
setup() {
// 时机成熟 回调函数自动执行
onMounted(() => {
console.log('mouted生命周期执行了')
})
}
}
</script>