Web Components使用(二)

在上一章节中主要介绍了Custom elements(自定义元素),Shadow DOM(影子DOM)的使用,我们发现其实只使用上述的两种方式,已经可以构建我们平时需要的组件,那么为什么还需要HTML templates(HTML模板)技术呢?
不知道大家还记不记得之前创建元素的方式:

        const input = document.createElement('input');
        input.setAttribute('type', 'text');
        input.setAttribute('class', 'input-vlaue');

创建一个input就需要写这些js代码,很明显,如果当html文档结构太深或者节点过多时,写出太多的创建html 节点的代码,还是很头疼的。一方面代码量过多且层级结构不清晰,另一方面时css也是用此方式创建,如何使用伪类呢? 多少是方便的。所以便有了HTML templates(HTML模板)技术。
我们先来看下它的定义:

HTML内容模板(<template>)元素是一种用于保存客户端内容机制,该内容在加载页面时不会呈现,但随后可以(原文为 may be)在运行时使用JavaScript实例化。") 和 <slot> 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。

其实就是它可以让你在编写组件时,可以预先定义好模板,然后再在模板上发展出自己的组件。
示例:
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./main.js"></script>
</head>
<body>
    <template id="my-paragraph">
        <style>
          p {
            color: white;
            background-color: #909090;
            padding: 5px;
            border: 1px soli silver;
          }
        </style>
        <p><slot name="my-text">默认文本</slot></p>
      </template>
      
      <my-paragraph>
        <span slot="my-text">个性化文本</span>
      </my-paragraph>
    
      <my-paragraph>
        <ul slot="my-text">
          <li>列表条目1</li>
          <li>列表条目2</li>
        </ul>
      </my-paragraph>

</body>
</html>

main.js

customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();

      const template = document.getElementById('my-paragraph');
      const templateContent = template.content;

      this.attachShadow({mode: 'open'}).appendChild(
        templateContent.cloneNode(true)
      );
    }
  }
);
运行结果

定义模板的的代码:

<template id="my-paragraph">
        <style>
          p {
            color: white;
            background-color: #909090;
            padding: 5px;
            border: 1px soli silver;
          }
        </style>
        <p><slot name="my-text">默认文本</slot></p>
</template>

由于这里的html import已经不被各大浏览器支持了,所以这里的定义模板的模块只能写到使用的html文本里面,或者使用js创建,写入到main.js里面。如下的例子,将template独立到js文件中。
示例:
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./main.js"></script>
</head>
<body>
      <my-paragraph>
        <span slot="my-text">个性化文本</span>
      </my-paragraph>
    
      <my-paragraph>
        <ul slot="my-text">
          <li>列表条目1</li>
          <li>列表条目2</li>
        </ul>
      </my-paragraph>

</body>
</html>

main.js

const str = `
<style>
  p {
    color: white;
    background-color: #909090;
    padding: 5px;
    border: 1px soli silver;
  }
</style>
<p><slot name="my-text">默认文本</slot></p>

`;

customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();

      const shadow = this.attachShadow({mode: 'open'});

      //const template = document.getElementById('my-paragraph');
      // const templateContent = template.content;
      const template = document.createElement('template');
      template.innerHTML = str;
      const templateContent = template.content;

      shadow.appendChild(
        templateContent.cloneNode(true)
      );
    }
  }
);

以上便是对Web Components的一个基本的认识和使用。由此可以看出Web Components在组件化开发方向的优势,可是在使用过程中也有一定劣势,以下便是目前自己不太喜欢的地方:

个人不太喜欢的地方
  • 无法在组件内部使用公共的样式,例如引入了外部样式,即使在组件内部使用该样式对应的class name也不会起作用,例如下面的代码,虽然在 slot外部的p标签内加了class name,但是在组件外部也是无法使用.test{}来定制样式了,这样一来就无法使用很多开源的css类库了。
const str = `
<style>
  p {
    color: white;
    background-color: #909090;
    padding: 5px;
    border: 1px soli silver;
  }
</style>
<p class="test"><slot name="my-text">默认文本</slot></p>

`;
  • 没了html import 语法,template就只能定义显示的html文件中,显然这不是我们想要的组件,我们希望的组件是简洁明了,使用简单,而这看起来组件和html还有了耦合。当然也可以把template写入到js中,但是如果template结构复杂,就会发现自负串过长,代码结构不美观,且html,css,js混合到了一起。
  • 其他的,暂时想不起来了...

参考网址:
MSDN:https://developer.mozilla.org/zh-CN/docs/Web/Web_Components
W3C: https://www.w3.org/html/ig/zh/wiki/Web-Components#.E7.AE.80.E4.BB.8B
web componets 实例代码:https://github.com/mdn/web-components-examples
HTML5 Rocks: https://www.html5rocks.com/en/tutorials/webcomponents/customelements/#instantiating
阮一峰:https://javascript.ruanyifeng.com/htmlapi/webcomponents.html#toc12
知乎:https://zhuanlan.zhihu.com/p/64619005

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354