1 toRef | toRefs
延续响应式
1.1toRef
-
针对一个响应式对象(reactive)的prop
-
创建一个ref,具有响应式
-
两者保持
引用关系
使用前提:针对的是响应式对象(reactive封装的)非普通对象
1.2 应用场景
- 想让响应式数据和以前的数据管理起来,并且更新响应式数据之后还不想更新ui
- 要将响应式对象中的某个属性提供给外部使用时
1.3 语法
const name = toRef(obj,'name')
1.4 toRef
vs ref
- ref : 接受一个原始值,返回一个具有响应式的对象, 修改响应式数据不会影响以前的数据,数据发送变化,界面就会自动更新, 本质是拷贝
- toRef : 接受一个响应式数据值,并把该属性包裹成ref对象,使其和原对象产生链接,一种引用关系
1.5 toRefs
特性和toRefs一致
唯一不同的点
- toRef: 复制 reactive 里的单个属性并转成 ref
- toRefs: 复制 reactive 里的所有属性并转成 ref
hooks
2.1 hooks
的定义
顾名思义,Hook就是“钩子”的意思。
Hooks就是把某个目标结果钩到某个可能会变化的数据源或者事件源上,那么当被钩到的数据或者事件发生变化时,产生这个目标结果的代码会重新执行,产生更新后的结果。
核心工作 抽离: 抽离复用其实正是hooks擅长的部分
hooks
的设计初衷就是因为以前复用逻辑
的方法都有一定的问题(如vue的mixin,react的高阶组件和renderProps模式),所以才搞出hooks让逻辑复用更方便,算是大家的一个通识 下面会提到vue mixin的痛处
要抽离复用,只要把抽离的部分再次封装成一个hooks
,然后在需要复用的地方调用该hooks即可(hooks里面也可以直接调用另一个hooks)
hooks
本质其实就是一个包含状态的函数,所以函数做的它都能做,任何地方都可以复用,比mixin
更容易追踪数据和逻辑的来源,且完全支持typescript的类型推断
2.2 命名规范 use
hooks
的命名都是以 use
作为开头,这个规范也包括了那么我们自定义的 hooks
。
2.3 为什么使用hooks
在拥有 Hooks
之前,我首先会想到的解决方案一定是 mixin
mixins
虽然有状态复用的能力,但它的弊端实在太多了。
弊端一:难以追溯的方法与属性!
export default{
mixins: [ a, b, c, d, e, f, g ], // 当然,这只是表示它混入了很多能力`
mounted() {
console.log(this.name)
// mmp!这个 this.name 来自于谁?我难道要一个个混入看实现?
}
}
又或者:
a.js mixins: [b.js]
b.js mixins: [c.js]
c.js mixins: [d.js]
// 你猜猜看, this.name 来自于谁?
// 求求你别再说了,我血压已经上来了
弊端二:覆盖、同名?
当我同时想混入 mixin-a.js
和 mixin-b.js
以同时获得它们能力的时候,不幸的事情发生了:
由于这两个 mixin
功能的开发者惺惺相惜,它们都定义了 this.name 作为属性。
这种时候,你会深深怀疑,mixins
究竟是不是一种科学的复用方式。
弊端三:代价很大
仍然说上面的例子,如果我的需求发生了改变,我需要的不再是一个简单的状态 name
,而是分别需
要 firstName
和 lastName
。
此时 name-mixin.js
混入的能力就会非常尴尬,因为我无法两次 mixins
同一个文件。
当然,也是有解决方案的,如:
// 动态生成mixin
function genNameMixin(key, funcKey) {
return {
data() {
return {
[key]: genRandomName()
}
},
methods: {
[funcKey]: function(v) {
this.[key] = v
}
}
}
}
export default {
mixins: [
genNameMixin('firstName', 'setFirstName'),
genNameMixin('lastName', 'setLastName'),
]
}
确实通过动态生成 mixin
完成了能力的复用,但这样一来,无疑更加地增大了程序的复杂性,降低了可读性。
因此,一种新的 “状态逻辑复用” 就变得极为迫切了——它就是 Hooks
!