Memos

CSS 蒙版

使用 CSS 蒙版可以帮助达到类似弹层指引的效果。

css 蒙版的关键点是:黑色表示完全透明展示;白色表示不展示,即图片完全被遮盖,黑色一片;而中间的颜色则表示相应的透明度。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="container" style="position: relative;">
  <svg style="position: absolute;" width="400" height="280">
      <defs>
          <mask id="mask3">
            <rect x="0" y="0" width="100%" height="100%" style="stroke:none; fill: #888"></rect>
            <circle id="circle1" cx="100" cy="100" r="50" />
            <rect x="200" y="200" width="100" height="50"></rect>
          </mask>
      </defs>

      <rect x="0" y="0" width="100%" height="100%" style="stroke: none; mask: url(#mask3)"></rect>
  </svg>

  <img src="http://img6.cache.netease.com/cnews/2014/11/3/20141103100737855b7.jpg" />
</div>

示例效果:

Html Readonly 属性

readonly 属性用于控制表单字段不可编辑,但和 disabled 不同,form 表单提交时会把值提交上去。

但对以下表单元素无效,包括 type 是 hiddenrangecolorcheckboxradiofile 以及按钮类型(button 或 submit)。

ES2015之对象计算属性值(computed Property Name)

对于 JavaScript 普通对象,定义和使用一般如下:

1
2
3
4
5
6
7
var obj = {
     a: 1
};
obj.b = 2;
var k = 'c';
obj[k] = 3;
obj['a'] = 0;

如果属性名(property name)是变量,那么引用时需要使用 [] 语法。

ES2015 中,使用字面量创建对象时也可以使用变量来创建属性名,具体方案是使用计算属性名(computed property name),使用形式是 [property],如:

1
2
3
4
5
var i = 1;
var obj = {
  [i]: 3
};
console.log(obj); // {'1': 3}

