web 自定义表情

Web Components 标准非常重要的一个特性是,它使开发者能够将HTML页面的功能封装为 custom elements(自定义标签)。而自定义标签的好处,就是在大型web开发的时候,可以封装组件(Vue、Angular等大型框架)来重用,方便开发跟管理。

在自定义标签之前,先来看下几个相关的API:

  1. Object.create(proto, [propertiesObject]): 创建新对象,将该新对象的__proto__指向proto,这里的proto是 HTMLElement,因为我们需要创建一个element。主要是ES5的写法,ES6可以通过 Class 跟 constructor 来实现。
  2. document.currentScript.ownerDocument: 该方法主要针对通过 HTML import导入的文件,用于获取自定义element的上下文document,并通过该document 获取该 element 定义的html模板。因为document是指向全局上下文的,获取不到自定义的元素。document.currentScript: 获取正在执行的<script>脚本。
  3. createdCallback: 创建元素成功之后的回调函数。将自定义元素的模板添加到该元素下面。
  4. Element.createShadowRoot: 创建 shadow DOM,将该标签模板与外部元素隔离开来,不受外部样式影响,也不影响外部样式。不过MDN上将这个API废弃掉了,建议使用 attachShadow() 替代
  5. Element.attachShadow(shadowRootInit): createShadowRoot 的替代者。shadowRootInit: 指定shadowRoot的封装模式 {mode: open/closed}。open 表示可在外部 获取到该shadow,closed 反之。
    1. open: ele.shadowRoot === shadow
    2. closed: ele.shadowRoot === null
  6. document.registerElement(tag-name, options): 注册自定义元素。MDN已经废弃这个API了,建议使用 customElements.define() 替代
    1. tag-name: 自定义标签的名字,必须有一个连字符 '-'
    2. options: 指定标签的原型属性跟可扩展对象
 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title></title>
 5     <link rel="import" href="./customized-tag.html">
 6     <style type="text/css">
 7         .red-color {
 8             color: blue
 9         }
10     </style>
11 </head>
12 <body>
13     <div class="red-color">aaa</div>
14     <customized-tag></customized-tag>
15 </body>
16 </html>
 1 <template>
 2     <div class="red-color">
 3         hahaha
 4     </div>
 5     <style type="text/css">
 6         /*.red-color {
 7             color: red;
 8         }*/
 9     </style>
10 </template>
11 <script type="text/javascript">
12     (function() {
13         // 创建一个html元素
14         let ele = Object.create(HTMLElement.prototype);
15         // 获取当前文档的元素节点里面的内容
16         // 因为这个文件是通过 import 导入到父html的, document无法直接获取到自定义的模板
17         // document.currentScript 获取到当前的script,因为默认 document 是之前全局上下文的
18         // document.currentScript.ownerDocument 获取当前文档,而不是全局
19         let customizedDoc = document.currentScript.ownerDocument.querySelector('template').content;
20         ele.createdCallback = function() {
21             // 创建shadow DOM,避免元素相互影响,已废弃,建议使用 attachShadow
22             // let shadow = this.createShadowRoot();
23 
24             // 创建shadow DOM, mode: open / closed, open 表示可以在js里面获取到该shadowDOM,closed 表示无法在外部获取到该shadow DOM
25             // open: ele.shadowRoot === shadow
26             // closed: ele.shadowRoot === null
27             let shadow = this.attachShadow({mode: 'open'});
28             // 拷贝节点,第二个参数表示是否导入后代节点
29             let clone = document.importNode(customizedDoc, true);
30             shadow.appendChild(clone);
31 
32             // 如果不想创建 shadowDOM, 可直接将节点append到父元素
33             // this.appendChild(clone)
34         }
35         document.registerElement('customized-tag', {
36             prototype: ele
37         })
38     })()
39 
40 </script>

 使用 customElements.define(tag-name, constructor, options) 方式注册组件

 1     class CustomizedTag extends HTMLElement {
 2         constructor() {
 3             super();
 4             this.attachToTag();
 5         }
 6 
 7         attachToTag() {
 8             let shadow = this.attachShadow({mode: 'open'})
 9             let ele = document.currentScript.ownerDocument.querySelector('template').content;
10             let clone = document.importNode(ele, true);
11             shadow.appendChild(clone)
12         }
13     }
14     customElements.define('customized-tag', CustomizedTag)

猜你喜欢

转载自www.cnblogs.com/l-c-blog/p/10746000.html