您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

低成本可复用前端框架——Linke

时间:2021-04-09 10:36:34  来源:今日头条  作者:闲鱼技术

业务背景

目前团队内的开发模式多是面向组件的,UI层和逻辑层均强耦合在一起,由于业务的差异性,往往很难完全复用。

  • 闲鱼前端业务处在高速发展不断尝试的阶段,如何能更快更稳定地完成需求,更好的支撑业务发展绝对是一个值得探索的问题。
  • 在接手一个复杂的老业务代码时,经过较多人的修改,往往可维护性较差,有时只想修改某个小地方却需要较大的理解成本,所以用一套统一的组件开发规范在长期维护中显得格外重要。
  • 闲鱼技术体系经历了从weex、rax0.x到现在rax1.x的变更,中间有过一些前端资产的积累,但是由于迁移的成本后期都不再维护,如何用更小的成本让业务层平稳过渡到新的技术体系?

对于以上的问题我们希望能用框架一并解决,对于该框架的目标主要包括:

  • 提高代码可复用性
  • 规范代码,降低长期维护成本
  • 降低业务层与技术体系的关联

 

思路

关于提效,其中比较重要的是相同的代码不要重复写,做更细的区分和提取,提高可复用的颗粒度。另一方面是解决现有开发下比较影响开发效率的问题。

 

组件的分层

所以我们将面向组件的开发模式分为UI层View和逻辑层Store,以Interface进行隔离和耦合。

低成本可复用前端框架——Linke

 

图一:组件构成

在UI层无需关心状态的流转,只负责展示和交互方法的调用,DOM相关的动画交互等行为逻辑也会放到该层中。

低成本可复用前端框架——Linke

 

图二:组件分工

在确认了分层的逻辑后自然就引入了Interface,主要分为两部分:一部分是IProps,申明该组件所需的Props,在使用者调用该组件时进行对应的提示和约束;另一部分则负责连接Store和View,其中包括状态state和交互方法;见下面的Interface示例:

export interface IMultiScrollerProps {
tabs: string;
onTabChange?(i: number): void;
}
export interface IMultiScroller extends IBase {
readonly tabIndex: number;
readonly tabSource: ITabItem;
readonly children: any;
onSwiperChange(i: number): void;
}

总结一下:所有的state和交互方法都在store中管理,供View消费;View中只负责和dom相关的逻辑操作,View和store的职责分界线就是View和store分别单独使用时其交互和效果都能保持不变;以此实现View和store分别能有更多的复用。

 

状态管理

现有的业务开发中基本所有的需求都是基于hooks的状态管理,主要存在以下问题:

  • 对于较复杂的组件hooks在多次迭代后的维护成本会非常高;
  • 有时候,你的useEffect依赖某个函数的不可变性,这个函数的不可变性又依赖于另一个函数的不可变性,这样便形成了一条依赖链。一旦这条依赖链的某个节点意外地被改变了,那么useEffect就被意外地触发了后面的情况就会变得不可控。
  • 异步陷阱
  • 状态的修改是异步的 useState返回的修改函数是异步的,并不会直接生效,所以此时读取该值获取到的是旧值。要在下次重绘才能获取新值。不要试图在更改状态之后立马获取状态。
const [value, setValue] = useState(0);
setValue(100);
console.log(value); // <- 0

•timeout指向的是旧值

timeout指向的是旧值,即使在外部已经重新设置,由于闭包所有在setTimeout中获取到的都是之前的值。

const [value, setValue] = useState(0);
window.setTimeout( => {
console.log('setAnotherValue', value) // <- 0
}, 1000);
setValue(100);

•何时使用useCallback/useMemo等对于新手来说存在一定的门槛。

关于 Hook 中的闭包:useEffect、useMemo、useCallback都是自带闭包的。也就是说,每一次组件的渲染,其都会捕获当前组件函数上下文中的状态(state、props)。所以每一次这三种 Hook 的执行,反映的也都是当时的状态,无法获取最新的状态。对于这种情况,应该使用 ref 来访问。

对于状态管理react体系中最受欢迎的应是redux与mobx

低成本可复用前端框架——Linke

 

图三:Redux Flow

redux的特点从上图可以总结得到下面的三大原则:

•单一数据源

•state 是只读的

•使用纯函数来执行修改

但是redux的问题也是十分明显的:开发者需要写更多附加的样板代码,并且留下更多需要我们维护的代码。

