分享好友 最新资讯首页 最新资讯分类 切换频道
vue 筛选组件_1.5W字,手摸手教你从0到1开发一个复杂组件(Filter)
2024-12-29 22:07

貌似在面试中,你如何设计一个 react/vue 组件,貌似已经是司空见惯的问题了。本文不是理论片,更多的是自己的一步步思考和实践。文中会有很多笔者的思考过程,欢迎评论区多多交流和讨论。

vue 筛选组件_1.5W字,手摸手教你从0到1开发一个复杂组件(Filter)

从需求讨论、技术方案探讨到编码、到最终的测试,经历过了很多次的脑暴,也遇到过非常多的坑,其中有可能跟业务有关、也有可能跟框架有关,基于这些坑,又讨论了很多解决方案和非常 hack(歪门邪道)的对策。但是随着时间的推移,再回头看看当时的 hack 代码,很多都不太记得为什么这么写了,所以这里简单记录下,Filter 组件的开发过程。以便后面查询,更希望能大家一起探讨,以求得更优质的代码架构和实现思路。

由于代码编写使用基于底层 weex 的 rax 框架,所以有些坑,或许对于正在使用 react 或者 vue 的你并不会遇到,可以直接忽略

Filter,已经常见的不可再常见的组件了,顾名思义,就是个筛选过滤器。我们先看看现有 app 上的一些 filter 展现 形式。既然做组件,我们就需要它足够的通用,足够的易于扩展。

  • 阿里拍卖的 Filter

  • 飞猪的 Filter

在说 Filter 的业务特征之前,我们先约束下每一部分的命名,以便于你更好的阅读此文

上面分别是拍卖和飞猪的 filter 页面,从这两个页面中,我们大概可以总结出关于 Filter 的一下几点业务画像

  • 随着页面滚动,Filter 可能具有吸附能力,但是可能距离顶部存在一定的距离

  • Panel 面板多样性(点击navItem 展开的面板)

  • Panel 面板以及 navItem 都可能会有动画

  • navBar 内容可变

  • panel 面板展示形式不定

  • panel 面板内容可能非常复杂,需要考虑性能优化

  • navBar 上可能存在非 Filter 的内容(关注按钮)

  • 有的navBar 的 navItem 没有对应的 panel 面板

  • Filter 上存在影响搜索结果但是没有影响的”快排“按钮

  • filter 配置参数能够指定

  • 通过 url 传入相关筛选 id 能够初始化面板选中

由于 rax 1.0 ts+hooks 开源版本还在开发中,所以仓库链接暂时就不放上了

  • rax-pui-filter-utils :Filter 的内部工具库,仅供 Filter 开发者提供的工具库

  • rax-pui-filter-tools:配合使用 Filter 的一些工具集,比如 提高性能的 HOC 组件、占位符组件等(可用可不用,根据自己业务需求来),思考原由:并不是每一个 Filter 的使用者都需要这些功能,做成可插拔式,为了降低没必要的 bundle 大小

  • pui-filter:Filter 核心功能开发库

