小知识随手记(八):颜色转换、const常量的改动内因、js消息队列、JSON.stringify()的一些特性、多背景图写法、懒加载原理、document.body与document.documentElement区别及使用、移动ios卡顿问题、移位运算符、nextSibling 和nextElementSibling的区别

1、十六进制颜色与rgba颜色相互转换

// 十六进制转rgb
String.prototype.colorRgb = function(){
  var sColor = this.toLowerCase();
  //十六进制颜色值的正则表达式
  var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
  // 如果是16进制颜色
  if (sColor && reg.test(sColor)) {
    if (sColor.length === 4) {
      var sColorNew = "#";
      for (var i=1; i<4; i+=1) {
        sColorNew += sColor.slice(i, i+1).concat(sColor.slice(i, i+1));
      }
      sColor = sColorNew;
    }
    //处理六位的颜色值
    var sColorChange = [];
    for (var i=1; i<7; i+=2) {
      sColorChange.push(parseInt("0x"+sColor.slice(i, i+2)));
    }
    // return "RGB(" + sColorChange.join(",") + ")";
    return {
      rbgString:"RGB(" + sColorChange.join(",") + ")",
      rbgArray:sColorChange
    };
  }
  return sColor;
};

  十六进制颜色转rgba颜色主要就是parseInt('0x')的使用,即如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。

  parseInt('0xff'),255;也就是3个十六进制位数转换为十进制数即可:rgba(255, 255, 255, .5),后面的这个透明度可以自己拼。

