Vue组件化 与 iOS 的业务组件化(模块化)

iOS 组件化Modular

Vue

一. 组件化的需要

Vue.js的两个外围数据驱动和组件化

为了进步代码复用性,缩小重复性的开发,咱们就把相干的代码依照 template、style、script 拆分,封装成一个个的组件。组件能够扩大 HTML 元素,封装可重用的 HTML 代码,咱们能够将组件看作自定义的 HTML元素。

二. 如何划分组件

通常一个利用会以一棵嵌套的组件树的模式来组织:

三. 组件分类

组件的品种可分为以下4种:

  1. 一般组件
  2. 动静组件
  3. 异步组件
  4. 递归组件

一般组件

import tem from './components/tem' ...{    components: {tem}  // 注册}

动静组件

var vm = new Vue({  el: '#example',  data: {    currentView: 'home'  },  components: {    home: { /* ... */ },    posts: { /* ... */ },    archive: { /* ... */ }  }})<component v-bind:is="currentView">  <!-- 组件在 vm.currentview 变动时扭转! --></component>

异步组件

const AsyncComponent = () => ({    // 须要加载的组件 (应该是一个 `Promise` 对象)    component: import('../components/MyComponent'),    // 异步组件加载时应用的组件    loading: LoadingComponent,    // 加载失败时应用的组件    error: ErrorComponent,    // 展现加载时组件的延时工夫。默认值是 200 (毫秒)    delay: 200,    // 如果提供了超时工夫且组件加载也超时了,    // 则应用加载失败时应用的组件。默认值是:`Infinity`    timeout: 3000})

递归组件

name: 'recursion-component',template: '<div><recursion-component></recursion-component></div>'

iOS

注:对于iOS或者android相比组件(Component),个人感觉称之为模块(Module)更为适合。组件强调物理拆分,以便复用;模块强调逻辑拆分,以便解耦。而且如果用过 Android Studio, 会发现它创立的子系统都叫 Module. 但介于业界习惯称之为组件化,所以咱们持续应用这个术语。 链接

一. 组件化的需要

在 iOS Native app 后期开发的时候,如果参加的开发人员也不多,那么代码大多数都是写在一个工程外面的,这个时候业务倒退也不是太快,所以很多时候也能保障开发效率。然而一旦我的项目工程宏大当前,开发人员也会逐步多起来,业务倒退突飞猛进,这个时候繁多的工程开发模式就会暴露出弊病了。

  • 我的项目内代码文件耦合比较严重
  • 容易呈现抵触
  • 业务方的开发效率不够高

为了解决这些问题,就呈现了组件化的概念。所以 iOS 的组件化是为了解决上述这些问题的,这里与Vue组件化解决的痛点不同。

iOS 组件化当前能带来如下的益处:

  • 放慢编译速度(不必编译主客那一大坨代码了,各个组件都是动态库)但动态库会加大包体积的大小
  • 不便 QA 有针对性地测试
  • 进步业务开发效率

组件化的封装性只是其中的一小部分,更加关怀的是如何拆分组件,如何解除耦合。前端的组件化可能会更加重视组件的封装性,高可复用性。

二. 如何封装组件

iOS 的组件化伎俩十分繁多,就是利用 Cocoapods 封装成 pod 库,主工程别离援用这些 pod 即可。最终想要达到的现实指标就是主工程就是一个壳工程,其余所有代码都在组件 Pods 外面,主工程的工作就是初始化,加载这些组件的,没有其余任何代码了。

拿弹个车为例

CocoaPods,iOS包管理工具,相似于前端的npm, yarn。其原理:依据Podfile形容,找到对应代码库的podspec文件,而后依据podspec中的形容,找到代码库,并且找到之后,拷贝须要的文件到本人的工程中。具体如果用 Cocoapods 打包一个动态库 .a 或者 framework链接

三. 如何划分组件

iOS 划分组件尽管没有一个很明确的规范,因为每个我的项目都不同,划分组件的粗粒度也不同,然而仍旧有一个划分的准则。

App之间能够重用的 Util、Category、网络层和本地存储 storage 等等这些货色抽成了 Pod 库。还有些一些和业务相干的,也是在各个App之间重用的。

准则就是:要在App之间共享的代码就应该抽成 Pod 库,把它们作为一个个组件。不在 App 间共享的业务线,也应该抽成 Pod,解除它与工程其余的文件耦合性。

常见的划分办法都是从底层开始入手,网络库,数据库存储,加密解密,工具类,地图,根底SDK,APM,风控,埋点……从下往上,到了下层就是各个业务方的组件了,最常见的就相似于购物车,我的钱包,登录,注册等。

四. 组件间的消息传递

划分好了组件,那么咱们就要解决两个问题:1.各个页面和组件之间的跳转问题。2.各个组件之间互相调用。

iOS组件化有以下三种计划

  • URLRouter注册
  • Protocol-Class注册
  • Taret-Action

咱们公司的计划是Target_Action,但体现上Target_Action能够通过URL来体现,也就是说URL通过解析能解析成Target_Action的模式。

1.url-block

url-block 这个形式我最早是在蘑菇街的组件化计划中看到的,简略来说它就是配置“一段 url 对应一个 block 办法”,当咱们应用 openUrl:办法的时候,其实就是在调用这个 block 办法。

比方上面代码:

[MGJRouter registerURLPattern:@"mgj://detail?id=:id" toHandler:^(NSDictionary *routerParameters) {    NSNumber *id = routerParameters[@"id"];    // create view controller with id    // push view controller}];

这是蘑菇街调用详情页的办法,MGJRouter作为中间件,任何组件间的调用都有它来对立解决。不过这种 url 的传递形式使得参数类型受到了限度,无奈传递非常规的参数类型,比方 UIImage。于是就有了上面这种 protocol-class。

2.protocol-class

protocol-class 也是在蘑菇街组件中提出的,对于须要非常规参数的时候,他们就应用这种计划。protocol-class 通过在外部保护了一个 protocol 和 class 的映射表,依据对于的 protocol 来获取对应的 class,应用方不须要在意 class 是哪个类,只有晓得它实现了 protocol 就能够。


代码如下:

[ModuleManager registerClass:ClassA forProtocol:ProtocolA];[ModuleManager classForProtocol:ProtocolA];

[ModuleManager classForProtocol:ProtocolA] 的返回后果就是之前在 ModuleManager 外部注册好的 dict 里 protocol 对应的 class。

3.target-action

这种组件化形式是利用一个中间件来调用,中间件利用 runtime 来调用其余组件,这种形式能够做到真正意义上的解耦。而后再通过实现中间件 category 的形式来提供服务,使得使用者只须要依赖中间件,而组件不须要依赖中间件。

外围代码总结

[self performTarget:@"A" action:@"viewController" params:params shouldCacheTarget:NO];
//这里的类和办法子都是运行时动静生成的- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget{    if (targetName == nil || actionName == nil) {        return nil;    }    NSString *swiftModuleName = params[kCTMediatorParamsKeySwiftTargetModuleName];    // generate target    NSString *targetClassString = nil;    if (swiftModuleName.length > 0) {        targetClassString = [NSString stringWithFormat:@"%@.Target_%@", swiftModuleName, targetName];    } else {        targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];    }    NSObject *target = [self safeFetchCachedTarget:targetClassString];    if (target == nil) {        Class targetClass = NSClassFromString(targetClassString);        target = [[targetClass alloc] init];    }    // generate action    NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];    SEL action = NSSelectorFromString(actionString);    .......}

4.AppDelegate解耦

典型的解决方案有以下几种:

• plist动态注册

• load办法动静注册

• 基于__attribute__的clang语法,把注册信息写到mach-o文件里 美团计划 facebook计划 案例

两者平台上开发方式存在差别

次要体现在单页利用和类多页利用的差别。当初前端比拟火的一种利用就是单页Web利用(single page web application,SPA),顾名思义,就是只有一张Web页面的利用,是加载单个HTML 页面并在用户与应用程序交互时动静更新该页面的Web应用程序。

浏览器从服务器加载初始页面,以及整个利用所需的脚本(框架、库、利用代码)和样式表。当用户定位到其余页面时,不会触发页面刷新。通过 HTML5 History API 更新页面的 URL 。浏览器通过 AJAX 申请检索新页面(通常以 JSON 格局)所需的新数据。而后, SPA 通过 JavaScript 动静更新曾经在初始页面加载中曾经下载好的新页面。这种模式相似于原生手机利用的工作原理。

然而 iOS 开发更像类 MPA (Multi-Page Application)。

往往一个原生的 App ,页面差不多应该是上图这样。

两者解决的需要也存在差别

iOS 的组件化一部分也是解决了代码复用性的问题,然而更多的是解决耦合性大,开发效率合作性低的问题。而 Vue 的组件化更多的是为了解决代码复用性的问题。

两者的组件化的方向也有不同。

iOS 平台因为有 UIKit 这类苹果曾经封装好的 Framework,所以根底控件曾经封装实现,不须要咱们本人手动封装了,所以 iOS 的组件着眼于一个大的性能,比方网络库,购物车,我的钱包,整个业务块。前端的页面布局是在 DOM 上进行的,只有最根底的 CSS 的标签,所以控件都须要本人写,Vue 的组件化封装的可复用的单文件组件其实更加相似于 iOS 这边的 ViewModel。

集体实现的一个组件化小Demo
Modular喜爱的给个start

友情链接:
Vue.js 官网文档

组件化 OR 模块化

iOS 组件化 —— 路由设计思路剖析

iOS利用架构谈 组件化计划

App 组件化与业务拆分那些事