Web Components简单用法介绍

2023-11-03

Web Components

浏览器原生组件,不用加载外部模块,代码量小。它允许用户创建可重用的定制元素,并在web应用中使用它们。

使用方法

一、自定义元素

自定义HTML标签称为自定义元素,自定义元素的名称必须包含连词线(如:user-card),用于区别原生HTML元素。

自定义元素的方法:

1. 自定义UserCard类
class UserCard extends HTMLElement {
    constructor() {
        super();
    }
}
2. 使用浏览器原生的customElements.define()方法,告诉浏览器user-card元素与该类相连
window.customElements.define('user-card',UserCard)
3. 在页面中直接插入以下标签即可使用
<user-card></user-card>

二、自定义元素的内容

给自定义元素添加内容包括两种方式

1. 通过JS添加

// 1. 定义继承自HTMLElement的UserCard类
class UserCard extends HTMLElement {
  // 2. 编写构造函数
  constructor() {
    // 3. 继承父类方法,必写
    super();
    // 4. 创建自定义的页面元素
    // 4.1 创建class为container的div
    var container = document.createElement("div");
    container.classList.add("container");
    // 4.2 创建class为name,innerHTML为“姓名:XXX”的p标签
    var name = document.createElement("p");
    name.classList.add("name");
    name.innerText = "姓名:XXX";
    // 4.3 创建class为email,内容为“邮箱:XXX”的p标签
    var email = document.createElement("p");
    email.classList.add("email");
    email.innerText = "邮箱:XXX";
    // 4.4 创建class为button,文字为“详细信息”的button按钮
    var button = document.createElement("button");
    button.classList.add("button");
    button.innerText = "详细信息";
    // 将name,email,button添加为container的子元素
    container.append(name, email, button);
    // this.append()的this表示<user-card></user-card>。
    // 将container 的内容填入<user-card></user-card>
    this.append(container);
  }
}
// 声明"user-card"代表刚刚定义的UserCard
window.customElements.define("user-card", UserCard);

完成这一步以后,自定义元素内部的 DOM 结构就已经生成了。

2. 通过 template 标签添加

<template>标签可以用来在HTML中定义DOM,它由Web Components API 提供。用于避免使用JS写DOM结构(很麻烦)。

完整代码如下:

<body>
<user-card></user-card>

<template id="userCardTemplate">
   <img src="https://semantic-ui.com/images/avatar2/large/kristy.png" class="image">
   <div class="container">
     <p class="name">User Name</p>
     <p class="email">yourmail@some-email.com</p>
     <button class="button">Follow</button>
   </div>
</template>

<script>
 // 改写一下自定义元素的类,为自定义元素加载<template>。
 class UserCard extends HTMLElement {
   constructor() {
     super();

     var templateElem = document.getElementById('userCardTemplate');
     var content = templateElem.content.cloneNode(true);
     this.appendChild(content);
   }
 }
 window.customElements.define('user-card', UserCard);    
</script>
</body>

三、添加样式

为自定义元素指定样式:把样式写在template里面

<template id="userCardTemplate">
  <style>
   :host {
     display: flex;
     align-items: center;
     width: 450px;
     height: 180px;
     background-color: #d4d4d4;
     border: 1px solid #d5d5d5;
     box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
     border-radius: 3px;
     overflow: hidden;
     padding: 10px;
     box-sizing: border-box;
     font-family: 'Poppins', sans-serif;
   }
   .image {
     flex: 0 0 auto;
     width: 160px;
     height: 160px;
     vertical-align: middle;
     border-radius: 5px;
   }
   .container {
     box-sizing: border-box;
     padding: 20px;
     height: 160px;
   }
   .container > .name {
     font-size: 20px;
     font-weight: 600;
     line-height: 1;
     margin: 0;
     margin-bottom: 5px;
   }
   .container > .email {
     font-size: 12px;
     opacity: 0.75;
     line-height: 1;
     margin: 0;
     margin-bottom: 15px;
   }
   .container > .button {
     padding: 10px 25px;
     font-size: 12px;
     border-radius: 5px;
     text-transform: uppercase;
   }
  </style>

  <img src="https://semantic-ui.com/images/avatar2/large/kristy.png" class="image">
  <div class="container">
    <p class="name">User Name</p>
    <p class="email">yourmail@some-email.com</p>
    <button class="button">Follow</button>
  </div>
</template>

四、自定义元素参数

自定义元素允许调用时传入不同数据形成个性化显示。

实现方式:通过在<user-card>添加属性和值,在JS中通过this.getAttribute()获取个性化数值,实现个性化展示。

<user-card
  image="https://semantic-ui.com/images/avatar2/large/kristy.png"
  name="User Name"
  email="yourmail@some-email.com"
