Web Components之Custom Elements

什么是Web Component?

Web Components 包含了多种不同的技术。你可以把Web Components当做是用一系列的Web技术创建的、可重用的用户界面组件的统称。Web Components使开发人员拥有扩展浏览器标签的能力,可以自由的进行定制组件。但截至本文时间,Web Components依然是W3C工作组的一个草案,并为被正式纳入标准,但这并不妨碍我们去学习它。

Web组件

何为Web组件?Web组件相对于Web开发者来说并不陌生,Web组件是一套封装好的HTML,CSS,以及JavaScript,它最大的特点就是可复用。基本在每一个网站上我们都可以看到各式各样的组件,例如下拉菜单、按钮、图片滚播、日历控件等。慢着,既然我们已经可以实现web组件的封装,那Web Component这家伙出现的意义是什么呢?Web Component回答道:“你们的实现方式不够优雅也不够完美,还是看看我的吧”。

因为当我们使用各种编程技巧对组件进行封装时,一个无法规避的事实是,组件的内部是可被访问和影响的,例如我们对样式表进行改动时经常会担心影响到页面组件的样式。而通过Web Component封装出来的组件,我们可以选择让组件的内部隐藏起来,也就是说,组件内部是与世隔绝的!

Web Component的组成

  • Custom Elements
  • HTML Templates
  • Shadow Dom
  • HTML Imports

总的来说,Web Components包含以上四种技术,本文着重谈谈Custom Element,这也是Web component中最核心的部分。

Custom Elements

自定义元素是一个可由创建者来自定义接口的对象。在创建时我们需要通过 document.registerElement() 来对自定义元素进行注册。该方法会返回一个元素的构造器,通过该构造器我们就可以创建我们的自定义元素的实例了。

var MyButton= document.registerElement('my-button');
document.body.appendChild(new MyButton());

实际上 document.registerElement(tag-name, prototype) 包含两个参数:

tag-name: 自定义元素的标签名,这个标签名必须包含连字符'-',这样做的母的是用以区分自定义元素和HTML规范的元素

prototype: 这是一个可选的参数,用于描述该元素的原型,在该元素中你可以为自定义元素进行接口的定义

var MyElement = document.registerElement('my-element', { 
  prototype: Object.create(HTMLElement.prototype, { 
    createdCallback: { 
      value: function() { 
        this.innerHTML = "<p>I'm a Custom Element</p>";
      } 
    } 
  }) 
});
document.body.appendChild(new MyElement())

在上面的例子中,我们通过Object.create()方法创建了一个继承自HTMLElement的对象作为自定义对象的原型,并设置了元素默认的 innerHTML ,如果你对Object.create()方法的第二个参数不熟悉,你最好先去查阅一下。实际上它的上面的例子跟下面给出的写法的效果是一样的:

var MyElementProto = Object.create(HTMLElement.prototype)

MyElementProto.createdCallback = function() {
    this.innerHTML = "<p>I'm a Custom Element</p>"
}

var MyElement = document.registerElement('my-element', { prototype: MyElementProto })

document.body.appendChild(new MyElement())

接着,在页面上我们可以看到渲染出如下结构:

自定义元素的生命周期

在上面的例子中我们可以看到自定义元素的原型上有一个 createdCallback 属性,它的值是一个回调函数,在自定义元素被创建的时候被调用。实际上自定义元素在它的生命周期中可能会经历以下几种变化:

  • 自定义元素在其注册前被创建
  • 自定义元素被注册
  • 自定义元素的实例在自定义元素注册后被创建
  • 自定义元素被插入到文档中
  • 自定义元素从文档中移除
  • 自定义元素的属性被创建、移除、修改

在自定义元素经历上面某些变化时,不同的回调函数会被调用。这些回调函数被保存在一个名为生命周期回调的键值对集合中。我们可实现的回调函数总共有以下4种,其中 attributeChangedCallback 的回调函数中我们可以通过其参数访问到操作的属性名、老的属性值、新的属性值。

DOM:

<div id="modify">
  <label class="CEgreen"><input type="radio" name="CEclass" value="green">green box</label>
  <label class="CEred"><input type="radio" name="CEclass" value="red">red box</label>
</div>

JS:

var MyElement = document.registerElement('my-element', { 
  prototype: Object.create(HTMLElement.prototype, { 
    createdCallback: { 
      value: function() {
        this.innerHTML = "<span>I'm a Custom Element</span>"
      }
    },
    attributeChangedCallback: {
      value: function(property, oldValue, newValue) {
        this.innerHTML = "attribute '" + property + "' is modified to " + newValue
      }
    }
  }) 
})
document.body.appendChild(new MyElement())

var temp = document.querySelector("#modify")
var myElement = document.querySelector("my-element")

temp.addEventListener('click', function(e){
  console.log(e.target.value)
  myElement.className = e.target.value
})

另外,给自定义元素添加样式和普通元素是一样的,这是上面例子中为自定义元素添加的样式:

my-element {display: inline-block;margin-top: 20px;padding: 10px;font-size: 24px;}

这就是一个最基础的自定义元素的实现了。如果我们希望自定义元素内部不受外部样式的影响,我们需要使用Shadow Dom来对内部dom结构和样式进行封装。

原文地址:https://www.cnblogs.com/WhiteCusp/p/4321139.html