前端降维术 作者: 灯小笼 时间: 2017-06-21 分类: 前端 这里说的前端,指的是传统意义上的前端,即包括HTML、css、javascript三种技术手段的前端。“降维”,顾名思义,就是降低维度,使问题涉及的因素减少,变得更加容易解决,而且解决方案较为简单可靠。 在著名的刘慈欣的科幻小说《[三体](https://book.douban.com/subject/2567698/)》里,”降维攻击“就作为一种常见于宇宙高级文明攻击低级文明的手段。比如,生活在四维世界的人们,他们是用”降维攻击“对付三位世界的人们。虽然与此同时,他们自身也会降维,但是从四维降低到三维,他们依然是活着的;而三维世界的人们,则被无情地抛入二维世界,不可逆转地失去生命和一切。不过,到前端这一块技术领域,还不至于这么残酷,我们只是想通过降维的手段使问题简化。 通常,由于开发人员对前端各项技术的细节了解不够透彻时,会提供需要综合运用多种技术手段解决的方案。而这几种方案的组合,彼此依赖,互相耦合,往往理解起来较为晦涩难懂,也不具备较好的可维护性和可扩展性。前端的降维术,则旨在通过对某一项技术更加彻底和升华地使用,显著减少对另一项技术的依赖,从而提供更简单易扩展的解决方案。比如,某些开发人员对于js的使用不够熟练,但由于对html和css的理解也不够深厚,很容易通过js去组装页面元素,或者拼接表单数据,然后提交到后端页面实现页面的保存。这样的技术方案,后期如果需要修改界面展示效果,或者对表单交互效果进行调整,一方面还得通过js调整达成效果,另一方面则容易导致不容易发现的bug产生。如果我们掌握一定的技巧,完全可以巧妙地避开对js的使用,使问题只依赖于html和css两个维度,就可以使问题得以解决。 ## 排序 网站常用到的功能就是排序,一般的思路大抵是在排序的子元素上定义一个属性,将需要排序的id放到上面,保存排序的时候,通过js依次将这些属性id提取出来,合并成一个字符串,提交给后端处理处理。 首先,设定一下开发环境:使用jQuery,且假设有一个plugin,名字叫sortable,设置后可以对元素启用排序支持。 ### 方案一 前端代码如下: ```html 1 2 3 ``` 服务端的代码大抵如下: ```php $ids = explode(',', $_POST['ids']); DataModel::sortIds($ids); ``` 在这个方案里边,需要我们掌握html元素自定义属性以及js的数组的基本用法。而一些对js数组不熟的同学,可能还会想到通过各个id后面拼接逗号构建id的字符串。 ```javascript var ids = ''; $('sortList li').each(function() { ids = ids + $(this).data('id') + ','; }); ``` 甚至,为了去掉拼接的字符串中最后的“,”,他们需要掌握一些额外的技巧: ```javascript var ids = ''; $('sortList li').each(function(i) { if (i == 0) { ids = $(this).data('id'); } else { ids = ids + ',' + $(this).data('id'); } }); ``` 然而,对于这类需要将数据保存到服务端的交互,使用form和基础表单控件来做,根本就不需要掌握自定义属性以及js数组算法等知识。 ### 方案二 改进后的前端代码: ```html 1 2 3 ``` 改进后的后端代码: ```php DataModal::sortIds($_POST['id']); ``` 乍一看,改进的方案的代码量并没有减少,甚至还有增多。但这样的方案,却只需要掌握基本的html用法,也没有涉及到js数组的用法和自定义属性的获取。这些基础的知识点,是大部分web开发者所熟知的,而且是很稳定的,不存在任何不稳定性。 再对比一下服务端代码,第一种需要掌握字符串分隔成数组的用法,而第二种,php自动将name为id[]的表单项自动转化成了数组,不再需要额外处理了。 再从扩展性来看,第一种方案的click方法里边,存在的外部变量有:`$('#sortList li')`这里边的元素`#sortList`以及`li`子元素的元素名称、自定义属性的名称`data-id`、ajax提交的`type`和`url`、以及回调函数`success`。而第二种方案,表单提交的这块代码,则只有回调函数是外部变量。甚至,我们可以将这样的表单提交行为封装成一个jQuery组件。 ```javascript jQuery.fn.ajaxform = function(callback) { this.submit(function() { type: this.method, url: this.action, data: $(this).serialize(), success: callback }); }; ``` 这个组件,作用就是将form表单提交转化为ajax提交。在这个基础上,第二种方案的前端部分可以简化为: ```html 1 2 3 ``` 而要想将第一种方案的交互模式也组件化,则有着更大的困难,而且涉及的参数过多,即使组件化,使用起来的体验也不一定爽。 ### 小结 对于前后端数据交互的场景,尽量使用form表单来处理,结合对隐藏域,name属性的数组化(及name="xxx[]"的模式)等,就能对表单处理异步化的应用,就能显著降低对js和html更多额外知识的需求,提升功能的稳定性和可扩展性。 标签: 前端, 降维, html, javascript