技术分享 | 【工程化】越抽象,越通用

2023-10-30 14:29:41 浏览数 (2)

以下内容比较抽象,均为理论内容,对于喜欢看代码的也不妨驻足,对代码规范可能有所帮助

导言

作为天天和js打交道的前端开发,组件一定是不少用的东西,如果你是写组件的,免不了考虑多种多样的场景。

由于我的文章5000多字,突然被清空了,气死我了,所以直接从一个案例开始讲起,不必要分开了。

从案例出发

甲方有个文章推广用的小程序,简单来说小程序核心部分发布推广需求有如下功能

  1. 需求标题
  2. 预期需求
  3. 推广平台
  4. 平台uid
  5. 推广内容

以3个月前的使用来看,暂时没有出现问题,大部分用户都用得好好的,但是越往后面,因为个别平台出了新的政策,例如A平台不给用户开放uid展示了,B平台不只是可以发表文字了,C平台未来对流量考核方式变了......这时候,原先的4满足不了A平台,5满足不了B平台,2满足不了C平台,作为尽职尽责的程序员,我们总不能让用户自适应吧,但是那个老六外包公司,做完之后没给源码,导致该动起来基本没办法,只能推倒重做了,抓包发现前后端交换的数据结构已经写死,没有办法通过前端更改数据结构的方式来改变整个应用的主要问题。

出现了什么问题

简单来说,就是数据和渲染不够“抽象”,他们把最底层的东西写死了,封成了一个几乎没法改动的成品数据,而渲染他们的组件也过于表层,想要实现功能却被组件限制住了。

什么是“抽象”

在以前,前端能实现的动画效果不是很多,有人想要五彩斑斓的背景渐变色,css就加入了linear-gradient;又有人想要毛玻璃,就有了backdrop-filter;这还没完,客户是上帝,又有人想要各种五彩斑斓且背景多变甚至随机根据光线变化的渐变,css可撑不住了,因为再加更多的特性,也满足不了客户的欲望,所以这时候canvas出现了,要做什么用户自己来定,我可不管了。

这个例子,就说明css还不够抽象,canvas比css在某些方面更加抽象,因为可定义的更多。

一般来说,越底层越抽象,如果一个html页面上全是canvas,确实挺抽象,因为你不懂这页面要干什么,而这个页面又可以实现各种各样的功能,比如绘制一个矩形,一个圆形,甚至往里面渲染3d模型,3d动画,渲染一个游戏等等等等,这样巨高度的定制化,就很“抽象”。

怎么“抽象”它

前端

回到甲方的需求,B平台既然可以发表图文并茂的内容,5就不止局限于<textarea />组件,仔细想一下,一个编辑器,一定就是textarea,input吗?

例如腾讯云的这个编辑器

它是一个span标签。为了实现输入功能,加入了可以编辑的属性contenteditable,作为开发者,我们也应该有这样的思路,既然不局限于文字,是不是可以从最本质的div,span等基本标签入手,用这些最基本的标签来实现该有的功能

简单复现一下甲方的代码:

代码语言:jsx复制
function App() {
    return (<>
        <Editor />
    </>);
}

function Editor() {
    return (<>
        <Input color="xxxx" width="xxxx" value={<>我永远<p color="red">喜欢</p><b>爱莉希雅</b></>} />
    </>);
}

function Input({ color, width, value }) {
    return (<input type="text"
        style={{
            color, width
        }}
        value={value}
    />);
}

App里面只有一个编辑器,而这个编辑器因为所有的页面都是一样的,所以当时就写死了,再往深层剖析

  • Editor是更深一层的抽象,表明了这个编辑器由一个输入框组件来实现
  • 输入框是Input,又是更深一层的抽象,里面的组件<input />就是html最基础的元素,用来实现表单输入

可以看出,越抽象的地方,代码越接多,这些代码是为了实现功能而一层层封装的。

只不过甲方没有考虑到项目的未来,把第二层抽象Editor部分完全写死了

后端

前后端数据交换是必不可少的部分,开始之初错误的估量,会引导整个项目错误的偏向

比如他们的数据

代码语言:javascript复制
const data={
    title:'我最喜欢的角色',
    content:'菲谢尔',
    uid:123456,
    satisfaction:1000,
    platform:'tencent',
    text:'大家都知道n我永远喜欢菲谢尔n但是为了模拟数据,我不得不喜欢',
}

因为在开始之初就认为所有平台的数据模板都是这样,导致了出现了麻烦,title,content等全部只能输入字符串,没有为富文本考虑

  • title一定只能是纯字符吗?我可不可以让某个字换颜色显示?
  • content和text一定是纯文本吗?可以不可以添加多媒体?甚至往里面加入其他页面iframe?
  • uid只能是纯数字吗?有些平台没有uid怎么办?
  • satisfaction一定是预期的“阅读量”吗?有些平台是阅读时间呢?或者是预期收入呢?
  • platform一定只有一个吗?

