一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
在Vue的项目里,创建组件是一个基本技能,Vue也提供了多种方法,比如 option API、 setup、script setup等。
如果组件里需要使用一些共用方法的话,那么可以使用 mixin、hook等方式,那么还有没有其他的方法呢?
当然可以有,这里介绍一种使用 class 解决共用代码的方法。
建立基类
我们先建立一个基类:
baseComp.js
import { ref } from 'vue' import { store } from '@naturefw/nf-state' export default class BaseComp { constructor () { this.name = 'baseName' this.inheritAttrs = false this.components = {} // 可以在这里注册共用组件 this.props = { // 可以在这里设置共用属性 baseProps: { type: String, default: '基类定义的 props' } } this.store = store // 设置状态,这样就不用每次都 import 了。 } _setup (props, ctx) { // 可以设置共用成员 const baseRef = ref('基类setup定义的') // 可以设置生命周期的钩子 // 其他共用代码 return { store, // 返回状态 baseRef // 返回成员 } } } 复制代码
按照 composition API 的方式设置对象的属性,然后我们可以设置组件共用的部分:属性、组件、状态、生命周期的钩子等,还有权限验证等流程。
建立函数
然后要做一个语法糖,简化获得基类的实例的代码,以及附加组件的个性设置。
其实这里可以设置一个子类,只是想想,似乎可以直接用实例。
childComp.js
import { ref, defineComponent } from 'vue' import BaseComp from './baseComp.js' /** * 返回组件需要的属性 * @param {*} info * * name = 'baseName' * * inheritAttrs = false * * components = {} * * props = {} * * setup = () => {} */ const myComp = (info) => { // 获取基类的实例 const comp = new BaseComp({}) // 设置组件的 name if (info.name) { comp.name = info.name } else { comp.name += new Date().valueOf() } // 附加组件内使用的组件,可以按照不同的小分类设置 if (info.components) { Object.assign(comp.components, info.components) } // 合并属性 if (info.props) { Object.assign(comp.props, info.props) } // 获取父类的 setup const _setup = comp._setup // 设置 setup comp.setup = (props, ctx) => { // 执行父类的 setup const _re = _setup(props, ctx) // 可以制定子类的共用成员 const childRef = ref('子类setup定义的') const _this = { props, ctx, store: _re.store } // 执行 组件定义的 setup,可以使用 this,也可以设置参数。 const _re2 = (info.setup) ? info.setup.call(_this): {} const _re3 = _re2 ?? {} // 返回给 template return { childRef, ..._re, ..._re3 } } // 返回组件需要的各种属性 return defineComponent(comp) } 复制代码
在组件里的使用方式
在组件里引入上面的函数,设置 setup 即可,当然也可以设置props等。
import childComp from './childComp.js' export default childComp({ setup: (props, ctx, store) => { // 可以有 this,也可以使用参数,看个人喜欢。 this.store.user.name = '修改一下用户名称' return {} } }) 复制代码
props, ctx 是默认属性,后面的是基类里提供的共用数据、方法等。
可以用参数传递,也可以用 this 的方式传递。
根据不同的需求,设置不同的子类
面向对象嘛,父类、子类、子子类,为啥要设置这么多呢?当然是为了灵活,如果一个基类就可以搞定的话,那么肯定不需要设置各种子类的。
所以,我们可以根据项目的需求,设置不同的子类,存放不同的共用函数。
小结
基本就是这样了,目前还只是一个基础的想法,至于有多大的实际意义嘛,等以后慢慢验证。
好吧,其实我还是喜欢组合的方式。然后对“页面”进行一下抽象,其实雷同的组件也就不多了。