先让我们来看看自定义 Web components 的生命周期。简单示例如下:
class MyElement extends HTMLElement { constructor() { // always call super() first super(); console.log('constructed!'); } connectedCallback() { console.log('connected!'); } disconnectedCallback() { console.log('disconnected!'); } attributeChangedCallback(name, oldVal, newVal) { console.log(`Attribute: ${name} changed!`); } adoptedCallback() { console.log('adopted!'); } } window.customElements.define('my-element', MyElement);
constructor()
构造函数,每当元素创建时 constructor
都会运行,且是在将元素附加到文档之前运行。我们将使用 constructor
来设置一些初始状态、事件侦听器和创建 shadow DOM。
与 React 中的 constructor
一样,都是类的构造函数。相当于在 React Hooks 中的组件初始化属性
const App = ()=>{ const [state, setstate] = useState(initialState) }
connectedCallback()
当元素插入 DOM 时,将调用 connectedCallback
。这是运行安装程序代码的好地方,例如获取数据或设置默认属性。
有点类似 React 的 componentDidMount
,组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染。
相当于在 React Hooks 中的组件初始化请求,也可以在这里面编写一些订阅。
const App = ()=>{ useEffect(() => { // 每次创建时执行 }, []) }
disconnectedCallback()
每当从 DOM 中删除元素时,都会调用 disconnectedCallback
,清理时间!我们可以使用 disconnectedCallback
删除任何事件侦听器,或取消间隔。
有点类似 React 的 componentWillUnmount
,在此处完成组件的卸载和数据的销毁。
相当于在 React Hooks 中的 useEffect 的返回函数
const App = ()=>{ useEffect(() => { return ()=>{ // disconnectedCallback } }, []) }
attributeChangedCallback(name, oldValue, newValue)
只要元素的的属性发生更改,就会调用 attributeChangedCallback
。我们可以通过实现静态的 observedAttributes
观察者来观察元素的属性,如下所示:
static get observedAttributes() { return ['my-attr']; }
在这种情况下,只要更改了 'my-attr'
属性,就会运行 attributeChangedCallback
。
只有
observedAttributes
观察者中列出的值,才会在attributeChangedCallback
有响应.
这个在 React 中,可以通过在 componentWillReceiveProps
判断属性变化,来手动模拟。在React Hooks中却可以很容易的实现。
const App = ()=>{ useEffect(() => { // 'my-attr' 变化时调用 }, ['my-attr']) // 伪代码,为了对应上面的写法 }
adoptedCallback()
每次将自定义元素移动到新文档时,都会调用的回调。仅当页面中包含 <iframe>
元素时,才会遇到此用例。
(不知道是啥,没找到对应的概念。有懂得朋友,请帮忙指出。)
registering our element
这个虽然不是生命周期的一部分,但是是每次编写都需要执行的过程,将我们的自定义元素注册到 CustomElementRegistry
中,如下所示:
window.customElements.define('my-element', MyElement);
CustomElementRegistry
是一个接口,提供注册自定义元素和查询注册元素的方法。注册表的 define
方法的第一个参数将是元素的名称,因此在这种情况下,它将注册 <my-element>
,第二个参数将传递我们自定义的类。
请务必注意如何命名 Web 组件。自定义元素名称必须始终包含连字符。例如:<my-element>
是正确的,而 <myelement>
则不正确。这是有意为避免元素名称冲突而做的,并作为自定义元素和常规元素之间的区别。
自定义元素也不能是自闭合,因为 HTML 只允许几个元素自闭。这些称为空元素,如
<br/>
或<img/>
,或不允许子节点的元素允许自闭元素需要更改 HTML 解析器,因为 HTML 解析对安全性很敏感。HTML 生产者需要能够依赖于给定的 HTML 分析方式,以便能够实现 XSS 安全的 HTML 生成。
在 React 中,我们都是使用引入组件的方式使用,硬要找一个类似的概念,那可能是
react-dom
的 render
方法,第一个参数为我们自定义的类,第二个参数为渲染的 dom 节点。
import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render(<App />, document.getElementById('root') );
参考链接 web-components-lifecycle:(https://github.com/thepassle/webcomponents-from-zero-to-hero/blob/master/part-one/README.md#%EF%B8%8F-a-components-lifecycle)