Web开发中的<自定义>

整理一下有哪些可以自定义的骚操作

自定义元素

自定义元素(Custom Elements)是一种更加灵活的HTML特性,可以使用它定义新的HTML元素。

目前是chrome和opera所支持的一个特性。

借助自定义元素,网络开发者可以创建新的 HTML 标记、扩展现有 HTML 标记,或者扩展其他开发者编写的组件。API 是网络组件的基础。它提供了基于网络标准来使用原生 JS/HTML/CSS 创建可重用组件的方法。其结果是代码更精简且模块化,并且在我们的应用中的可重用性更好。

定义

  1. 创建一个自定义元素类,使用ES6的class扩展基础的HTMLElement
  2. 调用customElements.define()让浏览器学习新的标签,输入新的名称与构建器
1
2
class MyElement extends HTMLElement {...}
window.customElements.define('my-element', MyElement);

自定义元素具有所继承DOM的所有属性和方法。

定义自定义元素的规则:

  1. 自定义元素的名称必须包含短横线 (-)
  2. 不能多次注册同一标记。否则,将产生 DOMException
  3. 自定义元素不能自我封闭

扩展

可以扩展已定义的自定义元素,也可以扩展原生HTML元素

  1. 扩展已定义元素

    1
    2
    class MyExtendElement extends MyElement {...}
    window.customElements.define('my-extend-element', MyExtendElement);
  2. 扩展原生HTML元素
    如果想要一个有漂亮的<button>元素,除了复制<button>的行为和功能,更好的方式就是使用自定义元素增补现有元素,这样的主要好处是可以获得其所有功能(属性,方法与无障碍访问)。
    要扩展元素的话需要创建继承自正确DOM接口的类定义,比如扩展<button>的自定义元素需要从HTMLButtonElement而不是HTMLElement继承。 同样,扩展<img>的元素需要扩展 HTMLImageElement。
    比如要扩展<button>元素,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class FancyButton extends HTMLButtonElement {...}
    customElements.define('fancy-button', FancyButton, {extends: 'button'});
    ```
    扩展原生元素时调用define()需要使用第三个参数告知浏览器要扩展的标记
    ## 使用
    ```html
    <my-element></my-element>

自定义元素可以在定义注册之前使用

可以先在页面中声明自定义标签,然后再使用define方法定义,原因是浏览器因为存在未知标记而采用不同方式处理潜在自定义元素。调用define()并将类定义赋予现有元素的过程称为“元素升级”。

未知元素与自定义元素

  • 未知元素
    <unknownelement>
    HTML规范中将没有定义的元素作为HTMLUnknownElement进行解析。
  • 自定义元素
    <unknown-element>
    自定义元素则并非如此。如果在创建时使用有效的名称(包含“-”),则潜在的自定义元素将解析为HTMLElement。
1
2
3
4
// "tabs" is not a valid custom element name
document.createElement('tabs') instanceof HTMLUnknownElement === true
// "x-tabs" is a valid custom element name
document.createElement('x-tabs') instanceof HTMLElement === true

响应

也就是生命周期中的钩子,在特定时间运行自己的代码,并且响应回调的函数是同步

  1. constructor
    创建或升级元素的一个实例时调用,用于初始化状态或设置事件监听
  2. connectedCallback
    元素每次插入到 DOM 时都会调用,用于运行安装代码,例如获取资源或渲染
  3. disconnectedCallback
    元素每次从 DOM 中移除时都会调用,用于运行清理代码,例如移除事件侦听器等
  4. attributeChangedCallback(attrName, oldVal, newVal)
    属性添加、移除、更新或替换。解析器创建元素时,或者升级时,也会调用它来获取初始值

API

全局的customElements中包含处理自定义元素的方法

define(tagName, constructor, options)

用于在浏览器中定义新的自定义元素

1
2
customElements.define('my-element', class extends HTMLElement { ... });
customElements.define('fancy-button', class extends HTMLButtonElement { ... }, {extends: 'button'});

get()

用于在给定有效自定义元素标记名称的情况下,返回元素的构造函数。如果没有注册元素定义,则返回 undefined

