组合式 api 的出现动机和 mixin 复用的痛点
技术考古 mixin
定性
- 是一个组件,有 data,prop 等属性
- 就是把 script 部分 export 从大括号开始的内容,全部放在一个单独文件中备复用
- 可在需要时导入,在 mixin 配置项按数组传入所需 mixin 就行
作用规范
- 和组件原有数据相比优先级不高,有命名冲突时以组件自己的 data 为主
- data 中所有数据进行合并
- 如果有重名则组件自身属性覆盖 mixin 属性
- methods, computed, prop,components 中的属性同样进行合并,重名则组件覆盖 mixin
- 如果对象 key 相同,组件内优先
生命周期钩子
- 组件和 mixin 都执行,且 mixin 比组件先执行
- 所以生命周期调用都能调用
引入方式
- 引入组件的就是局部 mixin,引入根组件的就是全局 mixin app.mixin()
- 全局插件相当于把上述的配置项在所有页面注入
- 这种适合写插件 可以在其中给 vue 加入任意配置项,并通过 this.$options 来获取
minxi 的问题
- 命名冲突
- 来源不明
- 分隔不清
组合式 API
setup(props, context)
setup 中没有 this
props 参数就能拿到所有 props 数据
context 参数能拿到 attrs,slots(父组件插槽)以及 emit(没有 this.$emit 了)
setup return 值能够被 template 使用,相当于代替 data
setup 中定义函数正常定义就行,但要记得 return 出去
setup()函数只是替代 data,computed 和 methods 这些响应式内容,components,props 和 emits 仍然使用配置项形式
不过进一步 setup 语法糖就全变成 definexxx 了
组合式的生命周期
- setup 在 created 和 beforeCreate 之前调用,所以直接在 setup 操作就行
- 所有钩子前面都加 on
- setup 代替了 beforeCreate 和 created 两个钩子
- 变为可以直接在 setup 中调用的函数
setup 中的 prop
- prop 配置项照样要写
- 但传 prop 和收 prop 的组件中都要接收 setup(prop)参数
- 并且使用 prop.xxx 方式读取 prop
如何将非响应性 prop 转换为响应性
- 父组件向子组件传递的响应性 prop 在子组件也是响应性的,无论是否进行解构
- template 会对响应性数据自动进行拆解,把 ref.value 拿出来,所以数据会变为 proxy 而非 refimpl
- 传递 js 基本类型数据时会失去响应性,乖乖地用 torefs
- 传递对象时就完全不怕,但如果用 ref 包裹
context 参数
- setup 的第二个参数是 context,context 中有两个主要属性
slots 属性
- slots 成为一个对象,需要在 setup 传入解构参数 setup(props, {slots})保存了组件中传入的 slots 信息,属性名就是名字,属性值成为函数
- 在组合式 api 中使用需要 return 一个回调函数来调用 h 函数
js
setup() {
return () => h('header', {}, slots.header())
}
attrs
使用同 slots setup(props, {attrs})
包括所有没有明确定义的其他属性(比如 data-xxx), 替代 $attrs 属性,模板中可以使用 this 来使用
本身是响应性的,和 prop 一样不能随便解构 setup 中的 emit
因为无法使用 this,所以 watch 和 emit 时要其他办法
在 子组件 setup 定义的函数中套 emit("name", params)函数来发射事件,同时在 emits 配置项里也要这么写
并在父组件中监听 emit 发射的事件
不过在模板中可以更随意一点用$emit
组合式中的 provide 和 inject
- 均变为函数,provide('propName', value)提供, const xxx = inject('propName')来接收
- 响应式数据也保持响应性,同样需要注意解包和深层数据响应性的问题
setup 源码的执行顺序
- createComponentInstance 创建组件实例
- setupComponent 初始化 component 内部操作
- setupStatefulComponent 初始化有状态组件
- 在 setupStatefulComponent 取出 setup 函数
- callWithErrorHanding 执行 setup