Vue3中的响应式 api
setup入口函数
作用
setup函数是一个新的新的组件选项,作为组件中组合式api的起点(入口函数)setup函数只会在组件初始化的时候执行一次setup函数在beforCreate生命周期钩子执行之前执行,这时实例还没有生成,this不可用
代码演示
export default{
setup(){
console.log('setup执行了');
console.log(this);
},
beforeCreate () {
console.log('beforeCreate执行了');
console.log(this);
}
}
运行截图
reactive
作用
reactive 是一个可执行函数,接收一个普通的对象传入,把 对象数据 转化为响应式对象并返回
使用步骤
- 从
vue框架中导入reactive函数
import { reactive } from 'vue'
- 在
setup函数中调用reactive函数并将想要变成响应式的 对象数据 当成参数传入
setup -> const state = reactive({name:'张一一'})
- 如果想要在模块中使用,必须
return
注意事项
- 在使用
reactive函数的时候,必须传入一个对象{name:'张一一'}
代码演示
<template>
<div>
{{state.name}} // 使用插值表达式引用
</div>
</template>
<script>
import {reactive} from 'vue'
export default {
name: 'App',
setup(){
const state = reactive({
name:'张一一'
})
setTimeout(() => {
state.name = '冯家祺'
},2000)
return{
state
}
}
}
</script>
ref
作用
ref 是一个可执行的函数,接受一个简单类型或复杂类的传入,并返回一个响应式,且可变的 ref 对象
使用步骤
- 从
vue框架中导入ref函数 - 在
setup函数中调用ref函数并传入数据(简单类型或复杂类型) - 在
setup函数中把ref函数调用完毕的返回值以对象的形式返回出去 - 在
setup函数是使用ref结果,需要通过.value访问,在模板中使用不需要加.value
代码演示
<template>
<div>
{{msg}} // 不需要加 .value
{{list}}
</div>
</template>
<script>
import {ref} from 'vue'
export default {
name: 'App',
setup(){
const msg =ref('张一一')
const list = ref ([1,2,3])
setTimeout(() => {
list.value.push(4,5,6) // 一定要加 .value
},2000)
return{
msg,
list
}
}
}
</script>
reative 对比 ref
ref函数可以接收一个简单类型的值,返回一个可改变的ref响应式对象,从而弥补reactive函数不支持简单类型的问题reactive和ref函数都可以提供响应式数据的转换,具体什么时候使用哪个API社区还没有最佳实践- 推荐写法 只有我们明确知道要转换的对象内部的字段名称(例如:form表单),我么才使用
reactive,否则一律使用ref,从而降低在语法选择上的心智负担
computed
什么是计算属性
-
特征:基于一个现有的响应式数据,经过一定的计算得到一个全新的数据,并且依赖的数据一旦发生改变,就会立即重新计算得到新值
-
优势:缓存,模板中如果多次使用,只会在第一次使用的时候执行一次函数,后面都会使用缓存
使用步骤
- 从
vue框架中导入computed函数 - 在
setup函数中执行computed函数,并传入一个函数,在函数中定义计算公式 - 把
computed函数调用完的返回值放到setup函数return出去的对象中 注意:一定要return
代码演示
<template>
<div>
{{list}}
{{filterList}}
</div>
</template>
<script>
import {ref,computed} from 'vue'
export default {
name: 'App',
setup(){
// 原始数据
const list = ref([1,2,3,4,5])
// 计算属性
const filterList = computed(() => {
// 基于list筛选出所有大于2的项 返回一个新数组
return list.value.filter(item => item > 2)
})
// 修改原数组 观察 计算属性
setTimeout(() => {
list.value.push(7,8,9)
},2000)
return{
list,
filterList
}
}
}
</script>
<style>
</style>
watch
作用
监听一个实例属性的变化然后执行一个回调,和 vue2 中的 watch 的功能一致
使用步骤
- 从
vue框架中导入watch函数 - 在
setup函数中执行watch函数,开启对响应式数据的监听 watch接收三个常规参数- 第一个参数为函数,返回你要的监听变化的响应书数据
- 第二个参数为响应式数据变化之后要执行的回调函数
- 第三个参数为一个对象,在里面配置是否开启 立即执行 或 深度监听
普通监听
数据变化 执行回调
代码演示
<template>
{{ age }}
<button @click="age++">change age</button>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const age = ref(18)
watch(() => {
// return 监听的数据
return age.value
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
})
return {
age
}
}
}
</script>
立即执行
一上来先执行一次,数据变化后再执行一次
watch的效果默认状态下,只有监听的数据发生变化才会执行回调,如果你需要在一上来的时候就立刻执行一次,需要配置一下immediate属性(第三个参数)
代码演示
<template>
{{ age }}
<button @click="age++">change age</button>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const age = ref(18)
watch(() => {
// return 监听的数据
// 返回你想要监听的响应式属性(ref产生的对象必须加.value)
return age.value
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
},{ immediate: true})
return {
age
}
}
}
</script>
深度监听
- 对象如果嵌套层级比较深,不管哪个属性变化,都会触发回调
- 默认情况下,没有开启深度监听,对象属性的修改不会引起回调执行
- 建议大家大多数情况不要开启深度监听,递归处理比较耗性能,推荐使用精确监听
当我们监听的数据是一个对象的时候,默认状态下,对象内部的属性发生变化是不会引起回调函数执行的,如果想让对象下面所有属性都能得到监听,需要开启
deep配置
代码演示
<template>
{{ state.name }}
{{ state.info.age }}
<button @click="name = 'pink'">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: 'cp',
info: {
age: 18
}
})
watch(() => {
return state
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
}, {
deep: true
})
return {
state
}
}
}
</script>
优化
使用
watch的时候,尽量详细的表明你到底要监听哪个属性,避免使用deep引起的性能问题,比如我仅仅只是想在state对象的age属性变化的时候执行回调,可以这么写
<template>
{{ state.name }}
{{ state.info.age }}
<button @click="state.name = 'pink'">change name</button>
<button @click="state.info.age++">change age</button>
</template>
<script>
import { reactive, toRefs, watch } from 'vue'
export default {
setup() {
const state = reactive({
name: 'cp',
info: {
age: 18
}
})
watch(() => {
// 详细的告知你要监听谁
return state.info.age
}, () => {
// 数据变化之后的回调函数
console.log('age发生了变化')
})
return {
state
}
}
}
</script>