JavaScript 编程实践 - UI层的松耦合 (一)
更新日期:
这是一篇读书笔记,对书中的描述进行精简,归纳,总结,
有时也会自己写一些例子,感想和扩展 O(∩_∩)O~
UI层的松耦合
WEB开发中 UI由三个彼此隔离又相互作用的层定义(HTML,CSS,JavaScript)。
在实际场景中,css和JavaScript是同等重要的,两者更像是兄弟关系并非依赖关系(javascript依赖css)。
一个页面很可能只有HTML和CSS而没有JavaScript,
或………………只有HTML和JavaScript而没有CSS。
在所有Web UI中,JavaScript的正确运行不应依赖CSS—在缺少CSS情况下也要能够正确运行,尽管两者之间可能有互动。
1. 什么是松耦合
1.1 什么是耦合:
如果两个组件耦合太紧,则说明一个组件和另一个组件直接相关,
如果修改一个组件的逻辑,那么另外一个组件的逻辑也需修改。
耦合的例子:有一个贯穿整个站点的css类叫做error,被嵌入到HTML中。如果有一天你要改error这个名字为warning,不仅要修改CSS还要修改用到这个类名的HTML,HTML和CSS紧耦合在一起。
1.2 什么时候才能称作松耦合:
当你能够做到修改一个组件而不需要更改其他组件时,你就做到了松耦合。
松耦合是易于调试的,这对于代码的可维护性来说至关重要。修改某部分代码是不会破坏其他人的代码,那便是极好的 0.0’
在一起工作的组件无法达到“无耦合”,我们的目标是确保对一个组件的修改不会经常性地影响其他部分。
2. 将JavaScript从CSS中抽离
IE8和更早版本的浏览器中有一个特性让人爱少恨多,即CSS表达式(CSS expression)。
CSS表达式允许你将JavaScript直接插入到CSS中,可以在CSS代码中直接执行运算或其他操作。
设置元素宽度以匹配浏览器宽度
|
|
CSS表达式包裹在一个特殊的expression()函数中,可以给它传入任意JavaScript代码。
浏览器会以高频率重复计算CSS表达式,严重影响了性能。且难以维护。
IE9不再支持CSS表达式,老版本IE依然可以运行CSS表达式。
有人会用CSS表达式来让低版本浏览器里也达到和高级浏览器一致的表现,但尽量避免使用,以避免浪费不必要的时间精力。
总结:避免使用CSS表达式
3. 将CSS从JavaScript中抽离
CSS和JavaScript互相协作的很不错,所以我们经常将样式数据和JavaScript混写在一起。
JavaScript改CSS方式:
方式一(不好):style属性
直接修改DOM元素的style属性。
style属性是一个对象,包含了可以读取和修改的CSS属性。
如:修改元素文本颜色
|
|
评价:这种写法经常看到,但是这种写法是有问题的。
缺点:当出现样式问题,通常首先去查找CSS,而非JavaScript,浪费时间。
例外:有一种使用style属性的情形是可以接受的:
当你需要给页面中的元素作定位,使其相对于另外一个元素或整个页面重新定位。这种计算在CSS中无法完成,
此时可以使用style.top、style.left、style.bottom、style.right 来对元素作正确定位。
在CSS中定义这个元素的默认属性,而在JavaScript中修改这些默认值。
方式二(不好):cssText属性
给cssText属性赋值整个CSS字符串
|
|
评价:这种写法是一次性设置多个CSS属性的一种快捷方法,同样有问题。
缺点:比如设置单个属性时:将样式信息写入JavaScript带来了可维护性问题。
方式三(最佳):操作className
操作CSS的className
例:在页面中显示一个对话框,css中的样式定义像下面这样
|
|
在JavaScript中像这样将样式添加至元素。
|
|
|
|
|
|
|
|
|
|
评价:JavaScript可以随意添加删除元素的className,而className定义的样式则在CSS代码中。
CSS样式随时可以修改,而不必更新JavaScript。
优点:JavaScript未直接操作样式,保持了和CSS的松耦合。
4.将JavaScript从HTML中抽离
很多人学习JavaScript之初所做的第一件事是,将脚本嵌入HTML中来运行。
绑定事件方式
方式一 (不好):使用on属性
使用on属性( 比如onclick )绑定一个事件处理程序
|
|
评价:此写法2000年时非常流行,尽管这种代码多数场景下是正常工作的,但却是两个UI层(HTML和JavaScript)的深耦合,这种写法有一些问题
缺点:
- 点击事件发生时,doSomething()函数必须存在,否则会报JavaScript错误,页面或弹出错误信息或点击事件不会有任何响应。
- 如果修改了doSomething()的函数名或如果此时点击按钮调用了其他函数,需要同时修改JavaScript和HTML代码。给维护带来了困难,这是典型的紧耦合的代码。
方式二(最佳): 通过script标签来引用
绝大多数(并非所有的)JavaScript代码包含在外部文件中,并在页面中通过script标签来引用。
对于支持2级DOM模型的浏览器来说,用下代码可完成上面例子中的功能:
|
|
关于addEventListener()函数:
IE8及其更早的版本不支持addEventListener()函数,因此需要一个标准的函数将这些差异性做封装。
|
|
我们常常像下面这样来使用这个方法
|
|
如果你用了 JavaScript 类库,可以使用类库提供的方法来给元素挂载事件处理程序
这里给出一些流行类库中的实例代码。
|
|
|
|
|
|
评价:优势在于,函数doSomething()的定义和事件处理程序绑定都是在一个文件中完成的。如果函数名称需要修改,则只需修改一个文件;
如果点击事件发生时想额外做些动作,也只需在一处做修改。
优点:不需同时修改多个文件,可维护性提高,实现了松耦合。
方式三 (不好):HTML中内联的脚本代码
在HTML中使用<script>标签,标签内包含内联的脚本代码。
|
|
评价:最好将所有JavaScript代码都放入外置文件中,以确保在HTML代码中不会有内联的JavaScript代码,利于调试。
缺点:不利于确信(而非猜测)从何下手调试bug