在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>

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值