></user-card>
<template id="userCardTemplate">
  <style>...</style>

  <img class="image">
  <div class="container">
    <p class="name"></p>
    <p class="email"></p>
    <button class="button">Follow John</button>
  </div>
</template>
<script>
class UserCard extends HTMLElement {
  constructor() {
    super();

    var templateElem = document.getElementById('userCardTemplate');
    var content = templateElem.content.cloneNode(true);
    content.querySelector('img').setAttribute('src', this.getAttribute('image'));
    content.querySelector('.container>.name').innerText = this.getAttribute('name');
    content.querySelector('.container>.email').innerText = this.getAttribute('email');
    this.appendChild(content);
  }
}
window.customElements.define('user-card', UserCard);    
</script>

五、shadow DOM

用于将<user-card>的内部代码隐藏,让用户看不到。且内部代码无法影响外部。

开启方法:this.attachShadow()

class UserCard extends HTMLElement {
  constructor() {
    super();
      // { mode:'closed' }表示Shadow DOM 是封闭的,不允许外部访问。
    var shadow = this.attachShadow( { mode: 'closed' } );

    var templateElem = document.getElementById('userCardTemplate');
    var content = templateElem.content.cloneNode(true);
    content.querySelector('img').setAttribute('src', this.getAttribute('image'));
    content.querySelector('.container>.name').innerText = this.getAttribute('name');
    content.querySelector('.container>.email').innerText = this.getAttribute('email');

    shadow.appendChild(content);
  }
}
window.customElements.define('user-card', UserCard);

六、组件的扩展

添加监听事件

this.$button = shadow.querySelector('button');
this.$button.addEventListener('click', () => {
  // do something
});

组件的封装

将js脚本与<template>封装成js文件,形成独立的组件文件。网页只要加载这个脚本就可以使用<user-card>组件。

参考链接

阮一峰—Web Components 入门实例教程https://www.ruanyifeng.com/blog/2019/08/web_components.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web Components简单用法介绍 的相关文章

  • Gradle 复制文件 无知的菜墩

    Gradle 复制文件 很多大佬都是直接贴出如下代码 简单说就是 task 直接使用 from into include 等方法 然而直接复制下来之后 过了俩小时零一秒钟后依然无法使用 一直不生效 task nestedSpecs type
  • Go Facade外观(门面)设计模式

    动机 Motivation 上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合 随着外部客户程序和各子系统的演化 这种过多的耦合面临很多变化的挑战 如何简化外部客户程序和系统间的交互接口 如何将外部客户程序的演化和内部子系
  • hbuilderx自定义常用代码块

    apipost body let res await this http post 1 if res code 200 2 else this toast res msg prefix apipost project uni app sco
  • hdu 5831 Rikka with Parenthesis II 2016 Multi-University 8

    Problem acm hdu edu cn showproblem php pid 5831 题意 给个括号序列 问能不能通过一次把两个不同位置的符号交换的操作 使得序列里的所有括号左右配对合法 分析 左括号进栈 如果是右括号而且栈顶是左
  • Linux性能监控命令_sar & 自动保存30天历史信息

    简介 sar命令将操作系统中选定的累积活动计数器的内容写入标准输出 计费系统根据 count 和 interval参数中的值 以秒为单位 按照指定的时间间隔写入指定次数的信息 目录 1 语法 1 1 常用参数 2 常见用法 2 1 监控CP