这些问题,是在项目初期就得要考虑到的,要结合项目的过去,现在和未来考虑,因为前后端交换数据是更抽象的问题,前端页面你可以一个人改,后端如果不是你负责,万一哪天想要改动数据结构,让你的几十个同事半夜加班动服务器,这一动,有可能在线的客户都要受影响。

所以我的考虑就是让数据结构变成这样

代码语言:jsx复制
const data = {
    title: {
        jsx: false,
        content: '我最喜欢的角色'
    },
    uid: {
        disableInput: ['arsrnairs'],
        map: {
            'tencent': 12345,
            'arsrna': 123456
        }
    },
    content: {
        jsx: true,
        content: <>我永远<p color="red">喜欢</p><b>菲谢尔</b></>
    },
    satisfaction: 1000,
    platform: ['tencent', 'arsrnairs', 'arsrna'],
    text: {
        jsx: true,
        content: (
            <>
                大家都知道<br />我永远喜欢<i>菲谢尔</i><br />但是为了模拟数据,我不得不喜欢
                 <img src="......"/>
                <Footer /><OtherContent {...someArgs} />
            </>
        )
    },
}

我不知道甲方原先是不是jsx写的页面,但是既然项目都要重写了,而且我喜欢jsx的语法,那就这么定了。

可以看到数据量大了不少,而且能定义的东西更多,至于多了什么,自己看吧。

如果嫌每次都要写这么多数据比较麻烦,还可以简单封装,比如ABCDE平台都是这一个模板,就可以写一个生成数据的函数

代码语言:javascript复制
function getData({
    title = "我喜欢谁",
    uidList,
    content,
    satisfaction,
    text
}) {
    const data = {
        title: {
            jsx: false,
            content: title
        },
        uid: {
            disableInput: [],
            map: uidList
        },
        content: {
            jsx: true,
            content
        },
        satisfaction,
        platform: ['tencent'],
        text: {
            jsx: true,
            content: text
        },
    }
    return data;
}

只用简单输入几个数据就能生成整个数据,而且不影响下一层抽象的功能,一举两得。

学会留空间

我的这个用了4年的ppt,顶部和背景从未变过,变的只有内容

可以想象成一堆抽象的元素,除了顶部和背景是写死的,其他地方是抽象的,因为我不知道未来会有什么,可以自由发挥,自由定制。

通用框架为什么能流行起来?

像react的脚手架create react app,你可以用react写出各种各样的页面不受影响,你可以做成游戏,也可以做成企业官网,甚至腾讯云的控制台

这些都是由你来决定,但是因为它不是最深层的抽象,你无法实现一些更深层的功能,例如polyfill,一些浏览器可能不支持es6的新特性时,没有polyfill就没法弥补这些功能。

再比如Antd,tdesign,jQuery,bootstrap,moment,lodash等等无论是ui库还是函数库,他们都有共同的特点,那就是可以随意定制,Modal模态框组件,弹出来的窗口不一定只能是文字,你可以弹视频,弹音频,弹广告等;moment.js的format函数不一定让你一定得是unix时间戳输入,你可以定制HH-mm-ss,也可以mm-ss-HH,一切由你决定。

用户是上帝

假设有一天,react来了个逆天举措,把audio封成了一个播放器组件,这个音频组件东西可多了,有歌词,有进度条,有控制器,均衡器,音效面板等等等等,这时候你页面上乱七八糟的audio,又是歌词又是音效的,我们根本不需要这么多,但是人家封死了你不得不用那么多,或者我用上了歌词,但是我想改变颜色,但没有接口,这下可就麻烦了。

多留空间给用户,你可以默认,但不能写死,用户写什么就是什么,用户不写我就默认。

我们留给其他开发操作的空间,绝不仅限于一两句数据,该抽象还得抽象

嫌麻烦可以封装,但是要保证最基本的方法是可改的。

总结

好的工程一定会考虑明天,而工程化里的组件通用化只是整个项目的小部分,各种代码规范等一起完善起来,才能让项目持久发展。

我的5年老站,毫不夸张地说,直到今年才逐渐从jQuery转为react

这些效果也是jQuery来实现的

jQuery一个近20年的框架,在今天仍然影响着大部分前端框架的发展,因为它操作dom的思想很超前,用本文的话说就是“抽象”,它很简单,但是可以组合成很复杂的工程,只不过在今天它很难满足日益增长的需求,各种新框架应运而生,仍然可以看到里面有jQuery的身影,这些框架部分代码,其实就是把jQuery封装了起来,变成浅一层抽象的组件,给用户使用。


感谢您阅读至此

Ar-Sr-Na 未经允许禁止转载

0 人点赞