效果图

  • `RelatePanel`筛选项关联Panel型,即筛选头和 Panel 是一对一关系,点击筛选头展示 Panel

  • `QuickSearch`筛选项快速搜索排序型,即筛选头没有对应 Panel,点击筛选头直接触发搜索

  • `PureUI`纯 UI占位类型,即纯 UI 放置,不涉及搜索,比如订阅按钮场景

  • 筛选面板显示隐藏统一管理,支持下拉和左滑展示隐藏动画,统一搜索回调函数

  • Filter 组件在和业务面板隔离,支持任意组件接入,业务组件里搜索变更通过 回调函数来触发

  • 提供了三种业务通用的面板组件

    • `rax-pui-list-select`,列表选择业务面板

    • `rax-pui-location-select`,省市区级联选择业务面板

    • `rax-pui-multi-selection-panel`,多选业务面板,查看组件使用文档

  • 这里指的是 Filter 的功能 Feature,跟上文提及的 Filter 组件功能可能并不能完全覆盖,但是我们提供解决方案,组件的设计始终秉持着不侵入业务的原则,所有与业务相关均给予配置入口。

    期望组件使用形式

    何为业务功能何为组件功能,这个需要具体的探讨,其实也没有严格意义上的区分。说白了,就是你买个手机,他都会送你充电器。但是。。。为什么很多手机也送手机壳(小米、华为、荣耀)但是 iPhone 却不送呢?所以到底是不是标配

    对于我们这个组件,简而言之:我们能做到的,我们都做!但是其中我们还是梳理出某些功能还是数据业务功能

    • navBar 上每一个 navItem 展示什么文案、样式属于业务功能

    • 整个 Filter 的数据处理,包括 url 上的查询参数需要抛给对应 navItem要展示的文案也是业务功能

    • Filter 是否点击滚动到顶部也是业务功能,毕竟很多搜索页 Filter 本身置顶。而且,对于 rax 而言,不同容器滚动方式还不同(但是我们提供这样的方法给你去调用)

    • panel 面板里面数据请求、逻辑处理都是你自己的业务逻辑。Filter 只提供基本的容器能力和接口

    换言之,Filter 里面任何功能都可以说为业务功能。但是我们需要提供 80%业务都需要的功能封装作为 Filter 的 Future。这就是我们的目的。

    • 筛选项关联Panel型,即筛选头和 Panel 是一对一关系,点击筛选头展示 Panel

    • 筛选项快速搜索排序型,即筛选头没有对应 Panel,点击筛选头直接触发搜索

    • 纯 UI占位类型,即纯 UI 放置,不涉及搜索,比如订阅按钮场景

    代码运行效果图如上截图。下面,简单说下代码的实现。

    开源版本(Ts+hooks+lerna)还未公布,所以目前还是采用 rax 0.x 的版本编写的代码。这里只做,有坑的地方代码处理讲解。欢迎各位大佬评论留出各位想法

    Filter.js

    先从 render 方法看起

    获取一些基本配置,以及 windowHeight(屏幕高度)和 activeIndex(当前第几个item 处于 active 状态(被点开))。

    之所以我们的 写在 上面,是因为在 weex 中,zIndex 是不生效的。若想 A 元素在 B 元素上面,则 render 的时候,A 必须在 B 后面。这样写是为了 panel 面板展开的下拉动画,看起来是从 navBar 下面出来的。

    renderPanel 方法就是渲染对应的 panel

    准确的说,这是一个 HOC,我们将代理、翻译传给 Filter 的影响或者 panel 面板需要使用的 props 传递给 Panel 面板。比如 onChange 回调,或者面板隐藏的回调以及当前哪一个 panel 需要展开等。

    由于 Panel 的面板复杂度我们未知。为了避免不断的展开和收齐不必要的 render,我们采用 的方式,将面板不需要显示的面板移除屏幕外,需要展示的在移入到屏幕内部。具体可见 Panel 的render return

    注意 Panel 面板的坑远不止这些,比如,我们都知道,render 是最消耗页面性能的,而页面初始化进来,面板名没有展示出来(此时面板 Panel 在屏幕外),那么是否需要走 Panel 面板的 render 呢?但是目前的这种写法,Panel 组件的生命周期是会都走到的。但是如果遇到 Panel 里面需要请求数据,然后页面 url 里查询参数有 ,navItem 需要展示对应的地理位置.如果不渲染 Panel 如何根据 id 拿到对应的地名传递给 navItem 去展示?对,我们可以拦截 Panel 面板的 render 方法,让 Panel render null,然后别的生命周期照样运行。但是,如果 render 中用户有对 的使用,那么就可能会造成难以排查的 bug。

    所以最终,为了提高页面的可交互率但是又不影响页面需求的情况下,我们提供了一个可选的工具:Performance HOC 。注意,是可选。

    通过配置Panel 的 shouldInitialRender 属性来告诉我,是否第一次进来,拦截 render。

    当然,Panel 也有很多别的坑,比如,现在 Panel 为了重复 render,将 Panel 移除屏幕外,那么,动画从上而下展开设置初始动画闪屏如何处理

    这里需要注意的是:NavBar 的数据是通过 props 传入的,如果状态放到 Filter 也就是 NavBar 的父组件管理的话,会导致 Panel 组件不必要的渲染(虽然已经提供 Panel 层的 shouldComponentUpdate 的配置参数),同时也是为了组件设计的高内聚、低耦合,我们将传入的 props 封装到 NavBar 的 state 中,自己管理状态。

    NavBar 中还需要注意的就是被动更新:Panel 层点击后,NavBar 上文字的更新,因为这里我们利用父组件来进行 Panel 和 NavBar 的通信

    最后 NavBar 中的 item 分为 快速搜索和带有 panel 的 NavBarItem两种,但是对于其公共功能,比如渲染的 UI 逻辑等,这里我们采用的方法是抽离 组件,供给 和 调用

    • NavBase 部分代码

    • NavRelatePanel.js

    Panel 核心代码

    Panel 的核心功能是对用户定义的 Panel.child 进行基本的功能添加,比如背景 mask 遮罩、动画时机的处理.

    Panel 的使用

    我们提供基础的动画配置,但是同时,也提供动画的 functionHook,这些都取决于动画的触发时机

    设置动画初始化样式中添加

    Filter 的组件看似简单,但是如果想写一个市场上较为通用和广泛的 Filter 组件,不仅仅是组件的颗粒度、耦合度和性能需要考虑,更多的是其中还是有太多的业务逻辑需要去思考。对于目前的初版(还未修改成正式开源版),已经基本涵盖了目前我们能够想到的业务场景,也已经有相关业务落地使用。

    当然,对于如果是直接放到业务中使用而不作为开源组件的话,我们可已经 Panel下的 child 通过 renderPortal 降低层级,通过 EventBus 或者 redux、mobx 等管理数据状态。那样会让整个代码逻辑看起来清晰很多。但是为了降低bundle 大小,我们尽可能的减少通用包的使用以及第三方插件的依赖。

    如果你喜欢探讨技术,或者对本文有任何的意见或建议,非常欢迎加鱼头微信好友一起探讨,当然,鱼头也非常希望能跟你一起聊生活,聊爱好,谈天说地。鱼头的微信号是:krisChans95 也可以扫码关注公众号,订阅更多精彩内容。
    最新文章
    deepl翻译手机版怎么翻译pdf文档?
      deepl翻译器官网安卓版是一款十分实用高效的AI翻译类软件,功能十分强大,专注于帮助用户进行各种语言的翻译,有着数百种语
    AI换脸好玩吗?看着这些真相,你就笑不出来:细思极恐!
    你的朋友圈被AI换头刷屏了吗?甚至登上了微博热搜。一个名为“ZAO”的AI换脸APP,昨晚忽然火爆全网!用户只需要在APP中上传一张
    Eclipse平台开发技术详解与应用
    Eclipse作为一个功能强大的开源集成开发环境(IDE),它起源于IBM的一个项目,并在2001年作为一个开放
    c++基础
    1. c++介绍 C++ 由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的,由于C++ 进一步扩
    cms网站开发
    CMS网站开发全攻略:从概念到实战本文将全面解析CMS(内容管理系统)网站的开发过程,从概念阐述到实际操作,帮助开发者了解CMS
    AI教程!入门必学的扁平矢量人物插画
    原图作者:Diana Stoyanova教程作者:设计师就业衔接班08期-56-爆米花指导:如如的设计主页交作业去这里→如何用简单的线条绘制
    21讲项目实战CMS-wordpress主题网站模板制作
     1、如何新建主题模板  找到文件夹wamp-www-wp-content-themes,然后在这里面新建  一个文件夹(名字自己取),把
    ai超级变脸如何创作
    超级变脸技术是一种利用人工智能算法实现面部替换的创意工具。以下是超级变脸创作的简要介绍:1. 选择工具:客户需要选择一个合
    42个关键词,带您读懂保定市政府工作报告
    [1]“十个紧紧抓住” 市委十一届四次全会要求,做好2018年各项工作,要突出“十个紧紧抓住”。 紧紧抓住中央、省一系列重大决策