前端组件的构建
大多数前端新人(至少不久之前我也是这么想的)对于前端组件的定义都认为是JavaScript组件,CSS只是一个皮肤,而HTML由JS动态生成。个人认为这个构建思路有点过时。
前端是由多中语言组成的,不仅仅是JS。从HMTL5的发展来看,CSS添加了动画等功能,HTML的标签更语义化。套用标准的MVC结构:CSS是View,html是model,JS则承担了一个逻辑控制的作用:control。所以说一个前端组件大概构成如下:
- CSS样式文件
- html文件
- js文件
貌似这和现有的那些组件差不多,其实是一样的。看你是如何对待了。你也可以把html与CSS都看成是这个JS库的demo,这就是之前所说的:前端组件都是JS组件的情况了… 虽然实际使用这个组件的时候你很可能把demo中的html和CSS都拷贝过来!
闲话少说如何利用之前的想法构建一个“前端组件”呢?
举一个链接hover上去滑动的例子:nudging组件。
CSS3的transition样式可以提供过度效果。
同时低级浏览器不支持这个样式,那么需要用JS去实现。
这是我们就得到如下的代码:
JS:
G.def('nudging',function(){var style = document.createElement('a').style, supportAnimate =false, prefix =['-o-','-webkit-','-moz-','-ms-'];for(var i=0; i < prefix.length; i++){if( style[ prefix[i]+'transition']!==undefined){ supportAnimate =true;}}/* * 链接放上后滑动 */var nudging = $.fn.nudging =function(/*@dom/selector/jquery obj*/dom ){var $this = dom ? $(dom):this; $this.hover(function(){//mouse in $(this).animate({ paddingLeft:'20px'},400);},function(){//mouse out $(this).animate({ paddingLeft:0},400);});}return{ nudging:nudging, cssSupport:supportAnimate };});
html:
<ul><li><ahref="#"class='nudging'>Link 1</a></li><li><ahref="#"class='nudging'>Link 2</a></li><li><ahref="#"class='nudging'>Link 3</a></li><li><ahref="#"class='nudging'>Link 4</a></li><li><ahref="#"class='nudging'>Link 5</a></li></ul>
css:
.nudging { cursor: pointer;-webkit-transition: padding-left 250ms ease-out;-moz-transition: padding-left 250ms ease-out; transition: padding-left 250ms ease-out;}.nudging:hover { padding-left:10px;}
demo
主要的思路是:如果CSS transition不支持则使用js实现。
这个组件提供了一个API:nudging。这里的API不仅仅是JS的nudging方法,还有CSS class:nudging!这个组件使用的module没有限制。那么依据这些,我们可以写出这个组件API文档:
API:
- function nudging:使用JS实现链接的nudging
- var cssSupport:判断浏览器是否支持CSS transition
- CSS class nudging:使支持CSS transition的浏览器的链接有budging效果
HTML Module:无限制
同样的方法可能实现很多这种组合性质的“前端组件”。
正确使用CSS API
或许有人会问,为什么不直接使用JS来修改style,达到动画效果呢?这样代码全都在js中,方便拷贝!
首先这个效果很简单,但是如果是多个元素构成的复杂效果,我们需要使用JS多次操作dom。有点前端开发经验的都知道dom操作就是前端开发的瓶颈所在!
其次不利于统一的管理,当使用JS来操作UI时。我们就需要将操作UI的代码单独独立成一个函数,函数可能被复用。如果你要新建出一种效果,这要新建一个函数。久而久之,代码中充满了UI的操作函数,和其他逻辑函数混杂在一起。或许你可以起一个好听的名字xxxUI等等,但是我们可以更加优雅的用JS来调用Class API来实现:
$(dom).addClass('nudging');
最后谈一下:何时生成html
有了HTML Module并不代表着组件中失去了“生成html”这一过程,比如:头像剪切组件。很多的UI是在选中并上传头衔之后才会出现,也就是说一开始显示并不需要,而且不一定会使用。这是将HTML临时生成最为合适!
不过这并不是让把这些html模型嵌入到JS中,模型和控制还是要分开。可以把html模型放到demo中的JS,这样就可以起到分离的作用。
总结
最重要的一点是:控制、显示、模型三者分离,抛弃后台开发程序员时候的一种语言定天下的思路:前端组件不仅仅是JS。虽然目前在显示方面,大部分的动画效果还需要JS来实现,不过随着CSS3的普及,显示将逐渐归为CSS处理!
当然这也不是没有确定,代码的分离必然造成了“拷贝”的不方便。这就需要一个好的代码管理和合并机制,这样就只需要
@import nudgin.css @import nudgin.js
这样简单的语法糖就可以实现目标了。
类别 design, javascript
标签 css, html, javascript, nudging, 前端组件
mark
支持文中的部分观点。例如,可以用CSS写的就用CSS写。若要改变 CSS 值,也只是通过赋予元素不同的Class Name 来做。
你难道不知道如果再写一个不加前缀的 transition 就可以多支持一个网页浏览器么。
回一:
再次声明:后端不是一个语言定天下,中间嵌入的语言也决不仅仅只是辅助作用.这和我国体制没有关联,在我国其他党派可以不作为,但是没有T-SQL就不能没有,而且作用很大,数据库建模,T-SQL语句优化.都是不可或缺的部分,所以我不赞成他们只是起辅助作用.
回二:
只要DOM是按照一定顺序解析的,HTML永远不能作为纯粹的Model.
不是只用Good Parts他就能成为Good Model.HTML本来就是用于显示的.还是那句话”不一定非要硬往MVC上套”.
回三:
1.HTML不是没了CSS就不能显示,至于美丑这里不表.但是有个例子:reST转为HTML就是使用基本的HTML用于显示,我不觉得他有多丑.
2.CSS是用于美化HTML,但是请注意:CSS能够美化HTML完全是因为他的选择器,将HTML作为完整的DOM,但是反过来说,你觉得一个Model就非要包含完整的模型路径不可?再次重申,HTML不仅仅是Model.
回四:
模块绝不仅仅是限定在一个包中.包是他的表现形式之一而已,在Linux中有无数多个包.他们作为模块并没有完全独立相反有相当的依赖关系,也就是说一个模块绝不仅仅只能是一个包所包含的.
模块就是将职责分离出来,逻辑独立出来,这是方便修改的.又怎么会疲于”修改和调试是件非常麻烦的事”.如果出现这种症状我觉得是方法不当,当然术业有专攻,我也知道其中有不少困难,包括我在内肯定有不少人很烦JS和HTML交互耦合的情况,特别是在调试功能普遍不给力的情况下.
但是我想举个例子,我在后端开发经历了两款不同的开发工具,vim和VisualStudio,当我使用VisualStudio中时是无论无何也都无法接受用诸如记事本之类的文本编辑就能开发.Net程序这种荒妙之谈.但是现在使用vim编写python之后,又有了所有IDE都只是浮云之感.当然这和平台有着必然的联系,但前台JS环境下的谁又能说不是呢?
Ext 正式这样一个例子,将所有逻辑富含在JS中,但是高度组建化的结果是媲美Flash的JS应用大行其道.当然谁有能说Ext不复杂呢.其中利弊供君参考.
回五:
引入Script标签和使用@import 有什么很大的区别吗?真的就是南橘北枳的差别?
压缩在一起的是完全重用的模块,至于其他拓展模块还是会需要另外再分一个文件.
回六:
正如现在流行的Java,Ruby,相反我想没有多少人会去用汇编写网站,为什么?性能不重要?还是开发效率更具有产值?
当Java发展时,声势盖过了C.就没有人诟病Java执行效率?答案是否定的.
如果时间倒退二十年,在那个锱铢必较的年代,开发效率确实不值一提.
但是在双核遍布,内存上G的时代,你还在为几kb作茧自缚,不能紧跟时代步伐.
摩尔定律也许在软件开发一样适用.每隔十八个月,软件开发的产能或许就能因为成熟而又高度可复用的模块而提高一倍.
难道为了极少部分没有升级配置的用户而抛弃大多数配置标准的用户?
亦或是绞尽各种Hack去顾及各种老版本的浏览器.还是说放弃这部分用户,为大多数用户创造更美好的体验?
与其为了支持几kb都能成为瓶颈的用户的浏览,倒不如去为几千万标准配置的用户谋福利.
软件有一万种实现方法,但始终是为用户服务,开发效率和执行效率不是一对矛盾,开发体验和用户体验更不是水火不容.选择权在你手中.
第一,我所说的后端的一个语言定天下,是指在后端中一个模块基本上只使用一种语言。即使是中间嵌入了其他的语言,那也只是辅助作用(和我国的现有体制类似)。但是前端则是三权分立的结构,每个语言都有自己负责的方面。更重要的是JS不是在前端中占主导位置。
举个例子,别人问你你们网站的后台用什么开发的,你肯定会说python/java/.net这样的一种语言,你觉对不会说是sql。但是前端开发没人会说是JS开发的。
第二,HTML虽然在设计的时候不仅仅是Model,它还有b,s,u这样的样式标签。但是在前端开发中非常不建议使用这样样式的标签。这是语言的设计问题。以现在HTML5推行的思路来看,HTML就是起到了数据模型的作用。至于你说的HTML包含CSS,JS,图片…那是不对的,HTML并不包含这些东西。就像python代码用了数据库,难道就能说python包含了数据库?重要的一点是:我是在谈如何更好的使用前端语言来设计组件,就像Douglas Crockford谈javascript一样,只使用Good parts,摒弃掉bad parts。
第三,我并不支持在前端中使用MVC模型(这在我得另一篇文章中提到过:http://mzhou.me/?p=95230),在这里提到只是为了解释方便。浏览器是解析HTML生成页面的,但是现在网站如果没有CSS那还能看吗?(即使你的语义化做的很好)HTML解析之后得到是dom树,然后浏览器把默认样式添加到这些dom元素之上得到了显示的网页。注意:即使你没有使用外部的CSS,浏览器还是会用内部的CSS去绘制页面。HTML仅是存储数据的容器,CSS也不局限于外部的CSS。这一点CSS权威指南中的有关优先级的一章有提到:还有客户端CSS的存在。
第四:你对于模块的理解有些偏差,你给我的感觉是:认为一个模块就应该在一个文件或者包之中。编程中模块是一个用于提供特定功能的代码集合,并且提供一个统一的对外API。一个模块是可以拥有自己的子模块的,换言之我的前端组件是一个模块,每个模块又分为JS、HTML、CSS三个子模块。他们还是一个统一的模块,只不过处于不同的文件中。这样做就是拷贝麻烦。但是前端遇到最多的情况不是拷贝代码而是修改,如果你的HTML放在JS里面那么调试和修改将是一个非常麻烦的事情,不是你想的那么简单。
第五:即使你把一个组件的代码放在一个JS里面,当你要使用它的时候,也不是仅仅把JS添加进来那么简单。因为如果你有多个组件,你不可能增加多个JS连接,减少连接数是很重要的性能实践之一。唯一的好方法就是用工具来实现加载,但是既然你已经通过工具来使用这些JS了,为什么不去使用另外一种工具去实现我所说的载入组件的方式呢?(@import方式,见文章最后)
第六:我认为做前端开发(其他开发也一样)性能是很重要的,即使它是零点几毫秒。平时在打包时候压缩代码,图片其实能获得的提升可能就只有几毫秒,但是这就是好前端与一般前端之间的差距。所以动态生成本来就要显示HTML是很不合适的,不要过多的操作dom,这是性能的瓶颈所在。
这句话说的最后页最终要:不要以开发的体验优先,要以用户的体验优先。
第一:
后端没有一语言定天下.相比前端的多浏览器.后端还是非常多的领域语言必须掌握,多个平台的区别(不是浏览器),T-SQL访问数据库,shell管理服务器,而多个业务平台交互更是交融反复(调用C模块只是一个小例子,为什么XML曾经被寄以众望. Web Service不正是为了解决这种跨平台的工具么)
第二:
HTML绝不仅仅只是Model.还有多的视图成分在里面.HTML在很长的一段时间里都被人诟病,因为包含的内容太多,CSS,JS,图片甚至其他Flash,Java app…不能不说混杂.即便如今html5也改变不了他的视图身份,这里要注意:浏览器是解析HTML来生成页面的,而不是CSS,HTML由于包含太多,所以不能仅仅作为模型存在.
前端也不一定非要往MVC里硬套.而且MVC本身存在很多问题,诸如结构不灵活,衔接不紧密等等.所以又会有MVP,MVVP等多个拓展模式.需要注意的一点,MVC提供给我们最基础的是一种分层思想,而不是固定不变的视图模型和控制器.
比HTML+CSS+JS更MVC的应该是XML+XSL+XPATH,这套组合才是完全的MVC.CSDN就是使用的这套.
第三:
将部分功能独立出来时,犹豫HTML本身包含太多,所以还是会碰到又要copy CSS, JS之类的.
我曾经也碰到过,那时我的解决方法是全部动态加载,使用JS.益处是完全作为了一个独立的模块,引入js就可以了,弊处就是所有修改都在JS总以字符串的形式修改,没有IDE的辅助略显麻烦,但是他们(HTML,CSS,JS)谁又不是能任意编辑的字符呢?