Web Component--01. 简介

Web Components 是什么?

Web Components是W3C定义的新标准,它给了前端开发者扩展浏览器标签的能力,可以自由的定制组件,更好的进行模块化开发,彻底解放了前端开发者的生产力。

Web Components 架构

Web Components在 W3C 规范中的发展有几个模块:

  • 模板元素
  • Html Import
  • Shadow DOM
  • 自定义元素
  • 装饰器

目前前四个模块足以支撑 Web Component,装饰器还没有一个完整的规范。

template 模板元素

创建一个template的 html 标签,通过 javascript 获取节点的模板内容

<template id="test">
test template
</template>
<h1 id="message"></h1>
<script type="text/javascript">
    var template = document.getElementById("test");
    console.log(template.content);
</script>

模板默认不显示,需要激活模板,通过以下两种方法来激活节点

  • 克隆节点

    var templateContent  = template.content;
    var activeNode = templateContent.cloneNode(true);
    document.body.appendChild(activeNode);
    
  • 导入节点

    var templateContent  = template.content;
    var activeNode = document.importNode(templateContent,true);
    document.body.appendChild(activeNode);
    

Html Import

Html Import 可以将外部的 HTML 文档嵌入到当前文档中,提供很好的资源共享。
带有import属性的link 支持两个事件

  • onload:文件成功引入页面会触发

  • onerror: 文件加载失败会触发

    <script type="text/javascript"> function importTest(message){ console.log(message); } </script>

Shadow DOM

在 Web Component 规范出来之前,关于 HTML、CSS、Javascript 构建 Web 应用程序的程序的争论一直不断。主要质疑有几种:

  • 样式覆盖:文档的样式会影响Web Component
  • 脚本替换:文档的Javascript会覆盖Web Component的部分代码
  • 重复的 ID:文档出现重复 ID 会导致解析异常

Shadow DOM的引入就是为了解决封装机制作用域的问题。
浏览器通常情况下是看不到Shadow DOM节点的,Google 开发工具可以帮我审查这些元素,需要做如下设定:

创建Shadow DOM : 通过 createShadowRoot 函数对一个 DOM 元素(宿主元素)创建一个 Shadow DOM 子树

<div id="box"></div><!--容器-->
<template id="test">
<style>
:host h1{color:red};
</style>
<h1>Test</h1>
</template>
<script type="text/javascript">
    var box = document.getElementById("box");
    var shadowRoot = box.createShadowRoot();
    var template = document.getElementById("test");
    var templateContent  = template.content;
    var activeNode = document.importNode(templateContent,true);
    shadowRoot.appendChild(activeNode);
</script>

自定义元素

开发一个自定义元素需要五个步骤:

  • 创建对象:

    var objectProto = Object.create(HTMLElement.prototype);
    
  • 定义对象属性:

    //定义单个属性
    Object.defineProperty(objectProto,'title',{
        writable : true,
    })
    
    //定义单个多个
    Object.defineProperties(objectProto,{
        height: {writable : true},
         {writable : true}
    })
    
  • 定义生命周期方法:

    //成功创建对象
    objectProto.createdCallback = function(){
        console.log('created');
    }
    //对象插入DOM中
    objectProto.attachedCallback = function(){
        console.log('attached');
    }
    
  • 注册新元素

    document.registerElement('test',{
            prototype : objectProto
    });
    

输入24px 的 HelloWorld:

<my-name title="HelloWorld" fontsize="2"></my-name>
<script type="text/javascript">
    var objectProto = Object.create(HTMLElement.prototype);
    Object.defineProperties(objectProto,{
        title: {writable : true},
        fontsize: {writable : true}
    })
    objectProto.createdCallback = function(){
        this.innerText = this.attributes.title.value;
        this.style.fontSize = this.attributes.fontsize.value * 12 + 'px';
    }
    document.registerElement('my-name',{
        prototype : objectProto
    });
</script>

时钟应用

  • test.html :通过import方式加载Clock Component
  • clock-elemect.html:负责倒计时的实现

test.html

<link rel="import" href="clock-element.html"/>
<digital-clock></digital-clock>

clock-elemect.html

<template id="clockTemplete">
    <style>
    :host::shadow .clock{
        display: inline-flex;
        justify-content: space-around;
        background:white;
        font-size: 8rem;
        box-shadow: 2px 2px 4px -1px grey;
        border: 1px solid green;
        font-family: sans-serif;
         100%;
    }
    :host::shadow .clock .hour,
    :host::shadow .clock .minute,
    :host::shadow .clock .second{
        color: orange;
        padding: 1.5rem;
        text-shadow: 0px 2px black;
    }
    </style>
    <div class="clock">
        <div class="hour">HH:</div>
        <div class="minute">MM:</div>
        <div class="second">SS</div>
    </div>
</template>
<script type="text/javascript">
(function(){
    var selfDoucment = document.currentScript.ownerDocument;
    var objectProto = Object.create(HTMLElement.prototype);
    objectProto.createdCallback = function(){
        var shadow = this.createShadowRoot();
        var templateContent = selfDoucment.querySelector('#clockTemplete').content;
        var templateNode = selfDoucment.importNode(templateContent,true);
        shadow.appendChild(templateNode);
        var hourElement = shadow.querySelector('.hour');
        var minuteElement = shadow.querySelector('.minute');
        var secondElement = shadow.querySelector('.second');
        window.setInterval(function(){
            var date = new Date();
            hourElement.innerText = date.getHours()+':';
            minuteElement.innerText = date.getMinutes()+':';
            secondElement.innerText = date.getSeconds();
        },1000);
    };
    document.registerElement('digital-clock',{
        prototype : objectProto
    });
})();
</script>





 
原文地址:https://www.cnblogs.com/linzhenjie/p/5486520.html