与 Redux 相似的,另一个状态管理方案是 MobX:

低成本可复用前端框架——Linke

 

图四:Mobx Flow

相比 Redux 的强规则约定,MobX 更简单灵活,核心原理是通过 action 触发 state 的变化,进而触发 state 的衍生对象(Computed value & Reactions)。开发者只需要定义需要 Observe 的数据和由此衍生的数据(Computed value)或者操作 (Reactions),剩下的更新就交给 MobX 去做就可以了。一句话总结就是:

任何源自应用状态的东西都应该自动地获得。

分析闲鱼的业务特色并不存在5个以上同学同时维护一个项目的超大型需求,强约定的redux对我们来说收益有限,而MobX 确实比 Redux 上手更容易些,并且不需要写很多样板代码,可以提供更高效的选择。

 

实现

我们给框架取名:Linke,来自switch的游戏塞尔达,希望它能像林克一样点亮一个个神庙。

基于上面的分析思路结合实际业务中的技术体系(Rax)最后我们设计了下面的研发体系:UI部分也就是View还是沿用原有的Rax,UI用到的状态也直接在View中管理。业务逻辑部分也就是Store用Mobx的能力解决上面提到的现有hooks开发遇到的问题,两者没有强关联。

Linke做为中间耦合层对他们进行约束和桥接。

低成本可复用前端框架——Linke

 

图五:基于Linke的研发体系

 

API

为保证开发者最低的学习成本,Linke在设计时尽可能地减少API,最终只有一个方法和4个Store内置方法,详见:

observer(baseComponent, Store)

保证组件能响应store中的可观察对象(observable)变更,即store更新,组件视图响应式更新

Store内置方法

•成员方法 - $$set: 所有状态变化必须通过$$set来完成,与微信的setData类似

•成员方法 - $$setProps:处理外部传入的组件props,View初始化或者props发生变化时调用

•成员方法 - $$didMount:提供View的生命周期,View被插入DOM时调用

•成员方法 - $$unMount:提供View的生命周期,View被移除DOM时调用 可以看出Store内置方法中除了$$set其他三个都是生命周期方法,其调用顺序为:$$setProps -> $$didMount -> $$unMount

 

demo

Interface.ts

import { IBase } from '@ali/idlefish-linke';
export interface IComponentProps { // 组件所需props
tabs: string;
onTabChange?(i: number): void;
}
export interface IComponent extends IBase { // 连接view和store的state&交互方法
readonly items: any;
handleLoadmore: void;
}

index.tsx

import { observer } from "@ali/idlefish-linke";
import Store from './store';
import { IComponent, IComponentProps } from './interface';
function Component({items, handleLoadmore}: IComponent) {
return (
<View>
{
items.map(item => {
return <Text>{item.title}</Text>
})
}
<View onClick={handleLoadmore}>load more</View>
</View>
)
}
export default observer<IComponentProps>(Component, Store);

store.ts

import { makeAutoObservable } from "@ali/idlefish-linke";
import { IComponent } from './interface';
export default class ComponentStore implements IComponent {
/**
* 所有状态变化必须通过$$set来触发Effect
* $$set赋值来自于makeAutoObservable(this);
* this.$$set('items', [])
*/
$$set;
/**
* 带初始值的属性会自动被观测
*/
items: any = ;
page: 1;
constructor {
// 自动observable该类
makeAutoObservable(this);
}
$$setProps(props) {
... // 对props的处理可以放到这里
}
$$didMount { // 通过 $$didMount / $$unMount 来感知view的生命周期
this.fetch;
}
fetch  {
mtop.request('mtop.xxx', {page})
.then(d => {
this.$$set('items', d.list);
})
}
handleLoadmore =  => {
this.$$set('page', this.page++);
this.fetch;
}
}

上面就是一个完整的组件demo。

 

对比

现在的组件开发模块模式如下图六所示,以组件为单位所有的逻辑是耦合在一起的,相互之间没有分界,即便是相同的样式也很难实现复用。无论是在代码理解还是二次开发上都存在较大的成本和不稳定性风险。

低成本可复用前端框架——Linke

 

图六:原组件的开发模式

基于Linke的组件开发模式如下图所示:

低成本可复用前端框架——Linke

 

图七:基于Linke的组件开发模式

View和Store相对独立没有强耦合性,这样的好处显而易见:

• 通过阅读Interface就能知道Store/View的基本逻辑,减少理解成本