并不是只能使用变量,而是可以使用一切表达式,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Computed property names (ES6)
var i = 0;
var a = {
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
  ["foo" + ++i]: i
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

var param = 'size';
var config = {
  [param]: 12,
  ["mobile" + param.charAt(0).toUpperCase() + param.slice(1)]: 4
};

console.log(config); // { size: 12, mobileSize: 4 }

参考链接

Arrow Function in ES6

Arrow function 的使用一来能简化匿名函数的使用,二来能解决匿名函数中不时碰到的 this 指向的问题。

在 JavaScript 中,大量地使用到匿名函数,比如事件绑定和像 map/reduce/filter 等这些方法中。

1
2
3
var selected = allJobs.filter(function (job) {
  return job.isSelected();
});

使用 arrow function 后,可以简化为下面这样:

1
var selected = allJobs.filter(job => job.isSelected());

Rest Parameters and Defaults in ES6

ES6 给函数增加了剩余参数(rest parameters)和参数默认值的功能。

剩余参数

因为 JavaScript 并没有重载功能,以及为了支持可变参数的情况,是通过 arguments 来实现的。ES6 增加了剩余参数这个功能,希望能简化下这种情况下的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function containsAll(haystack, ...needles) {
  for (let needle of needles) {
    if (haystack.indexOf(needle) === -1) {
      return false;
    }
  }

  return true;
}

console.log(containsAll('abc', 'a', 'b'));
console.log(containsAll('abc', 'a', 'd'));
console.log(containsAll('abc'));
console.log(containsAll());

参数默认值

参数默认值可用来解决以前需要用 param = param || 'default'if 判断设置的情况。

1
2
3
4
5
6
function sayHello(name, word="hello") {
  console.log(`${word}, ${name}`);
}
sayHello('Jimmy');
sayHello('Kate', '你好');
sayHello('Jimmy', undefined);

ES6 中,由于默认参数的表达式实在调用时自左而右地计算,所以,默认参数可以使用其之前的参数,如下:

1
2
3
4
5
6
7
function conditionalParameter(a, b=(a==1 ? 2 : 3)) {
  return a + b;
}

console.log(conditionalParameter(2, 5));// 7
console.log(conditionalParameter(1));   // 3
console.log(conditionalParameter(2));   // 5

参考资料

Template Strings in ES6

ES6 中的 template string 并不是 Mustache 这类模板库的替代品,最重要的是提供字符串插值功能,但并不提供诸如 if/for 等控制功能

定义

普通的字符串是使用 '" 来定义,template string 是使用 ““`。

1
let s = `This is a template string`

不同的是,template string 可以直接用来定义多行的字符串,并且保留其换行和空白。

1
2
3
let ss = `This is a
multiple line templat string
  which reserves space`

插值

和普通字符串相比,除了能够方便地定义多行的字符串外,还支持字符串插值,插值处支持任何 JavaScript 表达式,如果表达式返回值不是字符串,那么则按照通用的规则来做转换。

1
2
3
4
5
6
7
let obj = {
  name: 'obj',
  say: () => {return 3}
}

let c = `The ${obj.name} says: ${obj.say()}`
console.log(c) // The obj says: 3

参考资料

Generator in ES6

生成器(Generator)是一个由生成器函数返回的对象,其既是一个迭代器,也是一个可迭代对象。

生成器函数则是一个使用 function* 来声明的函数,如:

1
2
function* gen() {
}

能够暂停的函数

由于 JavaScript 是单线程的,所以一旦执行一个函数,那么一定是按顺序执行完函数体里的语句才能执行这个函数后面的语句。

生成器提供一个能力,可以在指定地方暂停,然后再在需要的时候回到暂停处继续执行。

1
2
3
4
5
6
7
8
9
10
function* gen() {
  console.log(1);
  yield;
  console.log(2);
}

var it = gen();
it.next();
console.log(3);
it.next();

上面代码中,log 的顺序将是 1 3 2

首先,调用生成器函数不会运行里面的代码,而是返回一个生成器。对于一个生成器而言,调用 next 方法来开始运行,然后在里面碰到 yield 时暂停里面的运行,而回到 next 调用处继续往下执行;再次调用 next,则回到生成器上次停止的地方继续往下执行,直至碰到 yield 而暂停里面回到外面或执行完毕。

Iterator in ES6

for-of 使用迭代器(iterator)来迭代一个可迭代(iterable)的对象,主要是想取代传统的比较繁琐的 for 及会遍历非自带属性以及无法 continue/break/returnforEach,其基本示例如:

1
2
3
for (let i of [1, 2, 3]) {
  console.log(i);
}

for-of 默认支持了数组、字符串、类数组以及 ES6 中的 Map 和 Set 等,但不支持平对象(字面量对象)(实际支持情况还看浏览器,比如在此刻 firefox 支持了 NodeList,但 Chrome 还不支持)。

迭代 Map 可以像上面那样使用单变量来在每次迭代时得到一个数组,也可以配合列表结构来直接得到 key 和 value。

1
2
3
4
5
6
7
let aMap = new Map();
aMap.set('a', 1)
aMap.set('b', [2]);

for (let [k, v] of aMap) {
  console.log(k, v);
}

Shadow Dom

Shadow DOM 的用途是封装隔离一个元素,从而在组件化的过程中隔离外部样式和 JS 的影响。

使用

创建

通过在一个元素(A)上创建一个 shadow root 的方式来创建 shadow dom,返回的值成为 shadow root,A 成为 shadow host。

一旦创建了 shadow root,那么宿主元素的原内容将不被展示,而是展示 shadow root 的内容。

可以在一个 shadow host 上创建多个 shadow root(但只有最新的一个会生效,但可以通过 <shadow></shadow> 来内嵌引用前一个 shadow;并且目前无法移除 shadow root),还可以把一个 shadow root 里的元素作为 shadow host 来继续创建 shadow root。

1
2
3
4
5
6
<button>Hello, world!</button>
<script>
var host = document.querySelector('button');
var root = host.createShadowRoot();
root.textContent = 'こんにちは、影の世界!';
</script>

通过配合使用 html template 可以简化创建时的繁琐,如:

1
2
3
4
var shadow = document.querySelector('#nameTag').createShadowRoot();
var template = document.querySelector('#nameTagTemplate');
var clone = document.importNode(template.content, true);
shadow.appendChild(clone);

Html Template

HTML 5.1 计划增加 template 元素,提供一段可被后续被 JavaScript 克隆和插入的代码片段。

what

<template></template> 元素是提供页面渲染是不被解析渲染,但在 JavaScript 使用并插入到文档后才解析渲染的代码片段。其可存放任意合法的 HTML 内容,可位于任何合法的非替换元素里,包括 <head> 等。

示例一

<template>
    <style>
    div {
        color: red;
    }
    </style>

    <div>
        <h1>template</h1>
        <img src="http://holdit.sinaapp.com/300" />
    </div>

    <script>
    alert('template');
    </script>

</template>

需要注意的是,这是一个可被重复使用的文档片段,并没有像 Mustache 那样的模板插值(“)甚至更高级的流程处理的功能。这是一个静态的模板,不是根据数据来动态生成 HTML 字符串。