最近公司的一个老旧的项目因为业务各方面原因突然活跃起来了,每日大概uv100
,pv能达到3500
。虽然不知道为什么uv
和pv
相差能那么大,但是由于使用多了,老项目的一些弊端就出来,需要不停地添加功能和修复BUG,所以我成了这个项目的前端接盘侠。
这项目技术栈大概是jQuery
+ backbone
,项目重构按照目前的情况来看短期是不可能了,所以要做的就是如何去优化。
问题
这个项目大概有差不多一年的历史了,在js文件里你随处可以看见下面这种代码,将函数挂载到全局变量上,然后又在另一个js文件里调用。
|
|
刚开始的时候的时候一脸懵比,后来已经习惯了,如果你在当前文件里没有找到该函数的声明,别急,随着html
里面js
的引用顺序挨个往前面翻就是了,总能找到。
下面才是今天真正的问题,我在某个文件里面看到了大量类似于这样的代码(样式class省略,内容进行了处理)
当数据产生变化的时候,都会出现类似下面的代码,由此产生了大量冗余代码。
同时jquery
的html
插入的实际上是清空了#target
里的DOM
,然后再插入重新生成新的DOM
,当然这样会有很大的性能损耗,其次每次这样操作都会产生大量重复的冗余代码。如果代码仅仅只有这么几行或者十几行或许不会有多大影响,但是我扫了一下整个项目,这样的代码粗略估计有至少200行以上了,后续开发中不可避免还会遇到类似的问题,所以写一个小插件解决这问题。
问题解决
为了解决上述的问题,我写了一个小插件Shaco
,名字来源于LOL中的恶魔小丑萨科的英文名字,寓意为神出鬼没
地解决视图渲染的问题。Shaco
的总代码量目前102行,其原理是通过数据劫持来监听(Observer)数据的变化,通过编译(Compile)来解析指定元素节点下的变量(Mustach语法),当数据产生变化时通知调用update的updateText刷新文本。
关于Shaco
Shaco
主要由三部分组成
Shaco
需要提供的参数为需要解析的元素, 其值建议使用id
唯一标志。然后就是需要Shaco
需要劫持的数据data
,务必为Object
。使用例子:
插件效果:
代码解析部分仅提供部分代码,详情请查看项目Github地址的lib/shaco.js
Shaco
关于Shaco函数部分, $el
为元素节点,$data
为需要劫持的数据,$save
用来存储模板解析含有变量的节点对象。
Observer
Observer
模块中通过defineProperty
去设置set
监听数据,当数据发生变化时,observe
新的数据,同时通知update
刷新视图。
Compile
Compile
模块中对节点进行解析,当节点是文本节点(即没有子节点)时进行compileText
,compileText
在处理是会把命中的节点压入$save
中。
updater
updater
在被劫持的数据更新时会被触发,此时会扫描数据,对$save
中节点进行遍历,然后更新数据。
性能问题
在进行视图渲染更新的时候,可以看到Shaco
只更新了对应DOM的nodeValue
而jQuery html()在进行视图渲染更新的时候,重新渲染了整个对应的DOM
对比一下两个操作耗费的时间,发现jQuery html()的大部分时间都集中在Rendering
和Paitning
上,而Shaco
因为只刷新来的nodeValue
所以没在这上面耗费多少时间。
题外话
Shaco
采用ES5
的语法编写,对于使用jquery
维护的老项目可以毫无顾忌的使用,不用担心任何问题。关于为什么不加入指令解析、watcher等?如果有这需要的话为什么不直接使用vue
呢?说到底Shaco
只是为一些老项目提供视图渲染方面的一个解决办法,减少冗余代码,而并非说是要徒手撸一个MVVM
框架出来。
关于input
使用Shaco
, 你可以这样做。
嗯,后来问了下项目当初是实习生
负责的,所以维护也理所当然落到了我头上!
╮( ̄▽ ̄”)╭”),估计当初也没想到这项目后来居然活了吧~
贴一张图~
老夫子写代码就用jquery,复制粘贴就是干.jpg
最后
Github项目地址:Shaco
在线Demo: https://blog.shanamaid.top/shaco/index.html