在vue react中如何使用Web Components组件

 更新时间:2023年05月17日 10:09:47   作者:pg_li  
这篇文章主要介绍了在vue react中如何使用Web Components组件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

在vue react中使用Web Components组件

1、web组件部分代码(git地址)

(function () {
    // 配置模板
    const getEemplate = () => {
        // 创建模板
        const template = document.createElement('template');
        // 给模板设置id 方便查找
        template.id = 'userCardTemplate';
        template.innerHTML = `
    <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 class="image">
    <div class="container">
        <p class="name"></p>
        <p class="email"></p>
        <button class="button">Follow John</button>
    </div>
    `;
        return template;
    };
    // 讲模板放到dom结构中去
    const createEemplate = () => {
        document.body.appendChild(getEemplate());
    };
    createEemplate();
    class UserCard extends HTMLElement {
        constructor() {
            super();
            this.creatShadow();
            // 此处防止vue等框架类型的组件使用时 生命周期导致的参数异常 因此延迟绑定参数
            setTimeout(() => {
                this.creatContent();
            });
        }
        /**
         * 封闭内部dom
         */
        creatShadow() {
            this.shadow = this.attachShadow({mode: 'closed'});
        }
        /**
         * 创建内部显示内容
         */
        creatContent() {
            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.shadow.appendChild(content);
        }
        /**
         * 当自定义元素第一次被连接到文档DOM时被调用
         * 相当于mounted
         */
        connectedCallback() {
            console.log('connectedCallback')
        }
        /**
         * 当自定义元素与文档DOM断开连接时被调用。
         * 与beforeDestroy类似
         */
        disconnectedCallback() {
            console.log('disconnectedCallback')
        }
        /**
         * 当自定义元素被移动到新文档时被调用。
         */
        adoptedCallback() {
            console.log('adoptedCallback')
        }
        /**
         * 暴露哪些属性可以被监听
         * @returns {string[]}
         */
        static get observedAttributes() {
            return ['image', 'name', 'email']
        }
        /**
         * 当自定义元素的一个属性被增加、移除或更改时被调用。
         */
        attributeChangedCallback() {
            console.log('attributeChangedCallback')
        }
    }
    window.customElements.define('user-card', UserCard);
})();
            /**
             * 自定义事件
            */
            this.dispatchEvent(new CustomEvent('submit', {
             detail: {
              data: {}
             }
            }));
            this.dispatchEvent(new CustomEvent('afterSubmit', {
             detail: {
              data: {}
             }
            }));

2、vue中使用部门代码

在public目录下得index.html中导入

<script src="./UserCard.js"></script>
<template>
  <div id="app">
    <user-card v-if="show" image="https://semantic-ui.com/images/avatar2/large/kristy.png"
               name="User Name"
               email="yourmail@some-email.com"
    ></user-card>
      <user-card
              image="https://semantic-ui.com/images/avatar2/large/kristy.png"
              name="test"
              email="yourmail@some-email.com"
      ></user-card>
    <button @click="onclick">
      测试
    </button>
  </div>
