手把手带你用原生js完成css属性的set和get

上一篇博文引见了getComputedStyle要领,接下来,我们就来完成一个浅易版的小插件,能够在不借助jQuery的情况下完成css属性的猎取和设置。

作者:Icarus
原文链接:手把手带你用原生js完成css属性的set和get

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 的私有要领,相称于我们在房子里找了一个小房间来放 getset 等要领。接下来我们在原型上新增一个 init 要领,用于初始化。以后我们模仿 jQuery 的体式格局,将initprototype 指向 cssToolprototype ,如许我们在用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.prototypethis.age=18相称于对 Foo.prototype.age 赋值,和运用 new 操纵符是有本质区别的。

小结

到这里,教程也就要告一段落了。一个 jQuery 中罕见的 css() 要领背地涵盖了异常多的知识点,跨浏览器的兼容性也是我们此次议论的重点,此次只是完成了一个异常浅易的 css 操纵插件。学问尚浅,假如有不清楚或许有毛病的处所,迎接列位留言或许提issue来协助我革新这个小插件。
末了,完全的项目地点:https://github.com/xdlrt/css-…
求一波star~

    原文作者:_Icarus
    原文地址: https://segmentfault.com/a/1190000008258365
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