手把手带你用原生js实现css属性的set和get
2017-11-02 13:52
1076 查看
https://segmentfault.com/a/1190000008258365
首先创建一个
全局作用域可以看作是一栋公寓楼,我们创建一个立即执行的匿名函数,相当于是公寓楼中的一间公寓,我们在屋子里做的事情就都是隐秘的,也就是起到隔离作用域的作用,避免和外部变量产生冲突。把
我们创建了一个叫
直接调用
对
IE678的透明度是通过
上一篇博客中提到,由于
IE678 中为
IE678 则不行,所以针对
对于一个没有设定高宽的元素而言,在 IE678 下直接获取得到的值是
IE 下也返回 px 值。
set 方法相较于 get 方法要简便的多,因为我们有
通过
另外,在IE浏览器还有个小坑,如果 cssText 不为空,返回值最后一个分号会被删掉,因此我们需要在累加的属性前加上一个分号。
使用 new 操作符时,是把
age 属性,最后
当不使用 new 操作符时,相当于一个普通对象上的函数调用,
new 操作符是有本质区别的。
到这里,教程也就要告一段落了。一个 jQuery 中常见的
css 操作插件。学问尚浅,如果有不清楚或者有错误的地方,欢迎各位留言或者提issue来帮助我改进这个小插件。
最后,完整的项目地址:https://github.com/xdlrt/css-...
求一波star~
Let's start
首先创建一个 css-tool.js文件,一开始他是这个样子的:
;(function (window,undefined) { "use strict"; var cssTool = function () { return new cssTool.prototype.init(); } cssTool.prototype = { init: function() { console.log('init success'); return this; }, } cssTool.prototype.init.prototype = cssTool.prototype; // 暴露接口 window.cssTool = cssTool; })(window);
全局作用域可以看作是一栋公寓楼,我们创建一个立即执行的匿名函数,相当于是公寓楼中的一间公寓,我们在屋子里做的事情就都是隐秘的,也就是起到隔离作用域的作用,避免和外部变量产生冲突。把
window作为参数拿到屋子里来,以后就不用再重复去外面找
window来用。最前面的分号是为了保证在文件合并压缩后产生语法错误。
undefined在老版本浏览器中不被支持,因此考虑到兼容性添加一个形参。
我们创建了一个叫
cssTool的私有方法,相当于我们在屋子里找了一个小房间来放
get和
set等方法。接下来我们在原型上新增一个
init方法,用于初始化。之后我们仿照
jQuery的方式,将
init的
prototype指向
cssTool的
prototype,这样我们在用
init作为构造函数创造实例时,可以使插件拥有两种调用方式:
var ct = new cssTool()构建
cssTool实例
直接调用
cssTool(),一样返回
cssTool实例
get方法
通用方式
现代浏览器和IE9+
window.getComputedStyle(elem,null).getPropertyValue(attr)
IE678
elem.currentStyle.getAttribute(camelCase(attr))
兼容处理
驼峰命名法转换-camelCase
对 currentStyle来说,在IE6浏览器中他很专一,只喜欢以驼峰命名法命名的变量,而IE78中就有点朝三暮四,驼峰命名法和中间带'-'的都照单全收,为了兼容和操作的简便,我们统一转换为驼峰命名法。
/** * 驼峰命名法转换,IE678使用 * font-size --> fontSize * @param {String} attr * @param {String} match 匹配到的字符串,如-c * @param {String} originText (\w)是一个捕获,这里是捕获到的字符,如c * @return 返回驼峰命名方式的css属性名 */ function camelCase (attr){ return attr.replace(/\-(\w)/g, function (match,originText) { return originText.toUpperCase(); }); }
透明度获取-getFilter
IE678的透明度是通过 filter:alpha(opacity=0)来设置的,我们利用正则表达式匹配到此时透明度的值,由于此时得到的是0-100之间的数值,所以需要换算为我们常见的0-1的形式。
/** * IE678下获取透明度的值 * @param elem 获取值的 dom * @return {Number} 透明度的值,默认为1 * IE678下设置透明度 filter: alpha(opacity=0) 取值为0-100 */ function getFilter(elem) { var _filter = elem.currentStyle.getAttribute('filter').match(/alpha\(opacity=(.*)\)/i); var value = parseFloat(_filter[1]); if(!isNaN(value)){ // 转化为0-1 return value ? value/100 : 0; } return 1; }
float 值的获取
上一篇博客中提到,由于 float是 ECMAScript 的一个保留字。所以在各浏览器中都会有代替的写法,比如说在现代浏览器中为
cssFloat,而在
IE678 中为
styleFloat。经测试,在现代浏览器中直接使用
getPropertyValue("float")也可以获取到
float的值。而
IE678 则不行,所以针对
float,需要简单的hack。
width | height 样式的获取
对于一个没有设定高宽的元素而言,在 IE678 下直接获取得到的值是 auto。而现代浏览器会直接返回它的 px 值,我们的目标就是在
IE 下也返回 px 值。
// 直接获取外部样式表未设置的 width 和 height 返回值为 auto // 为了获取精确的 px 值,使用 getBoundingClientRect 方法 // getBoundingClientRect 可以获得元素四个点相对于文档视图左上角 // 的 top、left、bottom、right值,进行简单计算即可 var condition = attr === 'width' || attr === 'height' && elem.currentStyle[attr] === 'auto'; if(condition){ var clientRect = elem.getBoundingClientRect(); return (attr === 'width' ? clientRect.right - clientRect.left : clientRect.bottom - clientRect.top ) + 'px'; }
set方法
set 方法相较于 get 方法要简便的多,因为我们有 cssText这个跨越 IE6+ 和现代浏览器的神器。
通过
elem.style.cssText可以对元素的样式进行读写,实际上操作的是 html 标签上的
style属性的值。因此不能直接对其赋值,不然就把整个
style属性的值给覆盖掉了。我们采用累加的方式来修改属性。
另外,在IE浏览器还有个小坑,如果 cssText 不为空,返回值最后一个分号会被删掉,因此我们需要在累加的属性前加上一个分号。
/** * 设置元素css样式值 * @param elem 设置值的dom元素 * @param {String} attr 设置样式名称,如font-size * @param {String} value 设置样式的值,如16px */ set: function (elem, attr, value){ // IE78 设置透明度需特殊处理 if(attr === 'opacity'){ // 针对 IE7 的 hack // filter 滤镜要求 hasLFooout=true 才能执行 // IE浏览器且 hasLFooout=false 时执行 if(!!elem.currentStyle && !elem.currentStyle.hasLFooout){ elem.style.zoom = 1; attr = 'filter'; value = 'alpha(opacity=' + value * 100 + ')'; } } // 通用方式 elem.style.cssText += ';' + (attr + ':' + value) + ';'; }
补充
简单解释new操作符的作用
var Foo = function() { return new Foo.prototype.init(); } Foo.prototype = { init: function() { this.age = 18; return this; }, age: 20 } console.log(Foo().age); // 18 console.log(Foo.prototype.age); // 20
var Foo = function() { return Foo.prototype.init(); } Foo.prototype = { init: function() { this.age = 18; return this; }, age: 20 } console.log(Foo().age); // 18 console.log(Foo.prototype.age); // 18
使用 new 操作符时,是把
init当成构造函数来调用,在
init内部会创建一个隐式对象并用
this指向它,此时的
this.age=18表示在这个隐式对象上增加一个
age 属性,最后
return this不是必需的,构造函数默认会返回
this。此时
Foo.prototype.age不受影响。
当不使用 new 操作符时,相当于一个普通对象上的函数调用,
this指向了
init所属的对象,即
Foo.prototype,
this.age=18相当于对
Foo.prototype.age赋值,和使用
new 操作符是有本质区别的。
小结
到这里,教程也就要告一段落了。一个 jQuery 中常见的 css()方法背后涵盖了非常多的知识点,跨浏览器的兼容性也是我们此次讨论的重点,这次只是实现了一个非常简易的
css 操作插件。学问尚浅,如果有不清楚或者有错误的地方,欢迎各位留言或者提issue来帮助我改进这个小插件。
最后,完整的项目地址:https://github.com/xdlrt/css-...
求一波star~
相关文章推荐
- 手把手用原生JS代码实现css属性的set和get
- JQuery模拟五------实现属性set&get和CSS set&get
- JS 实现对象属性的get 和set方法
- js操作css属性实现div层展开关闭效果的方法
- 基于css3新属性transform及原生js实现鼠标拖动3d立方体旋转
- 纯css,js原生,js原型,jquery四种方式实现轮播图效果
- 用原生JS实现的一个导航下拉菜单,下拉菜单的宽度与浏览器视口的宽度一样(js+html+css)
- 使用PHP魔术方法实现属性的set、get方法
- 原生JS中如何获取CSS属性中的值
- js通过标签元素id,用document.getElementById().style设置标签元素的css属性
- category使用 objc_setAssociatedObject/objc_getAssociatedObject 实现添加属性
- 【CSS进阶】原生JS getComputedStyle等方法解析
- 原生js实现Ajax---get
- 原生JS实现元素的getElementsByClassName()方法,适用于多个类名
- js原生获取元素的css属性
- 用原生JS实现getElementsByClass
- html5的classList属性介绍和原生js实现jQuery的addClass,removeClass,hasClass方法
- 原生js实现改变随意改变div属性style的名称和值的结果
- PHP使用方法重载实现动态创建属性的get和set方法
- 原生Js实现元素渐隐/渐现(原理为修改元素的css透明度)