# 组合式api
整理碎片化逻辑,将统一逻辑整理在一起,方便对逻辑进行处理
# 核心setup(props,context)
# props
在setup中的props参数是接收组件传入属性
当props传入新的值时,setup中的值也会被更新,所以props是响应式的。
setup 执行时机是在 beforeCreate 之前执行
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
因为 props 是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性。
需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成
import { toRef } from 'vue'
setup(props) {
const title = toRef(props, 'title')
console.log(title.value)
}
# context
在setup中的context参数是接收组件传入的方法
context中就提供了三个属性:attrs、slot 和emit,分别对应 Vue2.x 中的 $attr属性、slot插槽 和$emit发射事件。并且这几个属性都是自动同步最新的值,所以我们每次使用拿到的都是最新值。
export default {
setup(props, context) {
// Attribute (非响应式对象,等同于 $attrs)
console.log(context.attrs)
// 插槽 (非响应式对象,等同于 $slots)
console.log(context.slots)
// 触发事件 (方法,等同于 $emit)
console.log(context.emit)
// 暴露公共 property (函数)
console.log(context.expose)
}
}
this的使用
在 setup() 内部,this 不是该活跃实例的引用,因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这使得 setup() 在和其它选项式 API 一起使用时可能会导致混淆。
# 响应式声明值ref、reactive
两者之间的区别:在setup返回的refs在模版中访问时ref是自动浅解包,而reactive是深层解包。
好处:可维护性明显提高,可以控制哪些变量暴露,可以跟中哪些属性被定义 (属性继承与引用透明)
# reactive
对引用数据类型数据进行装箱操作使得成为一个响应式对象,可以跟踪数据变化。
const count = ref(1)
const obj = reactive({ count:count })
// ref 会被解包
console.log(obj.count === count.value) // true
// 它会更新 `obj.count`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2
// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3
# isReactive
检查对象是否是由 reactive 创建的响应式代理。
# readonly
接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理。只读代理是深层的:任何被访问的嵌套 property 也是只读的。
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {
// 用于响应性追踪
console.log(copy.count)
})
// 变更 original 会触发依赖于副本的侦听器
original.count++
// 变更副本将失败并导致警告
# shallowReactive
创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (暴露原始值)。
const state = shallowReactive({
foo: 1,
nested: {
bar: 2
}
})
// 改变 state 本身的性质是响应式的
state.foo++
// ...但是不转换嵌套对象
isReactive(state.nested) // false
state.nested.bar++ // 非响应式
# ref
对基本数据类型数据进行装箱操作使得成为一个响应式对象,可以跟踪数据变化。
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value。
# toRef
主要用于接收props参数时使用, 因为即使源 property 不存在,toRef 也会返回一个可用的 ref。这使得它在使用可选 prop 时特别有用,可选 prop 并不会被 toRefs 处理。
export default {
setup(props) {
useSomeFeature(toRef(props, 'foo'))
}
}
# toRefs
将响应式对象转化为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref。 主要用于reactive解构使用
const state = reactive({
foo: 1,
bar: 2
});
const stateAsRefs = toRefs(state);
// ref 和原始 property 已经“链接”起来了
state.foo++;
console.log(stateAsRefs.foo.value); // 2
stateAsRefs.foo.value++;
console.log(state.foo); // 3
// const { foo, bar } = stateAsRefs;
const { foo, bar } = state;
console.log(foo.value, bar.value);
# isRef
检查值是否为一个 ref 对象。
# 动态监听(computed,watch)
# computed计算属性
1、接受一个getter函数,并根据getter的返回值返回一个不可变的响应式ref对象。
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误 :返回的是一个不可变的响应式ref对象
2、或者,接受一个具有 get 和 set 函数的对象,用来创建可写的 ref 对象。
const count = ref(1);
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1;
}
});
console.log(count.value); // 1 只是单纯的获取ref中count的值,未触发computed
console.log(plusOne.value); // 2 获取computed属性值,触发get函数
count.value = 2;
console.log(plusOne.value); // 3 获取computed属性值,触发get函数,count.value=2,
plusOne.value = 4;
console.log(count.value); // 3 因为plusOne传入值,触发set函数,4-1=3。
console.log(plusOne.value); // 4 当前count.value=3,获取计算属性触发get 3+1=4
3、在reactive中使用 computed
const date = reactive({
dates:new Date(),
timeData:computed(()=>{
return date.dates
}),
yearData:""
})
const {timeData, yearData} = toRefs(date)
return {
timeData, yearData
}
# watch
← 设计模式笔记 Vue框架应用知识点 →