web找不到自定义组件方法_Web组件自定义元素

web找不到自定义组件方法

I wrote my first Custom Element using a CSS library called CSS Doodle. It’s an amazing app that uses Custom Elements to let you create stunning CSS animations. That unlocked a whole new desire to figure out how that thing works under the hood. So I decided to take a better look at Web Components in general, a topic many people asked me to write about.

我使用名为CSS DoodleCSS库编写了第一个自定义元素。 这是一个了不起的应用程序,它使用“自定义元素”来创建令人惊叹CSS动画。 这就释放了一种全新的渴望,即弄清楚该东西是如何工作的。 因此,我决定从总体上更好地研究Web组件,这是许多人要求我撰写的主题。

Custom Elements let us create new HTML tags.

使用自定义元素,我们可以创建新HTML标签。

I could not imagine why this could be a useful thing until I used that CSS Doodle library. After all we already have lots of tags.

在使用CSS Doodle库之前,我无法想象为什么这可能是有用的事情。 毕竟我们已经有很多标签。

This tutorial covers Custom Elements version 1, the latest release of the standard at the time of writing

本教程介绍了Custom Elements版本1,该标准是撰写本文时的最新版本

Using Custom Elements we can create a custom HTML tag with associated CSS and JavaScript.

使用自定义元素,我们可以创建具有关联CSS和JavaScript的自定义HTML标签。

It’s not an alternative to frameworks like React, Angular or Vue, but it’s a whole new concept.

它不是React,Angular或Vue等框架的替代品,而是一个全新的概念。

The window global object exposes a customElements property that gives us access to a CustomElementRegistry object.

window全局对象公开了customElements属性,该属性使我们可以访问CustomElementRegistry对象。

CustomElementRegistry对象 (The CustomElementRegistry object)

This object has several methods we can use to register Custom Elements and query Custom Elements already registered:

该对象有几种方法可用于注册自定义元素和查询已注册的自定义元素:

  • define() used to define a new Custom Element

    define()用于定义新的自定义元素

  • get() used to get the constructor of a Custom Element (returns undefined if not existing)

    get()用于获取自定义元素的构造函数(如果不存在,则返回undefined )

  • upgrade() to upgrade a Custom Element

    upgrade()升级自定义元素

  • whenDefined() used to get the constructor of a Custom Element. Similarly to get(), but it returns a promise instead, which resolves when the item is available.

    whenDefined()用于获取自定义元素的构造函数。 与get()类似,但是它返回一个promise,它在商品可用时解析。

如何创建自定义元素 (How to create a custom element)

Before we can call the window.customElements.define() method, we must define a new HTML element by creating a new class that extends the HTMLElement built-in class:

在调用window.customElements.define()方法之前,我们必须通过创建一个扩展HTMLElement内置类的新类来定义一个新HTML元素:

class CustomTitle extends HTMLElement {
	//...
}

Inside the class constructor we’re going to use Shadow DOM to associate custom CSS, JavaScript and HTML to our new tag.

在类构造函数中,我们将使用Shadow DOM将自定义CSS,JavaScript和HTML关联到我们的新标记。

In this way, all we’ll see in the HTML is our tag, but this will encapsulate a lot of functionality.

这样,我们在HTML中将看到的只是我们的标签,但这将封装许多功能。

We start by initializing the constructor:

我们从初始化构造函数开始:

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    //...
  }
}

Then, into it we call the attachShadow() method of the HTMLElement by passing an object with the mode property set to 'open'. This property sets the encapsulation mode for the shadow DOM. If it’s open we can access the shadowRoot property of an element. If it’s closed, we can’t.

然后,通过传递mode属性设置为'open'的对象,调用HTMLElement的attachShadow()方法。 此属性设置影子DOM的封装模式。 如果open则可以访问元素的shadowRoot属性。 如果关闭,我们不能。

Here’s how to do so:

这样做的方法如下:

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    //...
  }
}

Some examples you’ll find use the syntax const shadowRoot = this.attachShadow(/* ... */) but you can avoid so unless you set mode to closed, as you can always reference that object by calling this.shadowRoot.

您会发现一些示例使用语法const shadowRoot = this.attachShadow(/* ... */)但除非将mode设置为closed ,否则可以避免这样做,因为您始终可以通过调用this.shadowRoot引用该对象。

Which is what we’re going to do now, to set the innerHTML of it:

我们现在要做的是设置它的innerHTML:

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `
      <h1>My Custom Title!</h1>
    `
  }
}