1
2
let Drawer = customElements.get('my-drawer');
let drawer = new Drawer();

whenDefined()

若定义了自定义元素则返回可解析的 Promise,若元素已定义则立即得到解析

1
2
3
customElements.whenDefined('my-drawer').then(() => {
console.log('ready!');
});

兼容性


Can I Use custom-elements? Data on support for the custom-elements feature across the major browsers from caniuse.com.

自定义属性

data-*

data-*构成一类自定义数据属性,允许通过脚本在html标签与其DOM元素之间进行专有信息的交换。

标签中的data-*属性可以通过属性设置元素的HTMLElement接口的dataset属性来访问,dataset是一个DOMStringMap类型。

*名称的规则:

  1. 不能以xml开头,无论这些字母用于什么情况
  2. 不能包含任何分号 (U+003A)
  3. 不能包含A至Z的大写字母

名称中的短横线会被转换为下一个字母的大写替代(驼峰命名),比如获取data-my-value属性值可以通过HTMLElement.dataset.myValue(或HTMLElement.dataset[myValue])访问。

使用

1
<p data-my-value="World">Hello</p>
1
2
let p = document.querySelector('p')
console.log(p.dataset.myValue)

兼容性


Can I Use dataset? Data on support for the dataset feature across the major browsers from caniuse.com.

–* 与 var()

规范与兼容性

CSS自定义属性使用–*命名方式定义,值可以是任意有效的CSS属性值。

通过var()方法使用自定义属性,var方法的第一个为优先使用的值,其他值为缺省值,若第一个值未定义则使用缺省值。

使用

1
<p>hello</p>
1
2
3
4
5
6
7
8
9
:root {
--main-color: #f00;
--sub-color: #ee0;
}
p {
color: var(--main-color, #);
background-color: var(--sub-color);
border: var(--some-color, #000) solid 2px;
}

兼容性


Can I Use css-variables? Data on support for the css-variables feature across the major browsers from caniuse.com.

自定义事件

以前自定义事件需要自己封装一个类或使用Event类来实现,现在提供了一个CustomEvent API来满足这类需求。

使用

  1. 创建

    1
    2
    3
    4
    5
    let dinner = new CustomEvent('dinner', {
    detail: {
    info: 'Ma jiang noodles!'
    }
    })

    CustomEvent(type, customEventInit)

    第一个参数为event名称字符串,第二个参数为一个CustomEventInit字典,也接受来自Event构造函数中EventInit的参数,有如下字段:

    1. detail - 可选,默认为null,表示与事件关联的依赖值
    2. bubbles - 可选,默认为false,表示能否冒泡,来自EventInit
    3. cancelable - 可选,默认为false,表示是否可取消,来自EventInit
    4. composed - 可选,默认为false,表示是否会在shadow root之外触发侦听器,来自EventInit
  2. 监听

    1
    2
    3
    element.addEventListener('dinner', (e) => {
    alert(`Today\'s meal is ${e.detail.info}`)
    })
  3. 分发

    1
    element.dispatchEvent(dinner)

    由于CustomEvent是继承自Event的,分发时直接使用dispatchEvent方法即可。

兼容性


Can I Use customevent? Data on support for the customevent feature across the major browsers from caniuse.com.

参考

文章目录
  1. 1. 自定义元素
    1. 1.1. 定义
    2. 1.2. 扩展
    3. 1.3. 未知元素与自定义元素
    4. 1.4. 响应
    5. 1.5. API
      1. 1.5.1. define(tagName, constructor, options)
      2. 1.5.2. get()
      3. 1.5.3. whenDefined()
    6. 1.6. 兼容性
  2. 2. 自定义属性
    1. 2.1. data-*
      1. 2.1.1. 使用
      2. 2.1.2. 兼容性
    2. 2.2. –* 与 var()
      1. 2.2.1. 使用
      2. 2.2.2. 兼容性
  3. 3. 自定义事件
    1. 3.1. 使用
    2. 3.2. 兼容性
  4. 4. 参考
|