我们知道HTML样式定义的三种方式:

<link/>外部引入也就是定义 CSS 中的
<style/>嵌入式样式
style特性地定义

给一个HTML元素设置css属性,如:

var head= document.getElementById("head");
head.style.width = "20px";
head.style.height = "10px";
head.style.display = "block";

这是 DOM2 级样式提供的 API 了,这里总的来说还涉及了3个问题,当然也是 jQuery 内部需要解决与优化的问题。

1.单一的设置太麻烦,而且每次style一次就等于浏览器要绘制一次,当然高级的浏览器是可能会合并 style 的次数的
2.style 接口只能针对行类样式,对于 link 引入的样式,无法获取
3.样式属性名的兼容问题,比如驼峰,保留字 float 任何支持style特性的html元素在js中有一个对象的style属性,其实也是一个实例,但是内部属性命名都是采用驼峰形式的,如background-image要写成backgroundImage,其中一个比较特殊的就是float,保留字,所以就缓存cssFloat,ie:styleFolat,然后对于width,height这些处理都最好有一个量度单位。 合并cssText
var head = document.getElementById("head");
head.style.cssText = "width:200px;height:200px;";
和innerHTML一样,cssText快捷而且所有浏览器都支持,cssText只需要一次reflow,提高了页面渲染性能,当然如果是在创建的时候,我们还可以利用文档碎片,缺点自然就是样式被整体覆盖了,所以在处理的时候应该要先获取需要保留的样式然后再拼接起来。
样式访问
DOM2规范增加了defaultView接口,提供了getComputedStyle()方法可以返回了类型style属性合集。 getComputedStyle与style的区别
getComputedStyle是只读的,style是可读可写的 css的钩子机制
jquery提供一个api来条用用户自定义的函数,用于扩展,以便获取和设置特定属性值,在attr,prop,val和css的操作中都会引入钩子,钩子都有相似的结构。 var someHook = {
  get:function(elem){
    return "something";    
  },
  set:function(elem,value){
    
  }
} 在css3属性浏览器兼容的时候,都需要特定的前缀
Webkit内核浏览器:-weblit-border-radius
Firefox内核浏览器:-moz-border-radius 采用css hook可以标准化这些供应商前缀的属性,让css接受一个单一的标准的属性的名称(border-radius或用DOM属性的语法borderRadius)判断的代码省略,给某一元素设置borderRadius为10px.
$("#element").css("borderRadius","10px")

为了做浏览器兼容,我们不得不:

if(webkit){
   ........................
}else if(firefox){
  ...........................
}else if(...)更多

这是一种最没技术含量的写法了,如果我们换成一种 hook 的话:

$.cssHooks.borderRadius = {
get: function( elem, computed, extra ) {
return $.css( elem, borderRadius );
},
set: function( elem, value) {
elem.style[ borderRadius ] = value;
}
};

$.cssHooks 对象提供了一种方法通过定义函数来获取和设置特定的CSS值的方法,它也可以被用来创建新的 cssHooks 以标准化 CSS3 功能,如框阴影和渐变。

样式操作接口

jquery操作样式的接口jquery.fn.css与jquery.css

css:funtion(name,value){

  return value!=nudefined ? jquery.style(elem,name,value) : jquery.css(elem,name);

}

最终方法与设置样式的方法是实例方法,所以我们看传递的参数就知道了,只能是单一的elem,name,value实参。

jquery.style(elem,name,value);

jquery.css(elem,name);

所以如果我们传递是对象或者别的方式就需要一个过滤的环节,css参数的处理也跟以前的attr属性的处理保持一致,无非就是递归参数。

jquery.css()取值

用户传递写css属性名时可以很随意的,backgroundColor,backgound-color,所以框架内部自然要过这个统一的处理。

Query.css()取值

用户传递写 css 属性名是可以很随意的,backgroundColor,backgourd-color,所以框架内部自然要过这个统一的处理。

检测是否是驼峰写法,如果不是就得转化下:

origName = jQuery.camelCase( name );

其次还有一些特殊的属性名的读取问题,比如float就是关键字,就需要转成cssFloat,还有浏览器前缀的命名处理。

name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));

我们知道元素在 display:none 的情况下是无法获取一些跟布局定位有关的值的,还有不同的元素尺寸width、height、margin获取问题等等,但是这么多情况如何去处理?

jQuery在这里就引入了“css钩子”

hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];

每一个特定方法都带有各自的处理模式,举个例子如果要获取 ele.css("width")。

那么 cssHooks.width 中就是这样一个结构:

cssHooks = {
width:{
get:function(){},
set:function(){}
}
}

我们看到 cssHooks 几乎都是针对盒子模型的属性处理了,我们考虑下如果用户获取一个元素的 width 会有什么情况?