</template>
<script>
export default {
  data: function() {
    return {
      show: true
    }
  },
  name: 'App',
  mounted() {
  },
  methods: {
    // 测试web组件生命周期
    onclick() {
      this.show = !this.show;
    }
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

3、在react中使用

// submit事件 在点击登录时触发,传递的登录信息在,detail字段中
// afterSubmit 在登录数据下发服务端后触发 用于处理登录后的路由跳转等逻辑
<user-card url="https://www.baidu.com/"
                  user="account"
                  password="password"
                  id="form"
                  style="background-image: url(/assets/background.jpg)"
                  body-style="right: 200px;"
                  title="系统">
    </user-card>
    <script>
        const form = document.querySelector('#form');
        form.addEventListener('submit', (data)=> {
            console.log(data)
        });
        form.addEventListener('afterSubmit', (data)=> {
            console.log(data)
        });
    </script>
/**
 * 处理react tsx中直接使用web components报错问题
 */
interface UserCardModuleProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
    title: string,
    ...
}
declare global {
    namespace JSX {
        interface IntrinsicElements {
            'user-card': UserCardModuleProps
        }
    }
}

4、在html中使用

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
</head>
<body>
<user-card
        image="https://semantic-ui.com/images/avatar2/large/kristy.png"
        name="User Name"
        email="yourmail@some-email.com"
></user-card>
<user-card
        image="https://semantic-ui.com/images/avatar2/large/kristy.png"
        name="test"
        email="yourmail@some-email.com"
></user-card>
<script src="./public/UserCard.js"></script>
<script >
</script>
</body>
</html>

组件化统一标准——Web Components

Web Components是什么

一句话概括,Web Components是一个Web组件标准。现在的前端开发几乎已经离不开组件化开发了,无论是vue中的模板语法还是react中的JSX,都是把结构、样式和逻辑封装成一个组件,采用组件复用来提高开发效率。

既然组件如此重要,Web Components就是提供浏览器底层的支持,不依赖各种框架的支持和webpack的编译,让我们也能使用组件。

Web Components通过一种标准化的非侵入的方式封装一个组件,每个组件能组织好它自身的HTML、CSS、JavaScript,并且不会干扰页面上的其他代码。

Web Components的组成

Web Components由以下四个部分组成:

clipboard.png

HTML templates

支持template标签和slot标签。slot标签支持动态替换模板中的HTML内容,它用name属性来作为唯一表示。template中的内容被插入到DOM之前,不会渲染,它可以放在document中的任何位置。

HTML Imports

改造一下上面的例子,将template的内容写到一个新的main.html文件中,然后通过link引入。

Shadow DOM

Shadow DOM提供了一种健壮的封装方式来做到页面节点的隔离,避免全局样式冲突,这也是Web Component的核心优势。

clipboard.png

Shadow DOM中设置的样式没有影响外部<p>标签的样式。

Custom elements

在custom element的构造函数中,可以指定多个不同的回调函数,它们将会在元素的不同生命时期被调用:

  • connectedCallback:当 custom element首次被插入文档DOM时,被调用。
  • disconnectedCallback:当 custom element从文档DOM中删除时,被调用。
  • adoptedCallback:当 custom element被移动到新的文档时,被调用。
  • attributeChangedCallback: 当 custom element增加、删除、修改自身属性时,被调用。

clipboard.png

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解element-ui表格中勾选checkbox,高亮当前行

    详解element-ui表格中勾选checkbox,高亮当前行

    这篇文章主要介绍了详解element-ui表格中勾选checkbox,高亮当前行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 深入了解vue中一键复制功能的实现

    深入了解vue中一键复制功能的实现

    在现代的Web应用中,用户体验至关重要,而提供简单易用的复制功能是改善用户体验的一项关键功能,本文将为大家详细介绍Vue实现一键复制功能的具体方法,需要的可以参考下
    2023-11-11
  • vue实现带过渡效果的下拉菜单功能

    vue实现带过渡效果的下拉菜单功能

    这篇文章主要为大家详细介绍了vue仿写带过渡效果的下拉菜单功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • vue3 setup点击跳转页面的实现示例

    vue3 setup点击跳转页面的实现示例

    本文主要介绍了vue3 setup点击跳转页面的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-10-10
  • 解决Vue中使用keepAlive不缓存问题

    解决Vue中使用keepAlive不缓存问题

    这篇文章主要介绍了Vue中使用keepAlive不缓存问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Vue中父子组件如何实现传值

    Vue中父子组件如何实现传值

    这篇文章主要介绍了Vue中父子组件如何实现传值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • vue computed无法得到this的属性或方法的解决

    vue computed无法得到this的属性或方法的解决

    这篇文章主要介绍了vue computed无法得到this的属性或方法的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 使用vue重构资讯页面的实例代码解析

    使用vue重构资讯页面的实例代码解析

    这篇文章主要介绍了使用vue重构资讯页面的实例代码解析,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-11-11
  • 使用vue中的混入mixin优化表单验证插件问题

    使用vue中的混入mixin优化表单验证插件问题

    这篇文章主要介绍了使用vue中的混入mixin优化表单验证插件,本文是小编给大家总结的一些表单插件的问题,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • 用vue实现注册页效果 vue实现短信验证码登录

    用vue实现注册页效果 vue实现短信验证码登录

    这篇文章主要为大家详细介绍了用vue实现注册页,短信验证码登录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论