在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

总结

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

相关文章

  • 详解Vue项目在其他电脑npm run dev运行报错的解决方法

    详解Vue项目在其他电脑npm run dev运行报错的解决方法

    这篇文章主要介绍了详解Vue项目在其他电脑npm run dev运行报错的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • ubuntu中利用nginx部署vue项目的完整步骤

    ubuntu中利用nginx部署vue项目的完整步骤

    Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行,下面这篇文章主要给大家介绍了关于ubuntu中利用nginx部署vue项目的相关资料,需要的朋友可以参考下
    2022-02-02
  • vuex实现的简单购物车功能示例

    vuex实现的简单购物车功能示例

    这篇文章主要介绍了vuex实现的简单购物车功能,结合实例形式分析了vuex购物车组件相关商品列表、购物车创建、添加、删除、清空等相关操作技巧,需要的朋友可以参考下
    2019-02-02
  • vue.js+element 默认提示中英文操作

    vue.js+element 默认提示中英文操作

    这篇文章主要介绍了vue.js+element 默认提示中英文实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • vue elementUI select下拉框如何设置默认值

    vue elementUI select下拉框如何设置默认值

    这篇文章主要介绍了vue elementUI select下拉框如何设置默认值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • Vue.js tab实现选项卡切换

    Vue.js tab实现选项卡切换

    这篇文章主要为大家详细介绍了Vue.js组件tab实现选项卡切换效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 详解vue 实例方法和数据

    详解vue 实例方法和数据

    这篇文章主要介绍了vue 实例方法和数据的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-10-10
  • vue axios请求拦截实例代码

    vue axios请求拦截实例代码

    axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端.这篇文章主要介绍了vue/axios请求拦截的相关知识,需要的朋友可以参考下
    2018-03-03
  • Vue使用electron转换项目成桌面应用方法介绍

    Vue使用electron转换项目成桌面应用方法介绍

    Electron也可以快速地将你的网站打包成一个原生应用发布,下面这篇文章主要给大家介绍了关于Vue和React中快速使用Electron的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • Vue3 appear 失效的问题及如何使用 appear

    Vue3 appear 失效的问题及如何使用 appear

    appear 是一个在元素默认被显示的情况下 调用进入动画效果,使得元素在这种初次渲染情况下 执行进入动画的属性,最近在学习vue3的动画时遇到appear无法生效的问题,本文给大家详细讲解,感兴趣的朋友一起看看吧
    2023-10-10

最新评论