// rgb转十六进制
String.prototype.colorHex = function(){
  var that = this;
  //十六进制颜色值的正则表达式
  var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
  // 如果是rgb颜色表示
  if (/^(rgb|RGB)/.test(that)) {
    var aColor = that.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
    var strHex = "#";
    for (var i=0; i<aColor.length; i++) {
      var hex = Number(aColor[i]).toString(16);
      if (hex.length < 2) {
        hex = '0' + hex;
      }
      strHex += hex;
    }
    if (strHex.length !== 7) {
      strHex = that;
    }
    return strHex;
  } else if (reg.test(that)) {
    var aNum = that.replace(/#/,"").split("");
    if (aNum.length === 6) {
      return that;
    } else if(aNum.length === 3) {
      var numHex = "#";
      for (var i=0; i<aNum.length; i+=1) {
        numHex += (aNum[i] + aNum[i]);
      }
      return numHex;
    }
  }
  return that;
};

  rgba颜色转换为十六进制颜色,主要就是3个十进制数转换为十六进制数,主要用到了Number()对象的toString(16)基数方法,直接就能获取到一个数字的十六进制字符串,比较方便。

  采用 Number 类型的 toString() 方法的基模式,可以用不同的输出数字,例如二进制的基是 2,八进制的基是 8,十六进制的基是 16。

var iNum = 10;
alert(iNum.toString(2));    //输出 "1010"
alert(iNum.toString(8));    //输出 "12"
alert(iNum.toString(16));    //输出 "A"

2、ES6语法中的 const 声明一个只读的常量,那为什么下面可以修改const的值?

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

  const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动

  对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。

  但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

3、背景多背景图背景色写法

background url('../../assets/homeImgs/inviteImgs/bg-1.png') bottom / 100% 80% no-repeat, 
url('../../assets/homeImgs/inviteImgs/card-bg.png') #560506 center 10px / 95% no-repeat
// 背景图链接 背景色 定位(居中,距顶10px) / 尺寸大小(宽,高) 是否重复

  背景图显示优先,背景图显示不到的地方会显示背景色

4、图片懒加载实现原理

  将页面中的img标签src指向一张小图片或者src为空,然后定义data-src(这个属性可以自定义命名)属性指向真实的图片。当滚动到可视区域内时才设置img.src = 真实图片地址来加载图片。

var img = document.getElementsByTagName("img");
var num = img.length;
var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历
lazyload(); //页面载入完毕加载可视区域内的图片
window.onscroll = lazyload;
//监听页面滚动事件
function lazyload() {
  var seeHeight = document.documentElement.clientHeight; //可见区域高度
  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //滚动条距离顶部高度
  for (var i = n; i < num; i++) {
    if (img[i].offsetTop < seeHeight + scrollTop) {
      if (img[i].getAttribute("src") == "") {
        img[i].src = img[i].getAttribute("data-src");
      }
      n = i + 1;
    }
  }
}

5、vue-router的scrollBehav无效的问题

  作者在[issues](https://github.com/vuejs/vue-router/issues/675)中说了vue-router不在支持这个特性了

Hooking into transitions involves too many intricacies and depends on custom transition implementations, 
so vue-router is not going to support that as a built-in.
It's possible to implement your own transition component for that purpose though.

  所以需要自己解决,解决方案是:利用afterEach()钩子函数

router.afterEach((to, from) => {
  let bodySrcollTop = document.body.scrollTop
  if (bodySrcollTop !== 0) {
    document.body.scrollTop = 0
    return
  }
  let docSrcollTop = document.documentElement.scrollTop
  if (docSrcollTop !== 0) {
    document.documentElement.scrollTop = 0
  }
})

  还有document.body.scrollTop一直是0的问题,查资料发现是DTD的问题:页面指定了DTD,即指定了DOCTYPE时,使用document.documentElement;页面没有DTD,即没指定DOCTYPE时,使用document.body。IE和Firefox都是如此。

6、移动端ios网页版收起键盘导致页面空白解决办法

  失焦的时候把窗口滚动位置设置到(0,0)就行了

<input type="text" οnblur="window.scrollTo(0, 0);">

  移动ios滑动卡顿问题,加上2个样式即可

-webkit-overflow-scrolling touch
overflow-scrolling touch

7、移位运算符

let a1 = 10 << 2; // 40
let a2 = 10 << 3; // 80

  x << y,在数字x上左移y比特得到 x*2的y次方

8、nextSibling 和nextElementSibling的区别

  使用nextSibling属性返回指定节点之后的下一个兄弟节点,(即:相同节点树层中的下一个节点)。

  nextSibling属性与nextElementSibling属性的差别:

  (1)nextSibling属性:返回元素节点之后的兄弟节点(包括文本节点、注释节点即回车、换行、空格、文本等等);

  (2)nextElementSibling属性:只返回元素节点之后的兄弟元素节点(不包括文本节点、注释节点);

  注意:空格、回车也会看作文本,以文本节点对待。

9、js实现一个消息队列

  jquery里的消息队列

function show(a){
  alert(a)
}

callbacks = $.Callbacks();

callbacks.add(function(){
  show('a')
})

callbacks.add(function(){
  show('b')
})

callbacks.fire() //a,b  注:fire 可跟参数  callbacks.fire('aaaa')
callbacks.remove();//删除

  js实现一个简单的消息队列

var observal = {
   callback: [],
   add: function(fn){
     this.callback.push(fn)
 },
 fire: function(){
    this.callback.forEach(function(a){
             a()
       })
    }
}

  也就是利用数组存储,有时间就push,然后通过forEach触发

10、JSON.stringify() 的秘密特性

(1)第2个参数,数组时

{"id":"0001","type":"donut","name":"Cake","ppu":0.55,}

在日志中很难找到 name 键,因为控制台上显示了很多没用的信息。当对象变大时,查找属性的难度增加。
stringify 函数的第二个参数这时就有用了。 JSON.stringify(product,[
'name', 'type']) // 结果,{"name":"Cake","type":"donut"}

(2)第2个参数,函数时

  结果:{ "age" : 26 }

(3)第三个参数为数字:第三个参数控制最后一个字符串的间距。如果参数是一个数字,则字符串化中的每个级别都将缩进这个数量的空格字符。

(4)如果第三个参数是 string,那么将使用它来代替上面显示的空格字符。

(5)toJSON 方法

  我们有一个叫 toJSON 的方法,它可以作为任意对象的属性。JSON.stringify 返回这个函数的结果并对其进行序列化,而不是将整个对象转换为字符串。参考下面的例子。

  这里我们可以看到,它只打印 toJSON 函数的结果,而不是打印整个对象。

posted @ 2019-07-09 22:16  古兰精  阅读(393)  评论(0编辑  收藏  举报