vue rules 表单验证_Vue 面向对象编程 —— 领域驱动 表单

2f55e2eb10342a3802322493a77614c2.png

前文说到用抽象类做自顶向下的开发,稍稍有些复杂,现在的新思潮其实已经不推荐采用抽象类,继承等概念了

为什么呢?

因为组合优于继承

因为继承一定程度打破了类的封装性,而且还由于一系列的复杂的用法——抽象方法,多继承,钻石继承等——导致维护成本上升

但这并不意味着继承是无用的,继承最主要作用在架构上

继承可以作为架构师发力的工具,比如 enterprise-architecture 自动生成抽象类等用法

总结一句话:

继承是用来限制人用的

而现在,第三方库很丰富,普通人不考虑架构也可以做出功能多样的应用,再加上云服务等新型开发模式出现

按照功能领域划分代码结构比按照观念划分结构更适合

比如之前的表单,我们不需要考虑一个表单真的有那些功能,只需要实现最核心的功能即可,利用类的极强扩展性,将其它功能附加进来即可

这实际上是自顶向下和自底向上的思维方式区别,二者没有优劣之分,一般来说,分析问题时自顶向下,解决问题时自底向上,同时也分别是面向对象和函数式发力的地方

一个表单,最重要的就是 表单项 到 数据模型 的绑定和同步

还是用表单做例子哈,因为一个 UI 框架,最重要的就只有三个:
表单,表格,浮动层

我们希望实现的目标是(再重温一遍哈):

84422114662355e6e262a07ad95c3613.png

整个表单只有一个输入 initialValue,和一个输出 handleChange,包含数据模型结构,表单项绑定,都自动完成,并且要考虑表单嵌套的情况

之所以这么封装,目的是保证

所见即所得

使得使用者的负担降到最低

这次按照领域来开发,FormService 和 FormItemService 只包含最小功能集合:

1cd07d91ab135a2c12ebb8b9ab07e375.png

每个表单有个独立的注入口令,也有一个公共的注入口令

Form 组件在注入相关服务时,需要注入两遍实体:

45c16516cae129d8db782c7f5ce4f256.png

为什么要注入两遍呢?

静态属性的注入口令是特定的,只要是 Form 都是如此,保证每个 FormItem 拿到的都是离他最近的父组件 Form

但是如果我想要指定某个 FormItem 是特定 Form 的项目怎么办?

很简单,传入相关令牌即可:

const 

第一个 FormItem 属于表单 form1,第二个 FormItem 属于表单 form2,相关结构绑定也是如此

因此,FormItemService 实现如下:

213bcfeb593cb3b0e103446ff7ffff13.png

注意 data 绑定 的 toRef 方法

按照官方的说法:

e12523e7d3bf955f76478fa582cfd997.png

相当于它是 form.model 的一个代理对象,通过设置其 value 就可以做到更改 form.model 某个字段的目的


接下来是重头戏了,如何做到不对表单项进行 v-model 绑定就可以实现表单项和 model 的绑定呢?

78d6ebc0951333abbac78694cc4d8bf5.png

这里必须使用 render,单纯用模板无法实现相关功能需求

因为 Vue 3 的 this.$slots 拿到的不是vnode数据,而是vnode函数,需要运行之后才能获取数据,而运行时机由 Vue 控制

将 formItemService 的 data 绑定进 slot 的参数,注意,data 是个 Ref

这里涉及一个重要概念 ——

ref 的 props 传递

由于 Vue 模板的自动 value 绑定,这里可以肯定将成为 vue3 的一个难点

ref 是个代理对象,你在子组件 ref.value = xxx ,其实和 在父组件 ref.value = xxx 并没有任何区别

因为 ref 是脱离组件响应式单独存在的

是的,之前要你牢记单向数据流,而现在要求你一定程度地忘记它,双向绑定因此也有两种方式:

  • v-model 针对具体数据和操作方法的双向绑定
  • props 传递 ref 的针对 Proxy 的双向绑定

采用后者,一定要保证这个 ref 不要与任何其它组件数据产生依赖

因为绑定表单项的方式是用 $slots 的 default vnode,传入 props ,你并不知道 render 会运行多少次,无法采用第一种传递事件的方式,只能采用 ref 传递

所以,需要表单项也采用这个方式——props传递ref——实现双向绑定:

8cdab8e9e8bbea53d13515b0938ce9f4.png

注意那个 ctx.attrs ,这个涉及 vnode 的参数问题,请自信查阅新版差异:

f40b245c3f2e194e7cbe15c11c6745f3.png

当然,这种方式也可以与 v-model 共存

之后再实现 FormItemRulesService,只要保证依赖于 FormItemService 就可以实现 rules 功能了

大家可以思考以下,props 传递 ref 和 v-model 到底哪个好?

我是认为 props 更好,响应式编程会稍微难点,但是更直观,少写好多代码,你认为呢?

以上

https://codesandbox.io/s/boring-bose-3frgd?file=/src/App.vue​codesandbox.io
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值