1. 元素在隐藏 display:none 先获取不到尺寸
2. 元素的宽度,jQuery就有width、innerWidth、outerWidth等各种不同取值方式
3. 元素可以被设置css3的盒子模型

所以针对这一种特定的属性我们需要单独拿一个钩子做处理,那么在取值的时候,我们自然在 cssHooks.width.get 中要判断一下:当元素是否是可见状态,如果不是则要先处理下,在之后判断盒子模型的处理。接下来我们看到如果没有对应的钩子方法,我们模型采用了 curCSS 取值:

if (hooks && "get" in hooks) {
val = hooks.get(elem, true, extra);
}
if (val === undefined) {
val = curCSS(elem, name, styles);
}

其内部就采用了 defaultView.getComputedStyle(elem, null);最终就是通过 getComputedStyle的getPropertyValue 方法了。

所以总结 jquery.css 的接口其实也很简单。

1.转化样式命名
2.处理特殊的属性比如float
3.分离出一个钩子,用于处理跟尺寸有关的属性
4.其余元素采用getComputedStyle获取对应的值

样式的赋值

样式赋值处理的方式与 css 类似,只是要注意了 style 才具有样式的修改权限,这样的传对象其实都是需要调用多次 style 处理的,当然没有采用 cssText 的方式处理,因为本身以前的属性就会丢失了,值得注意的是,设置样式的时候我们是可以传递一个对象为参数的:

$div.css({
'padding' : '50',
'margin' : '50'
})

可以一次让元素添加多个属性,那么因为我们内部没有采用 cssText 去处理,而是靠的 style 接口,那么意味着就需要针对 jQuery 的参数去修正,换句话说我们就需要通过for in或者each去遍历这个参数,分解出每一个属性赋值给 style 接口。针对参数的多形式 jquery 在之前会通过一个 jQuery.access 方法过滤这些参数,原理就是针对字符串、数组、对象的一个遍历而已。

jQuery的处理流程:

1. 分解参数
2. 转换为驼峰式,修正属性名
3. 如果有钩子,则调用钩子的set get
4. 最终实现都是依靠浏览器自己的API的

样式类操作

通过给元素添加删除指定的样式类名用来修改样式的方法有 addClass removeClass,为每个匹配的元素添加指定的样式类名,对元素的样式操作,底层的实现就是修改元素的className值,实现的功能:

增加一条样式规则: .addClass('myClass')
增加多条样式规则: .addClass('myClass yourClass')

传递回调遍历样式规则:

$("ul li:last").addClass(function(index) {
return "item-" + index;
});

从接口传参去分析这个实现手法,参考右边的代码addClass我把代码简略的分了几个步骤:

  • 如果传递的是回调函数,递归调用分解下样式规则,通过正则 /\S+/g 空白分组
  • 如果元素本身存在 class 样式,先取出来组合成新的规则按照空格分开
  • 通过 className 设置新的样式传递一个参数与多个参数的处理无非就是字符串的拼接

这里就不详讲,看看代码就能理解重点说一下传递回调函数的设计,官方给的测试案例:

<p class ='selected highlight'>Goodbye</p>
<p class ='selected1 highlight1'>Goodbye</p>
<p class ='selected2 highlight2'>Goodbye</p>

增加样式代码:

$(p).addClass(function(index,className){
index className
0 "selected highlight"
1 "selected1 highlight1"
2 "selected2 highlight2"
});

遍历出所有的 P 节点,并找其对应的 class,返回给每一个回调函数,看看源码的设计:

//如果传递的是回调函数,递归调用  ⑴
if ( jQuery.isFunction( value ) ) {
return this.each(function( j ) { //each addClass回调
jQuery( this ).addClass( value.call( this, j, this.className ) );
});
}

不管是写插件还是其他的,只要是设计操作 DOM 的,在 jQuery 内部就的到 this.each 方法,原因很简单jQuery就是一个数组保存着所有对应的节点的下标

内部在传递一个编写好的回调函数,传递给 each 方法 ,each 方法理解就是一个循环方法,分解出 jQuery 数组中每一个下标元,然后把每一个元素返回给外部回调。

这里再进一步替换下代码就很明显了:

function(  i, obj[ i ]  ) {
jQuery( this ).addClass( value.call( this, j, this.className ) )
}

这里的 this 是指向的每一个 p 元素节点,因为 callback.call 了一下,把每一个上下文指定到当前的函数了,所以 this 就是对应的 obj[i],最后执行的代码就是:

value.call( this, j, this.className )

value 就是最外层用户定义的回调了,复制代码:

$(p).addClass(function(index,className){
// index className
// 0 "selected highlight"
// 1 "selected1 highlight1"
// 2 "selected2 highlight2"
});

这里意外的发现 jQuery Api没给出还包装了一层 jQuery( this ).addClass ,那么意味着 jQuery 还可以接受用户最外层的返回参数,然后再调用 addClass 给当前节点增加新的类名:

jQuery( this ).addClass( value.call( this, j, this.className ) );
p.addClass(function(index,className){
return 'aaaa'
});


JavaScipt 样式操作的更多相关文章

  1. 解密jQuery内核 样式操作

    基础回顾 jQuery里节点样式读取以及设置都是通过.css()这个方法来实现的,本章通一下分解探究下jquery里这部分代码的实现 那么jQuery要处理样式的哪些问题? 先简单回顾下样式操作会遇到 ...

  2. jQuery 2.0.3 源码分析 样式操作

    根据API分类 CSS addClass() jQuery.cssHooks .hasClass() .removeClass() .toggleClass() .addClass() 对元素的样式操 ...

  3. 深入学习jQuery样式操作

    × 目录 [1]设置样式 [2]增加样式 [3]删除样式[4]切换样式[5]判断样式[6]样式操作 前面的话 使用javascript脚本化CSS是一个系列,包括行间样式.计算样式.CSS类.样式表. ...

  4. JQuery_元素样式操作

    元素样式操作包括了直接设置CSS 样式.增加CSS 类别.类别切换.删除类别这几种操作方法.而在整个jQuery 使用频率上来看,CSS 样式的操作也是极高的,所以需要重点掌握.  一.css()方法 ...

  5. DOM样式操作

    CSS 到 DOM的抽象 通过操作 CSS 对应的 DOM对象来更新CSS样式 换肤操作 如何获取实际的样式(不仅有行内,更有页面和外联样式表中定义的样式) 样式表分为三类: 外联,页面,行内 内部样 ...

  6. jQuery - 5.样式操作

    样式操作 1.获取样式 attr("class"), 2.设置样式attr("class","myclass"), 3.追加样式addCla ...

  7. jQuery编程基础精华02(属性、表单过滤器,元素的each,表单选择器,子元素过滤器(*),追加方法,节点,样式操作)

    属性.表单过滤器 属性过滤选择器: $("div[id]")选取有id属性的<div> $("div[title=test]")选取title属性为 ...

  8. jquery系列教程2-style样式操作全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件 ...

  9. JQuery DOM操作 、属性和CSS样式操作、其他函数

    DOM操作 1.在div1内部最后追加一个节点 $("#div1").append("<img src='../01-HTML基本标签/img/Male.gif'/ ...

随机推荐

  1. selenium测试(Java)--多窗口切换(十三)

    selenium测试(Java)--多窗口切换(十三) 如果遇到点击按钮或链接后出现新窗口的情况,就需要使用窗口切换的方法. 本例中就是先打开百度搜索界面,然后利用js打开一个百度新闻界面,然后通过s ...

  2. jquery常用总结

    1.遍历对象 n是属性 value是对应的值 $.each(param,function(n,value) { datas[n] = value; }); 2.获取select改变后的值 $('sel ...

  3. King's Quest —— POJ1904(ZOJ2470)Tarjan缩点

    King's Quest Time Limit: 15000MS Memory Limit: 65536K Case Time Limit: 2000MS Description Once upon ...

  4. this的问题

    javascript this可以绑定到:全局对象,自己定义的对象,用构造函数生成的对象,通过call或者apply更改绑定的对象    1.全局对象  1 2 3 4 5 function glob ...

  5. easyUI + swfupload 多附件上传功能

    public void UPLOADFILED() { Date dt = new Date(System.currentTimeMillis()); SimpleDateFormat sdf = n ...

  6. Android Listview

    方法一: xml文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xml ...

  7. Excel怎样从一串字符中的某个指定“字符”前后截取字符及截取字符串常用函数

    怎么样可以从一串字符中的某个指定位置的前或后截取指定个数的字符. 如:12345.6789,我要截取小数点前(或后)的3个字符.怎么样操作, 另外,怎么样从右边截取字符,就是和left()函数相反的那 ...

  8. 年终汇报、总结、述职:教你做一场B格满满的技术大会演讲

    什么样的演讲和呈现最受听众欢迎,内容干货?逻辑清晰?长相帅气? 偶尔被邀作为speaker参加一些圈内的技术大会进行演讲.这里我分享下自己的经验,如何做一场B格满满的技术大会演讲,希望给做汇报.总结. ...

  9. 把CentOS 7.x网卡名称eno16777736改为eth0

    CentOS 7.x系统中网卡命名规则被重新定义,可能会是"eno167777xx"等,下面我们把网卡名称改为eth0这种. 一.cd  /etc/sysconfig/networ ...

  10. 续并查集学习笔记——Gang团伙题解

    一言不合先贴题目 Description 在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1. 我朋友的朋友是我的朋友: 2. 我敌人的敌人是我的朋友: 所有是朋友的人组成一个团伙 ...