javascript开发组件--Web Component(2)

179 阅读2分钟

使用Web Component 开发Dialog组件

这回灵感一直在,虽然这回只是做了外形,事件交互那些都没添加,不过给了我很大的动力。话不多说,搞起来。 看图看图

效果图

html


<!-- 方法1 -->
<hd-dialog title="这个是title" content="这个是内容"  width="80%" top="10%" visible="open"></hd-dialog>

<!-- 方法2 -->
<hd-dialog showClose="close" visible="open">
    <div slot="title">这个是title2</div>
    <div slot="content">这个是内容2</div>
    <div slot="footer">这个是footer2</div>
</hd-dialog>

dialog.js

// <hd-dialog></hd-dialog>
class HdDialog extends HTMLElement {
	constructor() {
		super();
		const shadowRoot = this.attachShadow({ mode: 'open' });
    this.shadowDom = shadowRoot;
    this.data()
		this._style()
		this._html()
		this.render()
	}
	// 初始化数据
	data() {
		this.state = {
			title: '', // 标题
			width: '50%', // 弹窗宽度
			visible: 'close', // 是否显示Dialog  close || open 
			top: '20vh', // Dialog距离顶部的高度
			mask: 'open', // 是否需要遮罩层
			showClose: 'open',
		}
	}
	// 样式引入
	_style() {
		// 在shadowRoot创建css 
		let dialogCss = document.createElement('style')
		let width = this.getAttribute('width')
		let top = this.getAttribute('top')
		dialogCss.textContent = `
			.hd__dialog {
				position: fixed;
				z-index: 31;
				top: ${top ? top : '20vh'};
				left: 50%;
				width: ${width ? width : '50%'};
				background-color: #fff;
				transform: translateX(-50%);
				border-radius: 2px;
				box-shadow: 0 1px 3px rgba(0,0,0, .3);
				box-sizing: border-box;	
			}
			.hd__dialog_mask {
				position: fixed;
				width: 100%;
				height: 100%;
				background-color: #000;
				opacity: .5;
				top: 0;
				left: 0;
				bottom: 0;
				right: 0;
				z-index: 30;
			}
			.hd__dialog-header {
				width: 100%;
				padding: 12px;
				border-bottom: 1px solid #ebeef5;
				box-sizing: border-box;
				position: relative;
			}
			.hd__dialog-close {
				position: absolute;
				right: 12px;
				top: 50%;
				transform: translateY(-50%);

			}
			.close-icon {
		    position: relative;
		    width: 2px;
		    height: 15px;
		    background: #909399;
		    transform: rotate(45deg);
		    display: inline-block;
		    margin-right: 10px;
		  }
		  .close-icon:after {
		    position: absolute;
		    top: 0;
		    left: 0;
		    content: "";
		    width: 2px;
		    height: 15px;
		    background: #909399;
		    transform: rotate(270deg);
		    margin-right: 10px;
		  }
		  .hd__dialog-content {
		  	width: 100%;
				padding: 12px;
				box-sizing: border-box;
				position: relative;
		  }
		  .hd__dialog-footer {
		  	width: 100%;
				padding: 12px;
				border-top: 1px solid #ebeef5;
				box-sizing: border-box;
				position: relative;
		  }
		  .footer-wrap {
		  	width: 100%;
		  	display: flex;
		  	justify-content: flex-end;
		  	gap: 12px;  	
		  }
		  .el-hide {
		  	display: none;
		  }
		`
		this.shadowRoot.appendChild(dialogCss)
	}

	// html
	_html() {
		let container = document.createElement('div')
		container.classList.add('hd__dialog')
		this.getAttrVisible()
		if(this.state.visible !== 'open') {
			container.classList.add('el-hide')
		}
		this.getAttrMask()
		if(this.state.mask === 'open' && this.state.visible === 'open') {
			// 创建content
			let mask = document.createElement('div')
			mask.classList.add('hd__dialog_mask')
			this.shadowRoot.appendChild(mask);
		}
		// 创建header
		let header = document.createElement('div')
		header.classList.add('hd__dialog-header')
		header.innerHTML = this._htmlHeader()
		container.appendChild(header)
		// 创建content
		let content = document.createElement('div')
		content.classList.add('hd__dialog-content')
		content.innerHTML = this._htmlContent()
		container.appendChild(content)
		// 创建footer
		let footer = document.createElement('div')
		footer.classList.add('hd__dialog-footer')
		footer.innerHTML = this._htmlFooter()
		container.appendChild(footer)
		console.log('container--', container)
		this.shadowRoot.appendChild(container);
	}
	render() {
		this.getAttrShowClose()
		let closeBox = this.shadowRoot.querySelector('.hd__dialog-close')
		if(this.state.showClose === 'close') {
			closeBox.classList.add('el-hide')
		}
	}
 	// header的元素内容
	_htmlHeader() {
		let title = this.getAttribute('title')
		let innerHTML = `
		<slot name="title">
			<div>${title}</div>
		</slot>
		<div class="hd__dialog-close">
			<span class="close-icon"></span>
		</div>
		`
		return innerHTML;
	}
	// content的元素内容
	_htmlContent() {
		let content = this.getAttribute('content')
		let innerHTML = `
		<slot name="content">
			<div>${content}</div>
		</slot>
		`
		return innerHTML;
	}
	// footer的元素内容
	_htmlFooter() {
		let innerHTML = `
		<slot name="footer">
			<div class="footer-wrap">
				<hd-button size="mini">取消</hd-button>
				<hd-button size="mini" type="primary">确认</hd-button>
			</div>
		</slot>
		`
		return innerHTML;
	}
	// 获取属性 hideClose 显示关闭图标
	getAttrShowClose() {
		let close = this.getAttribute('showClose')
		let atrrAll = ['close', 'open']
		if(close && atrrAll.includes(close)) {
			this.state.showClose = close
		} else {
			this.state.showClose = 'open'
		}
	}
	// 获取属性  mask 遮罩层
	getAttrMask() {
		let mask = this.getAttribute('mask')
		let atrrAll = ['close', 'open']
		if(mask && atrrAll.includes(mask)) {
			this.state.mask = mask
		} else {
			this.state.mask = 'open'
		}
	}
	// 获取属性  mask 遮罩层
	getAttrVisible() {
		let visible = this.getAttribute('visible')
		let atrrAll = ['close', 'open']
		if(visible && atrrAll.includes(visible)) {
			this.state.visible = visible
		} else {
			this.state.visible = 'close'
		}
	}
	// 当监听的值发送变化时
	attributeChangedCallback(attrName, oldVal, newVal) {
		if(attrName === 'visible') {
			this.state.visible = newVal
			this._html()
		}
	}
}
customElements.define('hd-dialog',HdDialog);


小结

好啦! 就写这么多了 要下班了。我现在很兴奋, 我正有很多的鬼点子,不过我需要时间。把它们叫出来。对的 我要更多的时间去弄他们。 提前祝大家国庆快乐。