文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Web Components如何实现类Element UI中的Card卡片

2023-07-02 16:05

关注

这篇“Web Components如何实现类Element UI中的Card卡片”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Web Components如何实现类Element UI中的Card卡片”文章吧。

Web Components 核心组成

1. Custom Elements

自定义的 HTML 标签,称为自定义元素(custom element)。根据规范,自定义元素的名称必须包含连词线-,用与区别原生的 HTML 元素。所以,<com-card>不能写成<comcard>

<div id="custom-card" class="com-card">  <div class="com-card-head">    <slot name="head"></slot>  </div>  <div class="com-card-body">    <slot></slot>    <div class="link-wrap">      <a class="link" href="" title=" rel="external nofollow"  rel="external nofollow" "></a>    </div>  </div></div><script>  class ComCard extends HTMLElement {    constructor() {      super()      var tplEle = document.getElementById('custom-card')      this.append(tplEle)    }  }  window.customElements.define('com-card', ComCard)</script>

这样就注册了浏览器可识别渲染的一个自定义元素标签。

2. Shadow DOM

Shadow DOM 是对DOM的一个封装。可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。
使用自定义元素的 this.attachShadow() 方法可以开启 Shadow DOM

class ComCard extends HTMLElement {  constructor() {    super()    var shadow = this.attachShadow({mode: 'closed'})  // open    var tplEle = document.getElementById('custom-card')    shadow.appendChild(tplEle)  }}window.customElements.define('com-card', ComCard);

其中参数{ mode: 'closed' },表示 Shadow DOM 是封闭的,不允许外部访问。

3. templates 和 slots

因为组件的样式应该与代码封装在一起,只对自定义元素生效,不影响外部的全局样式。所以,可以把样式写在<template>里面,这样作为自定义元素结构的基础可以被多次重用。

<template id="custom-card-template">  <style>    .com-card {    }  </style>  <div class="com-card">  </div></template><script>  class ComCard extends HTMLElement {    constructor() {      super();      var shadow = this.attachShadow({mode: 'closed'})  // open      var tplEle = document.getElementById('custom-card-template')      var content = tplEle.content.cloneNode(true)      shadow.appendChild(content)    }  }  window.customElements.define('com-card', ComCard);</script>

完整代码

<!DOCTYPE html><html><head>  <meta charset="UTF-8">  <title>Web Component</title>  <style>    * {        box-sizing: border-box;    }    body {        font-size: 14px;    }    .box {        padding: 5px 0 30px;    }    .box .caption {        display: none;    }    .box h2 {        text-align: center;    }    .box li {        color: #666;        font-size: 14px;        line-height: 1.8;        margin-top: 15px;    }    .img {        display: block;        width: 80%;        margin: 0 !important;    }    .card-head {        display: flex;        justify-content: space-between;        align-items: center;    }    .card-title {        color: #333;        font-size: 16px;    }    .card-head-btn {        color: #409eff;        cursor: pointer;        text-decoration: none !important;    }    .card-head-btn:hover {        text-decoration: none;    }  </style></head><body><div class="box">  <h2>Web Component</h2>  <com-card data-show-head="0" data-url="https://tiven.cn" data-title="天问博客">    <div slot="head" class="card-head">      <div class="card-title">卡片名称</div>      <a class="card-head-btn">操作按钮</a>    </div>    <img class="img" src="https://file.lsjlt.com/upload/202306/28/bh23o2zxbzf.jpg" alt="天問">  </com-card>  <br>  <br>  <com-card data-show-head="1" data-url="https://tiven.cn/p/de241e23/" data-title="Vite+Vue3+Vant快速构建项目">    <div slot="head" class="card-head">      <div class="card-title">卡片名称</div>      <a class="card-head-btn" onclick="hello()">操作按钮</a>    </div>    <img class="img" src="https://file.lsjlt.com/upload/202306/28/yrxrhzjgdpe.jpg" alt="天問">    <ol>      <li>君不见黄河之水天上来,奔流到海不复回。</li>      <li>君不见高堂明镜悲白发,朝如青丝暮成雪。</li>      <li>天生我材必有用,千金散尽还复来。</li>    </ol>  </com-card></div><template id="custom-card-template">  <style>    .com-card {        min-width: 200px;        min-height: 100px;        border-radius: 4px;        border: 1px solid #ebeef5;        background-color: #fff;        overflow: hidden;        color: #303133;        transition: .3s;        box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);    }    .com-card-head {        padding: 10px 20px;        border-bottom: 1px solid #ebeef5;        box-sizing: border-box;    }    .com-card-body {        padding: 20px;    }    .link-wrap {        text-align: left;        padding-top: 20px;    }    .link {        display: inline-block;        height: 42px;        line-height: 43px;        padding: 0 30px;        text-align: center;        cursor: pointer;        color: #fff;        background-color: #409eff;        border-color: #409eff;        -webkit-appearance: none;        box-sizing: border-box;        outline: none;        transition: .1s;        font-weight: 500;        -moz-user-select: none;        -webkit-user-select: none;        -ms-user-select: none;        font-size: 14px;        border-radius: 4px;        text-decoration: none !important;    }  </style>  <div class="com-card">    <div class="com-card-head">      <slot name="head"></slot>    </div>    <div class="com-card-body">      <slot></slot>      <div class="link-wrap">        <a class="link" href="" title=" rel="external nofollow"  rel="external nofollow" "></a>      </div>    </div>  </div></template><script>  class ComCard extends HTMLElement {    constructor() {      super();      var shadow = this.attachShadow({mode: 'closed'})  // open      var tplEle = document.getElementById('custom-card-template')      var content = tplEle.content.cloneNode(true)      var attrList = Array.from(this.attributes);      var props = attrList.reduce((prev, item)=>{        prev[item.name] = item.value        return prev      }, {})      if (props['data-show-head']!=='1') {        var head = content.querySelector('.com-card-head')        head.remove()      }      var urlEle = content.querySelector('.link')      if (props['data-url'] && props['data-title']) {        urlEle.href = props['data-url']        urlEle.title = props['data-title']        urlEle.innerText = props['data-title']      } else {        urlEle.remove()      }      shadow.appendChild(content)    }    connectedCallback(){      //在这里发送数据请求(Ajax)      console.log('connectedCallback')    }    //被从文档DOM中删除时调用    disconnectedCallback(){      console.log('disconnectedCallback')    }    //被移动到新的文档时调用    adoptedCallback(){      console.log('adoptedCallback')    }    //当增加、删除、修改自身的属性时被调用    attributeChangedCallback(){      console.log('attributeChangedCallback')    }  }  window.customElements.define('com-card', ComCard);  function hello() {    alert('Hello,Web Component')  }</script></body></html>

最终效果如上图所示

Web Components vs Vue Components

Vue ComponentWeb Component
data实例属性
propsattributes
watchobservedAttributes、attributeChangedCallback
computedgetters
methodsclass methods
mountedconnectedCallback
destroyeddisconnectedCallback
style scopedtemplate中的style
templatetemplate

Web Components 生命周期回调函数

connectedCallback:当 custom element首次被插入文档DOM时,被调用。

disconnectedCallback:当 custom element从文档DOM中删除时,被调用。

adoptedCallback:当 custom element被移动到新的文档时,被调用。

attributeChangedCallback: 当 custom element增加、删除、修改自身属性时,被调用。

优点 and 缺点

优点:

缺点:

七、基于web components的框架

LitElement 是一个快速、轻量级的 Web UI 框架。使用 lit-html 来渲染元素。

Polymer 是一款实用、基于事件驱动、封装性和交互性强的 Web UI 框架。

Omi 是基于 Web 组件的跨框架跨平台框架 。移动端 & 桌面 & 小程序。

以上就是关于“Web Components如何实现类Element UI中的Card卡片”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