stencil 组件

stencil 组件

    • 装饰器
      • 生命周期
      • 应用加载事件
    • 组件定义
      • 组件如何响应数据变化
    • 组件使用
      • 如何传递 slot
      • 如何暴露组件内部的方法供外部使用?
      • `@Element` 装饰器
    • Host 组件
    • 样式
    • 函数组件

stencil 提供一些装饰器、生命周期钩子和渲染函数去编写一个组件。

装饰器

装饰器是一组用于声明组件元数据的函数,会在构建产物中移除,所以不会有运行时开销。

  • @Component() 声明一个类是组件
  • @Prop() 声明一个组件的特性或者属性
  • @State() 声明组件内部状态
  • @Watch() 监听 prop 或者 state 的改变,然后执行副作用
  • @Listen() 监听组件内部的 DOM 事件
  • @Event() 声明自定义事件
  • @Method() 暴露组件方法
  • @Element() 声明组件变化的自定义标签

生命周期

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第一次挂载

connectedCallback
⬇️
componentWillLoad
⬇️
componentWillRender
⬇️
render
⬇️
componentDidRender
⬇️
componentDidLoad
⬇️
disconnectedCallback # 组件被移除

prop 或者 state 更新:

@Watch
⬇️
componentShouldUpdate
⬇️
componentWillUpdate
⬇️
componentWillRender
⬇️
render
⬇️
componentDidRender
⬇️
componentDidUpdate
⬇️
disconnectedCallback # 组件被移除

常用的:

connectedCallback 会调用多次:首次和移除后再添加到 DOM 都会调用,可设置定时器、监听原生事件等。

const el = document.createElement('my-cmp')
document.body.appendChild(el)
// connectedCallback() called
// componentWillLoad() called (first time)el.remove()
// disconnectedCallback()document.body.appendChild(el)
// connectedCallback() called again, but `componentWillLoad()` is not.

disconnectedCallback 组件从 DOM 中移除时调用,可在此做一些收尾工作。

componentWillLoad 在 render 之前调用, 调用一次
可再次发送 ajax 请求获取数据。

componentShouldUpdate(newValue,oldValue,property)

返回布尔值,决定组件是否重新渲染。

可以更新状态的钩子有:

componentWillLoad
@Watch
componentWillUpdate
componentWillRender

componentDidLoad(), componentDidUpdate() and componentDidRender() 更新状态,会导致再次渲染。

componentDidUpdate()、componentDidRender() 可能导致无限渲染。

父子组件的生命周期:

<cmp-a><cmp-b><cmp-c></cmp-c></cmp-b>
</cmp-a>
cmp-a - componentWillLoad()
cmp-b - componentWillLoad()
cmp-c - componentWillLoad()cmp-c - componentDidLoad()
cmp-b - componentDidLoad()
cmp-a - componentDidLoad()

Component Lifecycle Methods

应用加载事件

一个特殊的生命周期钩子,在整个应用加载完成后触发。

window.addEventListener('appload', event => {console.log(event.detail.namespace)
})

组件定义

import { Component, Prop, h, EventEmitter, Event } from '@stencil/core'// 组件装饰器
@Component({tag: 'app-input', // 名字全局唯一styleUrl: 'index.scss', // 组件的样式shadow: true, // 开启 shadow root 封装组件样式
})
export class MyInput {@Prop() value: string | number = ''@Event({ eventName: 'input' }) input: EventEmitter// 直接使用属性名称作为事件名称@Event() inputChanged: EventEmitteronInput(e: Event) {// e.preventDefault() // 默认行为不行e.stopPropagation()const inputEle = e.target as HTMLInputElementthis.input.emit(inputEle.value)}onChange(e: Event) {const inputEle = e.target as HTMLInputElementthis.inputChanged.emit(inputEle.value)}render() {return <input value={this.value} onInput={e => this.onInput(e)} onChange={e => this.onChange(e)} />}
}

解读:

  • @Component装饰器声明该类是一个组件,传递一些元数据,比如组件的标签,标签必须全局唯一,且含有-,样式,是否开启 shadow 等。

tag 属性必需,更多参数

  • @Prop声明组件的属性

关于命名

在组件内部使用小驼峰命名,在 html 使用 dash-case 传递数据。

如何处理原生属性?

添加到自定义标签上。

如何传递对象、数组等复杂数据?

在 stencil 组件中,和 jsx 一样。

在 html 中,所有属性都是字符串,只能传递字符串

comInstance.setAttribute('prop', value) // 无效
comInstance.prop = value // work well 且对对象和数组无效

如何在 html 中修改 prop?

暴露方法和设置 prop 可变,在外部调用方法修改。

prop 的选项

export interface PropOptions {attribute?: string = falsemutable?: boolean = falsereflect?: boolean = false
}

prop 默认是组件内部不可变更的,否则触发警告通过 mutable 修改这个默认行为。