随机推荐

  • HTTP->WebRTC演进路径

    first HTTP Pre AJAX 原始web 一页里发送请求后才返回另一页 如Geocities second AJAX 2004 更新页面不需要刷新 如GMail third Web Sockets 2008 页面能建立双向通信 通
  • Android 10 暗黑模式适配,你需要知道的一切

    在 Android 10 里 Dark theme 暗黑模式得到了系统级的支持 暗黑模式不仅酷炫 而且有降低屏幕耗电 在光线较暗的环境中使用更舒适等好处 今天带大家看一下如何适配暗黑模式 本文会从以下几点进行介绍 动态开启暗黑模式 使用 D
  • 解密IP地址的不同潜力与应用场景

    作为专业爬虫代理供应商 我们经常需要面对不同的IP地址需求 在IP地址选择中 动态IP和静态IP是两个常见的选项 但究竟什么是动态IP和静态IP 它们有什么区别和优势 适用于哪些场景 本文将为你详细解答 让你对IP地址有更全面的了解 第一部
  • html文字图片同一行,CSS控制图片和文字在同一行显示且对齐的3种方法

    CSS控制图片和文字在同一行显示且对齐的3种方法 在 HTML 代码中 有时会需要在文字旁边加上一个图标 默认情况 是图片置顶对齐 文字置底对齐 所以通常图片高 文字低 不能水平居中对齐 常见欢思中属餐显近和想都性厅示近和想都性厅示方法有3
  • Java并发JUC集合类

    文章目录 Java并发JUC集合类 为什么HashTable慢 它的并发度是什么 ConcurrentHashMap在JDK1 7和JDK1 8中实现有什么差别 JDK1 8解決了JDK1 7中什么问题 ConcurrentHashMap
  • Java jinfo 命令详解

    jinfo 命令可以用来查看 Java 进程运行的 JVM 参数 命令如下 root admin jinfo help Usage jinfo option
  • 40 多名直接下属、从不 1 对 1 沟通,老黄如此管理下的英伟达能在 AI 芯片领域称霸多久?...

    省时查报告 专业 及时 全面的行研报告库 省时查方案 专业 及时 全面的营销策划方案库 免费下载 2023年8月份全网热门报告合集 ChatGPT提词示例 让你的ChatGPT聪明100倍 超百页干货资料 AI应用的难点 痛点与未来 202
  • It's Not Just Standing Up: Patterns of Daily Stand-up Meetings

    It s Not Just Standing Up Patterns of Daily Stand up Meetings Jason Yip ThoughtWorks Inc jcyip thoughtworks com http mar
  • VScode launch.json和tasks.json文件的配置

    task json version 2 0 0 command g args g file o file exe 编译命令参数 problemMatcher owner cpp fileLocation relative workspace
  • 高效的学习方法(费曼学习方法)

    学习技巧有四个简单的步骤 1 提取书本信息 阅读并理解 拿出一张白纸简要概括知识点以及对知识点进行深度拓展和横向拓展 深度拓展指增强知识点的理解深度 可以通过提问题的方式加强深度理解 横向拓展指增强其阅读广度 通过与其他学科建立关联 2 在
  • #pragma once和#ifndef / #define / #endif的区别

    转摘自 http www 360doc com content 10 0124 00 722458 14261695 shtml pragma once 指令格式如下 pragma once这是一个比较常用的指令 只要在头文件的最开始加入这
  • 华为OD机试 - 跳房子II(Java)

    题目描述 跳房子 也叫跳飞机 是一种世界性的儿童游戏 游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格 然后获得一次选房子的机会 直到所有房子被选完 房子最多的人获胜 跳房子的过程中 如果有踩线等违规行为 会结束当前回合 甚至可能
  • c++什么时候使用new,调用构造函数

    new 补充 构造函数的调用 对象 可以调用成员函数 不可以调用构造函数 我们无法像调用成员函数那样使用对象来调用构造函数 因为在构造函数构造出对象之前 对象是不存在的 因此构造函数被用来创建对象 而不能通过对象来调用 详见 构造函数的4种
  • 三台机器搭建redis集群过程及问题记录

    文章目录 1 前言 2 搭建集群 3 遇到的问题 4 相关文章 1 前言 Redis版本 5 0 4 服务器版本 Linux CentOS 6 CentOS 7 CentOS 9 redis集群需要至少要三个master节点 我们这里搭建三
  • prometheus 服务发现原理

    服务发现 概述 如上图 Prometheus核心功能包括服务发现 数据采集和数据存储 服务发现模块专门负责发现需要监控的目标采集点 target 信息 数据采集模块从服务发现模块订阅该信息 获取到target信息后 其中就包含协议 sche
  • selenium+python:Excel 存储数据,在已存在的Excel修改写入数据 并保存

    三 Excel文件的写入 思路 新建Excel表格 新增该表格的工作表 根据指定的行和列写入数据 保存Excel表格 参考链接 http www cnblogs com chjbbs p 4153239 html 具体代码如图 4 所示 4
  • MyBatis学习(四):MyBatis使用代理方法(接口)实现数据库的操作

    在第一篇简单的mybatis示例中 我们简单的介绍了如何通过SQL映射文件来实现对数据库的操作 在对数据库操作的时候是采用上图中的1 2来实现对数据库的操作 见上图就可以实现对数据库的操作了 但是这样做还是不太方便 有没有更好的方法呢 接口
  • 基于流计算 Oceanus(Flink) CDC 做好数据集成场景

    由于第一次做实时 所以踩坑比较多 见谅 测试环境用的flink 小公司没有用到hadoop组件 一 踩坑记录 1 本地代码的flink版本是flink1 15 4 生产环境是flink1 16 1 在使用侧输出流时报错 需要使用以下写法 需
  • Candy Machine--前缀和&&二分查找

    任意门 JB loves candy very much One day he finds a candy machine with N candies in it After reading the instructions of the
  • Web Components简单用法介绍

    目录 Web Components 使用方法 一 自定义元素 自定义元素的方法 1 自定义UserCard类 2 使用浏览器原生的 customElements define 方法 告诉浏览器 user card 元素与该类相连 3 在页面