package.json 封装 vue模块_Vue composition api 模块

2f3d8bbc1b38bde8267396a27f989594.png

如果你的项目,只是类似活动页面等开发场景,你只需要看我得第一篇文章就可以了解 Vue composition api 了:

https://zhuanlan.zhihu.com/p/181630740​zhuanlan.zhihu.com

如果你需要开发较为复杂的后台页面,那可能看我的第二篇和第三篇文章,也能让你很舒服地将 Vue composition api 用起来:

https://zhuanlan.zhihu.com/p/183744518​zhuanlan.zhihu.com
https://zhuanlan.zhihu.com/p/187325450​zhuanlan.zhihu.com

但是如果你想要充分发挥逻辑复用的威力,做出一个长期维护拳头产品,那么这篇文章将有所裨益,当然,这个层级我也在试探,希望能与大家共勉,出了差池也希望谅解~


模块

能做到服务封装,实现 “微”,已经很不错了吧?

照理来说,Vue composition api 的潜力已经被挖掘到极致了吧?

其实不然,即使已经做到了 服务分割,服务发现,也还远远不够,为什么呢?

回头看一下之前的例子,是不是一直都有一个问题?没发现?

我们所有的服务,最终注入并且处理的地方是在哪里?

视图组件

const 

这合理么?

中小型应用,这样是合理的,视图的结构就是功能的结构

大型应用,这样不合理,视图以及一切部件,都是为功能和业务服务的


我们从视图的角度来看,当在组件内部注入服务时,其子组件和孙组件都可以访问到该服务。

其它组件呢?与其平级的组件和其父组件呢?是会访问不到么?

当组件出现嵌套依赖的时候,以组件结构作为功能结构的模型将会出现重大漏洞!

这个问题在后端,被称为:

循环依赖问题

不过呢,好消息是,js 原生的模块化文件加载机制已经处理了这个问题,是不是很开心?不用再大量展开了!

因此,你只需要通过改变文件划分,就可以完成模块化改造,让代码围绕着功能逻辑展开。

那么我们来试试,首先之前依赖视图逻辑的划分方式要彻底改变:

  1. 摒弃掉 pages/views 之类的文件夹
  2. 包含视图组件的每个文件夹下声明 index.tsx 作为主视图入口
  3. 常用第三方库尽可能 组合函数化 (这个需要靠第三方,比如 React 的 ahooks)

而我们按模块化划分的文件夹应该是怎样的结构呢?

直接看 Angular 的文档吧~

领域模块:

领域特性模块用来给用户提供应用程序领域中特有的用户体验,比如编辑客户信息或下订单等。
它们通常会有一个顶层组件来充当该特性的根组件,并且通常是私有的。用来支持它的各级子组件。

路由模块:

路由模块为其它模块提供路由配置,并且把路由这个关注点从它的配套模块中分离出来。

服务模块:

服务模块提供了一些工具服务,比如数据访问和消息。理论上,它们应该是完全由服务提供者组成的,不应该有可声明对象

窗口部件模块:

窗口部件模块为外部模块提供组件、指令和管道。很多第三方 UI 组件库都是窗口部件模块。
窗口部件模块应该完全由可声明对象组成,它们中的大部分都应该被导出。
窗口部件模块很少会有服务提供者。
如果任何模块的组件模板中需要用到这些窗口部件,就请导入相应的窗口部件模块。

那么,你定义出来的文件结构应该类似于这样:

+ routeModule
  - user.tsx
  - index.tsx
+ widgetModule  // 部件模块不能有外部注入,不需要 index
  - dialog.tsx
  - message.tsx
+ serviceModule  // 服务模块不需要 index
  - useRequest.tsx
  - useDrag.tsx
+ userModule  // 领域模块
  - index.tsx
  - profile.tsx
+ workerModule // 领域模块
  - index.tsx
- App.tsx  // 根

当前适合 Vue Composition api 的 vue-router 还没发布,因此先不考虑 路由模块,需要重点说一下 部件模块。

部件模块

部件模块不应该有注入逻辑,不应该依赖于你的业务,比如很多第三方ui库,他的 button,table,和你正在写的业务是没有关系的,在这个模块中不可能出现 userInfo 之类的数据。

模块集成

模块可以嵌套模块,模块只是资源的一种划分方式而已:

+ widgetModule 
  - dialog.tsx
  - message.tsx
  + bottomSheetModule // 嵌套 module
    - mobileBottomSheet.tsx

接下来来一个重头戏:

单一数据原则

模块划分了是不是不符合单一数据原则呢?有可能,即便你严格按照模块划分方式进行依赖的注入,也免不了会出现循环依赖的问题。

那怎么办呢?

很简单,所有全局单例服务的注入,全部放在根组件进行