reflect:声明 DOM prop 是否对应到标签特性上,设置为 true,在 html 标签上,会显示该属性。

@Component({ tag: 'my-cmp' })
class Cmp {@Prop({ reflect: true }) message = 'Hello'@Prop({ reflect: false }) value = 'The meaning of life...'@Prop({ reflect: true }) number = 42
}

渲染结果:

<my-cmp message="Hello" number="42"></my-cmp>

不设置为 true,依然可以通过 DOM 对象拿到 prop。

修改特性名字 attribute

如何验证 prop?

在 Watch 中验证 prop 合法性,不合法抛出错误。

如何设置必需?

都默认可选,可在 Watch 验证是否必须。

  • @Event声明组件触发的事件,后面是事件名称

this.eventName.emit(data) 触发自定义事件,data 是发送到父组件的数据,监听 eventName 事件时通过 event.detail 获取到 data

在自定义标签上仍然能监听到原生事件,如何避免监听到原生事件呢?

阻止事件冒泡,必要时取消默认行为。

如何监听?

  • @Listen(eventName)监听事件,绑定到组件上,可通过第二个参数配置绑定的元素。
    @Listen 监听全局事件很有用。

  • 在 jsx 中,通过onXxx监听

  • html 中通过addEventListener

更多事件信息

组件如何响应数据变化

当 props 和 state 改变,stencil 重新渲染,比较变化时,比较的时引用,所以数组和对象,引用不变,不会更新。

Reactive Data

组件使用

通过自定义标签 app-input 在 stencil 组件中使用:

import { Component, h, Host, State, Watch } from '@stencil/core'@Component({tag: 'app-home',styleUrl: 'app-home.css',shadow: true,
})
export class AppHome {@State() input = 'hello world'onInput(e: CustomEvent<HTMLAppInputElement>) {this.input = e.detail as unknown as string}// NOTE 监听原生事件// 被组件内阻止事件冒泡后,监听不到onNativeChange(e: Event) {const inputEle = e.target as HTMLInputElementconsole.log('原生事件', inputEle.value)}onChange(e: CustomEvent<HTMLAppInputElement>) {console.log(e.detail)}@Watch('input')inputChanged(newValue: string, oldValue: string) {console.log(newValue, oldValue)}render() {return (<app-inputvalue={this.input}onInput={e => this.onInput(e)}onInputChanged={this.onChange}onChange={this.onNativeChange}/>)}
}

如何传递 slot

<Host><slot name='prepend'></slot><input value={this.value} onInput={e => this.onInput(e)} onChange={e => this.onChange(e)} /><slot name='append'>hello</slot>
</Host>

从父组件传递:

<app-input>{/* 不指定slot名字,无法处理 */}{/* <h1>header one</h1> */}<h2 slot='prepend'> append slot</h2>{/* <div slot='append'> */}<span slot='append'>append</span><span slot='append'>append one</span><span slot='append'>append another</span>{/* </div> */}
</app-input>

如何通过 slot 传递数据到父组件?

slot 的高级用法

如何暴露组件内部的方法供外部使用?

通过 @Method 暴露方法, ref 获取组件实例,调用组件方法。

  @Method() // @Method 装饰器要求方法返回Promiseasync getValue() {return this.value}

在父组件通过 ref 调用组件方法

@Component({tag: 'app-home',styleUrl: 'app-home.css',shadow: true,
})
export class AppHome {person: Person = { name: 'John', age: 23 }appInput!: HTMLAppInputElementcomponentWillLoad() {console.log('Component is about to be rendered', this.appInput)}componentDidLoad() {console.log(this.appInput) // 组件实例this.appInput.getValue().then(console.log)console.log(this.appInput.person) // 拿到自定义属性console.log(this.appInput.title) // 拿到原生属性// console.log(this.appInput?.onInput)// 拿不到没有暴露的方法}render() {return <app-input ref={refInput => (this.appInput = refInput)} person={this.person} title='input' />}
}

通过函数的方式绑定 ref 到组件上,组件挂载后,ref 是组件实例。

prop、method、原生属性是共有的,其他都是私有的。

@Element 装饰器

在组件内部获取自组件实例。

和在组件外部通过 ref 获取组件实例,值是同一个。

Host 组件

Host 组件一个内置组件,不会渲染到页面上。

常用的场景:

  • 在组件内部设置自定义标签的属性
import { Component, Host, h } from '@stencil/core'@Component({ tag: 'todo-list' })
export class TodoList {@Prop() open = falserender() {return (<Hostaria-hidden={this.open ? 'false' : 'true'}class={{'todo-list': true,'is-open': this.open,}}/>)}
}
  • 作为Fragment

样式

stencil 使用 Shadow DOM 要封装 DOM 和样式,内部样式不泄露到外部,外部样式不影响组件内部的 DOM。

@Component({shadow: true,// 启用 shadow DOM
})

不启用,和平时的 style 一样书写,就是全局样式。

启用后:

  • 样式隔离:内外部样式不相互影响。

  • 设置样式的选择改变

启用前,可通过自定义标签获取到 DOM

app-input {
}

启用后,自定义标签失效,使用 :host

:host {
}

启用后,对 :host 选择器有影响,目前还不清楚是什么影响。

都使用 :host

  • 获取 DOM 的方式改变
this.el.querySelector('div') // 启用前
this.el.shadowRoot.querySelector('div') // 启用后

如何从外部改变内部的样式?

  • CSS custom 变量

CSS 变量往往设置成全局的,但是全局样式文件只能导入一个。

  • ::part and ::theme, an ::explainer
  • 全局样式

哪些情况该考虑使用全局样式:

  1. Theming: defining CSS variables used across the app

  2. 字体

  3. body background

  4. CSS resets

更多教程

函数组件

import { h } from '@stencil/core'
import './index.css'
export const Hello = props => <h1>Hello, {props.name}!</h1>

函数组件无法使用样式,且只能在 JSX 中使用,以大写字母开头,不能在 html 中使用,这个很坑爹。

函数组件还有以下限制:

  • 不会被编译成 web component,故无法在 html 中使用
  • 不能使用生命周期函数
  • 不会创建 DOM 节点
  • 无法使用 shadow DOM 和 scoped style,其实无法应用样式

这些特点,限制了函数组件的使用场景,除了 renderProp ,几乎无用。

renderProp 只能在 jsx 中使用。

How To Build Web Components Using Stencil JS

Creating Web Components with Stencil

你的前端框架要被 Web 组件取代了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/862272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】高级IO——五种IO模型和基本概念 ,非阻塞IO,fcntl,实现非阻塞IO,同步通信和异步通信

文章目录 Linux高级IO1. 五种IO模型1.1 阻塞IO1.2 非阻塞IO1.3 信号驱动IO1.4 IO多路转接1.5 异步IO 2. 同步通信和异步通信3. 阻塞和非阻塞 Linux高级IO 1. 五种IO模型 IO是什么&#xff1f; IO是计算机领域中的缩写&#xff0c;指的是输入/输出&#xff08;Input/Output&…

狂撒1.69亿美元却对加密避而不谈?揭秘加密大选背后的金钱政治

撰文&#xff1a;Jesse Hamilton 来源&#xff1a;Coindesk 编译&#xff1a;Ning 在政治选举中&#xff0c;有钱能使鬼推磨这句俗语体现地淋漓尽致&#xff0c;而直接诞生的产物&#xff0c;就是独具特色的政治行动委员会&#xff08;PAC&#xff09;&#xff0c;各类型捐赠者…

你的钱花得值不值?简谈FMEA培训的投资与回报

在探讨 FMEA&#xff08;失效模式及影响分析&#xff09;培训是否值得投资时&#xff0c;需要综合考虑多个方面。 从投资的角度来看&#xff0c;FMEA 培训通常需要一定的费用支出&#xff0c;包括培训课程的费用、培训期间员工的时间成本以及可能涉及的培训材料和设备成本。 然…

基于RK3588的GMSL、FPDLink 、VByone及MIPI等多种摄像模组,适用于车载、机器人工业图像识别领域

机器人&工业摄像头 针对机器人视觉与工业检测视觉&#xff0c;信迈自主研发和生产GMSL、FPDLink 、VByone及MIPI等多种摄像模组&#xff0c;并为不同应用场景提供多种视场角度和镜头。拥有资深的图像算法和图像ISP专家团队&#xff0c;能够在软件驱动层开发、ISP算法、FPG…

Solr安装IK中文分词器

Solr安装IK中文分词器 如何安装Solr与导入数据&#xff1f;为什么要安装中文分词器下载与安装IK分词器1.1、下载IK分词器1.2、安装IK  第一步&#xff1a;非常简单&#xff0c;我们直接将在下的Ik分词器的jar包移动到以下文件夹中  第二步&#xff1a;修改Core文件夹名下\c…

家电品牌如何利用3D数字化技术,突破转型瓶颈?

家电行业正经历着从增量市场向存量市场的转变&#xff0c;用户的消费观念也日趋成熟&#xff0c;更加注重产品的体验和服务质量。无论是线上购物平台还是线下实体门店&#xff0c;提供个性化和增强体验感的产品与服务已成为家电市场未来发展的核心驱动力。 51建模网依托“3D数字…

基于单片机和组态王的温度监控系统的设计

摘 要 : 介绍了以 MSP430 单片机为核心 , 建立基于 DS18B20 和组态王的温度采集和监控系统。主要研究了单片机和组态王的通用通讯协议。按照 KingView 提供的通信协议 , 设计组态王与单片机的通信程序 , 实现了组态王与M SP430 单片机的直接串行通讯。在中药提取装置的…

实现在父盒子中点击生成子盒子并识别父盒子边界不溢出

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</…

Excel单元格输入逐字动态提示可选输入效果制作

Excel单元格输入逐字动态提示可选输入效果制作。INDEX函数整理动态列表&#xff0c;再配合IF函数干净界面&#xff0c;“数据验证”完成点选。 (笔记模板由python脚本于2024年06月27日 22:26:14创建&#xff0c;本篇笔记适合喜欢用Excel处理数据的coder翻阅) 【学习的细节是欢悦…

浅谈制造业EHS管理需要关注的重点

在快速发展的制造业中&#xff0c;EHS&#xff08;环境、健康、安全&#xff09;管理体系如同一道坚实的屏障&#xff0c;守护着企业的绿色与安全。那么&#xff0c;这个管理体系到底包含哪些内容呢&#xff1f;接下来&#xff0c;让我们一同探寻其奥秘。 一、EHS管理体系的丰富…

vue3日历选择器

倒叙日历&#xff1a; <template><div class"date-picker"><div class"column" wheel"onYearScroll"><div v-for"(year, index) in displayedYears" :key"index" :class"{current: year current…

SyntaxError: Unexpected token ‘??=‘

前端运行报错&#xff1a; globalThis.GLOBAL_NX_VERSION ?? GLOBAL_NX_VERSION;^^^SyntaxError: Unexpected token ??解决&#xff1a; 检查node版本 node -v当前使用的是14.21.3的版本&#xff0c;切换到一个16.0.0以上的版本即可&#xff0c;推荐使用nvm管理node版本 …

全球视角下的AI安全挑战:面向未来的准备

云安全联盟大中华区即将推出人工智能安全认证专家&#xff08;Certified Artificial Intelligence Security Professional&#xff0c;CAISP&#xff09;培训及认证计划&#xff0c;将在Q3全面上线。 在全球科技创新的洪流中&#xff0c;人工智能&#xff08;AI&#xff09;无…

vue+fineReport 使用前端搜索+报表显示数据

--fineReprot 将需要搜索的参数添加到模版参数 sql&#xff1a; --前端传递参数 注&#xff1a;因为每次点击搜索的结果需要不一样&#xff0c;还要传递一个时间戳的参数&#xff1a; let timesamp new Date().getTime()

项目测试计划(Word)

1简介 1.1 目的 1.2 范围 2. 测试参考文档和测试提交文档 2.1 测试参考文档 2.2 测试提交文档 3. 测试策略 3.1整体测试策略 3.2功能测试 3.3 界面测试 3.4 性能测试 3.5 安全性测试 3.6 工具 4 测试阶段进入和退出标准 4.1进入标准 4.2退出标准 5 测试范围 5.1需要测试的模块 …

uboot基本使用网络命令和从服务器端下载linux内核启动

网络命令ip地址设置: setenv gmac_debug 0; setenv mdio_intf rgmii; setenv bootdelay 1; setenv ethaddr 00:xxxx:81:70; // mac地址 setenv ipaddr xxx; //开发板 IP 地址 setenv netmask 255.255.255.0; setenv gatewayip xxx.1; setenv serverip xxxx; //服…

企业数据治理必备工具:智能元数据管理平台

当下&#xff0c;企业拥有海量数据&#xff0c;但仅拥有数据并不能释放数据价值。我们还需要深入了解数据的各种属性、来源和关系等信息。这些信息被称为“元数据”&#xff0c;即用于描述数据的数据。 假设&#xff0c;把我们每个人的身份证、户口本都当做数据&#xff0c;那…

使用 Python 注销、重启、关闭计算机

众所周知&#xff0c;Python 是一种功能强大的脚本语言。在本文中&#xff0c;将编写一个 Python 程序本控制计算机&#xff0c;实现计算机的注销、重启、关闭等操作。 Python 中的 os 模块&#xff0c;提供了一种与操作系统交互的方式&#xff0c;可以使用 os.system() 函数在…

统信桌面操作系统上使用命令行添加软件图标到任务栏

原文链接&#xff1a;统信桌面操作系统上使用命令行添加软件图标到任务栏 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在统信桌面操作系统上使用命令行添加软件图标到任务栏的文章。通过命令行将常用软件的图标添加到任务栏&#xff0c;可以快速启动软件&#xf…

20240627优雅草新产品取得原始软件著作权授权

https://doc.youyacao.com/22/2153 20240627优雅草新产品取得原始软件著作权授权 介绍 历程消息&#xff1a;优雅草2024年新产品最新取得原始著作权两份&#xff0c;2款产品将在近期完成为商业授权产品在蜻蜓松鼠官网售卖&#xff0c;本两款产品是智慧园区能源监测管理系统解…