• 数据逻辑和View逻辑分别在Store和View中管理,真正实现各司其职,减少维护成本。

• 最重要的一点是通过分离让Store和View分别实现了复用,组合不同的Store/View生成不同的组件

低成本可复用前端框架——Linke

 

图八:Store分别和不同的View组合

低成本可复用前端框架——Linke

 

图九:不同的Store和同一个View组合

 

应用

目前Linke已经应用在了闲鱼前端各个新项目中,包括2个线上项目和3个正在开发的项目收益明显,什么功能的代码在什么位置一目了然配合Interface中的注释大大减少了接手项目的理解成本。

通用基础组件和业务组件都在有序的抽离中,同时随着View/Store库的不断丰富,可以复用的物料资源增加,不同业务和同一业务不同场景中可以复用的View/Store越来越多,在一定程度上大大减少开发成本提高效率。

展望

目前新财年除了现有的H5业务外,最大的特点是会对各个小程序做一些流量探索,比如淘系轻应用、微信小程序、支付宝轻应用等,这些应用的特点是与端内的H5业务及其相似,但是会有各自的细微差异。所以我们也在探索基于Linke对此类业务场景的提效。



Tags:前端框架   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
CSS框架提供了设计一致解决方案的基本结构,以解决前端web开发中的常见问题。它们提供了通用功能,可以针对特定场景和应用程序进行覆盖。这大大减少了开始创建应用程序和网站所...【详细内容】
2021-12-06  Tags: 前端框架  点击:(15)  评论:(0)  加入收藏
《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的是一个由百度开源的低代码前端框架&mdash;&mdash;amis...【详细内容】
2021-11-05  Tags: 前端框架  点击:(65)  评论:(0)  加入收藏
每个前端开发人员都听说过三个用于构建 Web 应用程序的框架:React、Vue.js和Angular。React 是一个 UI 库,Angular 是一个成熟的前端框架,而 Vue.js 是一个渐进式框架。它们几...【详细内容】
2021-08-25  Tags: 前端框架  点击:(96)  评论:(0)  加入收藏
1、D2admin开源地址: https://github.com/d2-projects/d2-admin文档地址: https://d2.pub/zh/doc/d2-admin/效果预览: https://d2.pub/d2-admin/preview/#/index开源协议:MITima...【详细内容】
2021-07-13  Tags: 前端框架  点击:(127)  评论:(0)  加入收藏
业务背景目前团队内的开发模式多是面向组件的,UI层和逻辑层均强耦合在一起,由于业务的差异性,往往很难完全复用。 闲鱼前端业务处在高速发展不断尝试的阶段,如何能更快更稳定地...【详细内容】
2021-04-09  Tags: 前端框架  点击:(271)  评论:(0)  加入收藏
本文作者 : Stanley 罗昊本文转自: https://www.cnblogs.com/StanleyBlogs/p/14480990.html下载Layui与文件分析下载直接去官网下载即可 文件分析下载完成后,解压会得到一个文...【详细内容】
2021-03-09  Tags: 前端框架  点击:(220)  评论:(0)  加入收藏
尝试了很多不同的前端框架,最终我们选择Vuetify(https://vuetifyjs.com)前端框架。从Bootstrap开始,到iview,Buefy,elementUI,我们都是不断的尝试了多种不同的前端Vue框架,最终选择V...【详细内容】
2020-10-10  Tags: 前端框架  点击:(143)  评论:(0)  加入收藏
起初,按照惯例,先在Vue.js官网上看了相关文档介绍及基础使用。 接着在某站上看了某马实战教程,相关环境已准备好,开开心心的在cmd中输入 vue ui,直觉告诉我,事情没那么简单,果然后...【详细内容】
2020-07-14  Tags: 前端框架  点击:(94)  评论:(0)  加入收藏
ZUI一个基于 Bootstrap 深度定制开源前端实践方案,帮助你快速构建现代跨屏应用。Bootstrap是非常优秀的前端框架,但在构建大型应用的开发时通常远远不够。如果Bootstrap能够完...【详细内容】
2020-06-24  Tags: 前端框架  点击:(82)  评论:(0)  加入收藏
我们又来做这个对比了。这次是 2020 年的版本,还有之前的版本: 2019 年、 2018 年、 2017 年。先来明确一点&mdash;&mdash;这篇文章绝对不是为了告诉你该选择哪个前端框架而...【详细内容】
2020-06-10  Tags: 前端框架  点击:(69)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条