You can add as many tags as you want, you’re not limited to one tag inside the innerHTML property

您可以根据需要添加任意多个标签,而不仅限于innerHTML属性中的一个标签

Now we add this newly defined element to window.customElements:

现在,我们将此新定义的元素添加到window.customElements

window.customElements.define('custom-title', CustomTitle)

and we can use the <custom-title></custom-title> Custom Element in the page!

我们可以在页面中使用<custom-title></custom-title>自定义元素!

Note: you can’t use self-closing tags (in other words: this <custom-title /> is not allowed by the standard)

注意:您不能使用自动关闭标签(换句话说:该<custom-title />是标准不允许的)

Notice the - dash in the tag name. We are required to use a dash in a Custom Element. This is how we can detect a built-in tag from a custom one.

注意标记名称中的-破折号。 我们需要在自定义元素中使用破折号 。 这就是我们可以从自定义标签中检测内置标签的方式。

Now we have this element in the page, and we can do what we do with other tags: target it with CSS and JavaScript!

现在,我们在页面中有了这个元素,我们可以使用其他标签进行操作:使用CSS和JavaScript定位它!

提供元素的自定义CSS (Provide a custom CSS for the element)

In the constructor, you can pass a style tag in addition to the HTML tag that defines the content, and inside that you can have the Custom Element CSS:

在构造函数中,除了可以定义内容HTML标记之外,还可以传递style标记,并且在其中可以包含Custom Element CSS:

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `
      <style>
        h1 {
          font-size: 7rem;
          color: #000;
          font-family: Helvetica;
          text-align: center;
        }
      </style>
      <h1>My Custom Title!</h1>
    `
  }
}

Here’s the example Custom Element we created, in Codepen:

这是我们在Codepen中创建的示例Custom Element:

See the Pen Web Components, My Custom Title by Flavio Copes (@flaviocopes) on CodePen.

见笔Web组件,我的自定义标题由弗拉维奥·科佩斯( @flaviocopes上) CodePen

语法较短 (A shorter syntax)

Instead of first defining the class and then calling window.customElements.define() we can also use this shorthand syntax to define the class inline:

除了先定义类然后再调用window.customElements.define()我们还可以使用以下速记语法来定义内联类:

window.customElements.define('custom-title', class extends HTMLElement {
  constructor() {
    ...
  }
})

添加JavaScript (Add JavaScript)

Just like we did for CSS, we can embed JavaScript.

就像我们对CSS所做的一样,我们可以嵌入JavaScript。

We can’t add it directly to the template tag like we did for CSS though.

但是,我们不能像我们对CSS那样直接将其添加到template标记中。

Here I define a click event listener in the Custom Element constructor:

在这里,我在Custom Element构造函数中定义了一个click事件监听器:

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `
      <h1>My Custom Title!</h1>
    `
    this.addEventListener('click', e => {
      alert('clicked!')
    })
  }
}

替代方案:使用模板 (Alternative: use templates)

Instead of defining the HTML and CSS in a JavaScript string, you can use a template tag in HTML and assign it an id:

除了在JavaScript字符串中定义HTML和CSS之外,您还可以在HTML中使用template标记并为其分配一个id

<template id="custom-title-template">
  <style>
    h1 {
      font-size: 7rem;
      color: #000;
      font-family: Helvetica;
      text-align: center;
    }
  </style>
  <h1>My Custom Title!</h1>
</template>

<custom-title></custom-title>

Then you can reference it in your Custom Element constructor and add it to the Shadow DOM:

然后,您可以在“自定义元素”构造函数中引用它,并将其添加到Shadow DOM:

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    const tmpl = document.querySelector('#custom-title-template')
    this.shadowRoot.appendChild(tmpl.content.cloneNode(true))
  }
}

window.customElements.define('custom-title', CustomTitle)

Example on Codepen:

Codepen上的示例:

See the Pen Web Components, My Custom Title with template by Flavio Copes (@flaviocopes) on CodePen.

请参阅CodePen上的Pen Web Components,“我的自定义标题”和 Flavio Copes( @flaviocopes )的模板

生命周期挂钩 (Lifecycle hooks)

In addition to constructor, a Custom Element class can define those special methods that are executed at special times in the element lifecycle:

constructor ,Custom Element类还可以定义在元素生命周期的特定时间执行的那些特殊方法:

  • connectedCallback when the element is inserted into the DOM

    将元素插入DOM中的connectedCallback

  • disconnectedCallback when the element is removed from the DOM

    从DOM中删除元素时, disconnectedCallback的回调

  • attributeChangedCallback when an observed attribute changed, or is added or removed

    attributeChangedCallback观察到的属性改变,或者被添加或删除

  • adoptedCallback when the element has been moved to a new document

    元素移到新文档时采用了adoptedCallback

    class CustomTitle extends HTMLElement {
    constructor() {
    ...
    }
    connectedCallback() {
    ...
    }
    disconnectedCallback() {
    ...
    }
    attributeChangedCallback(attrName, oldVal, newVal) {
    ...
    }
    }

attributeChangedCallback() gets 3 parameters:

attributeChangedCallback()获得3个参数:

  • the attribute name

    属性名称
  • the old value of the attribute

    属性的旧值
  • the new value of the attribute.

    属性的新值。

I mentioned it listens on observed attributes. What are those? We must define them in an array returned by the observedAttributes static method:

我提到过它监听观察到的属性。 那些是什么? 我们必须在observedAttributes静态方法返回的数组中定义它们:

class CustomTitle extends HTMLElement {
  constructor() {
    ...
  }

  static get observedAttributes() {
    return ['disabled']
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    ...
  }
}

I defined the disabled attribute to be observed. Now when it changes, for example in JavaScript we set disabled to true:

我定义了要观察的disabled属性。 现在,当它更改时,例如在JavaScript中,我们将disabled设置为true:

document.querySelector('custom-title').disabled = true

the attributeChangedCallback() fires with the set of parameters 'disabled', false, true.

attributeChangedCallback()会使用参数'disabled', false, true的集合触发。

Note: attributeChangedCallback() can be called on the element using JavaScript (for some unknown - to me - reason), but you shouldn’t do that. It should just be invoked automatically by the browser

注意:可以使用JavaScript在元素上调用attributeChangedCallback() (出于某种未知的原因-对我来说是原因),但是您不应该这样做。 它应该只是由浏览器自动调用

定义自定义属性 (Define custom attributes)

You can define custom attributes for your Custom Elements by adding a getter and setter for them:

您可以通过为它们的自定义元素添加一个getter和setter来定义自定义属性:

class CustomTitle extends HTMLElement {
  static get observedAttributes() {
    return ['mycoolattribute']
  }

  get mycoolattribute() {
    return this.getAttribute('mycoolattribute')
  }

  set mycoolattribute(value) {
    this.setAttribute('mycoolattribute', value)
  }
}

This is how you can define boolean attributes, ones that are “true” if present, like disabled for HTML elements:

这样可以定义布尔属性,如果存在,则为“ true”,例如disabled HTML元素:

class CustomTitle extends HTMLElement {
  static get observedAttributes() {
    return ['booleanattribute']
  }

  get booleanattribute() {
    return this.hasAttribute('booleanattribute')
  }

  set booleanattribute(value) {
    if (value) {
      this.setAttribute('booleanattribute', '')
    } else {
      this.removeAttribute('booleanattribute')
    }
  }
}

如何设置尚未定义的自定义元素的样式 (How to style a Custom Element that’s not yet defined)

JavaScript might take a little to kick in and a Custom Element might not be defined as soon as the page loads. The page might do an ugly re-layout when the element is added in the page.

JavaScript可能需要花费一点时间,并且页面加载后可能不会立即定义Custom Element。 在页面中添加元素时,页面可能会进行难看的重新布局。

To solve this problem, add a :not(:defined) CSS pseudo class that sets the height and fades in the element when available:

要解决此问题,请添加:not(:defined) CSS伪类,该伪类设置高度并在可用时淡入元素:

custom-title:not(:defined) {
 display: block;
 height: 400px;
 opacity: 0;
 transition: opacity 0.5s ease-in-out;
}

我可以在所有浏览器中使用它们吗? (Can I use them in all browsers?)

The current versions of Firefox, Safari and Chrome support them. IE will never do, and Edge at the time of writing has support for them in development.

当前版本的Firefox,Safari和Chrome支持它们。 IE将永远不会这样做,并且在撰写本文时,Edge在开发中已经为他们提供了支持。

You can use this polyfill to add a better support also for older browsers.

您可以使用此polyfill为旧版浏览器添加更好的支持。

翻译自: https://flaviocopes.com/web-components-custom-elements/

web找不到自定义组件方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值