在vue react中使用Web Components组件
1、web组件部分代码(function () {// 配置模板const getEemplate = () => {// 创建模板const template = document.createElement('template');// 给模板设置id 方便查找template.id = 'userCardTemplate';template.innerHTML = `&
·
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>
更多推荐
已为社区贡献6条内容
所有评论(0)