const 

这样将大大减少心智负担,并且符合了单一数据源的原则。所有逻辑和数据都在跟组件完成了声明(当然,不一定保存于根组件)。

熟悉 Angular 的同学也会发现,这同时也是 Angular 推荐写法:

@

Angular 给出的解释是:

坚持指定通过应用的根注入器提供服务。 为何?注入器是层次化的。 为何?当你在根注入器上提供该服务时,该服务实例在每个需要该服务的类中是共享的。当服务要共享方法或状态时,这是最理想的选择。 为何?当不同的两个组件需要一个服务的不同的实例时,上面的方法这就不理想了。在这种情况下,对于需要崭新和单独服务实例的组件,最好在组件级提供服务。

当然,最后一句也可以看出,这种方式只适合 全局单例服务,非全局的化,还是得老老实实声明注入喔。


统一导入导出

当你用文件系统完成模块封装后,还有一个问题没有解决,如题所示,统一导入导出。

什么意思呢?假设你有一个部件模块 OverlayModule:

// OverlayModule

大多数情况下,我们希望模块有统一的导出结构。

这个无可厚非,但是当你开发大型超大型项目的时候,往往你不止想要的是统一的导出结构,更想要统一的导入结构

你似乎可以这么做:

import 

对了,小朋友们已经看出来了,之所以推荐使用 jsx 的原因,template 写法组件声明是会比较麻烦的,有小伙伴指出,Vue 的优势不是逻辑视图分离么?朋友,在有逻辑复用的情况下:整个组件都应该是视图。(坚持把视图以外逻辑放在服务中)

如果你需要导入的是 自定义组合函数 :

import 

同理,如果我们需要更简单的统一导入导出方式,封装 module 时操作是最为方便的:

// OverlayModule

这样是不是会更加直观呢?


好了,Vue composition api 的系列介绍基本结束了,相信大家对新版 Vue 的潜能有了更多的期待,这里也可以做一个横向对比,让大家知道 Vue 在相关竞品中的位置。

  1. Vue 是最晚实现逻辑复用的主流框架,15年 Angular 率先实现,React 18年年底实现,Vue 还在开发中,但是,晚出现不一定是劣势,Angular 和 React 都存在一定的问题。
  2. Angular 现在可能只适合大型项目,对比没有逻辑复用的 React,和 Vue 版本,Angular 优势是无以复加的,相关的优点对于当时的 React 和 Vue 来说无异于降维打击,但是 事件驱动的 zone.js 难度实在是太高(最近将成为可选项),rxjs 上手难度尤为曲折(如果 Redux/vuex 只是用了一点点 函数式的概念,rxjs 则为函数式响应式大成,非科班很难用得顺手)。另外,对比当前版本的 React,在小型应用上,React 方便程度真的太高了,尤其是与其生态相配合。
  3. React 心智负担较高,新版本 React 将组件作为管道,大范围使用 monad,全面拥抱函数式开发(甚至可以看成一个有视图的 rxjs, cycle.js 类似体验),使用时限制太多,依赖数组/调用顺序/不许使用条件/非响应式可变ref,都在增加编程难度。

而 Vue 的优点也很明显 ——

简单

就目前的使用体验来说,Vue composition api 真的是把简单可用放在了第一位上的,核心 api 只有两个,直接使用之前的生命周期,除了需要理解响应式,其它基本无负担。

类型支持更让人惊艳,provide,inject 使用要比 React 的方式来的方便,并不需要自己单独封装 connect,要是加上了 language service,相信会有不少人从 React hooks 版本转向 Vue。

遗憾的是目前还没有带类型推断的 依赖查找/依赖注入 系统,当然,官方也是有解释的,decorator 还是不够稳定。

总而言之,Vue 正在利用自己的后发优势,在小型,中型,中大型应用上,向 React 发起挑战。

当然了,最后还是想聊聊关于不变性的思考:

不变性

如果把 Vue 的 reactive 看成“变量”,当然会认为这个系统天生不稳定,函数式拥趸甚至会说:“怎么能写变量呢?”,不过话又说回来,利用 proxy 封装之后,实际上还是调用的 getter,setter 方法,只是隐藏了细节而已。

带来的效果是,请求只需要声明,不需要传参了(react 如此做会违背不变性原则,比如 ahooks 的 useRequest.run(data)),看看这个例子:

a51ec0d93879e728debff3db0d60cb65.png

发送请求并未传参,原因仅仅是有这么个函数:

export 

这个不纯,会出问题!

但是想想看,如果不死守教条可以让自己写的快一点,为什么还要按着书本不放呢?

我们本质上都是坏小孩,不是么?

有没有大佬想要搞个 Vue 版本的 ahooks ? 加我一起呀~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值