Web Components
这个table组件是我很久以前就想搞的了 一直拖到现在 今天终于出来了 原因也是最近才找到方法 说白了就是菜吧 最近接触了一个东西 叫 web component
Web Components
Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们。
后面的就不说了 你们可以看看文档 这时候说回来 一直迷恋于封装组件的我第一眼看到就觉得有搞头 然后开始研究它 当然现在的我还是一直在爬坑 下面的组件封装过程也只是我的个人理解 整个组件并不完善 只是某个阶段
table组件 模仿element table组件模式 先看看html 部分
table.html
sql
<hd-table class="hd-table">
<hd-table-column type="index" label="日期" width="180"></hd-table-column>
<hd-table-column prop="date" label="日期" width="180"></hd-table-column>
<hd-table-column prop="name" label="姓名" width="180"></hd-table-column>
<hd-table-column prop="address" label="地址" width="180"></hd-table-column>
</hd-table>
bash
<script type="text/javascript" src="./table.js"></script>
<script type="text/javascript">
let data = [{
date: '2016-05-03',
name: '王小虎1',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-02',
name: '王小虎2',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎3',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎4',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-08',
name: '王小虎5',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-06',
name: '王小虎6',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-07',
name: '王小虎7',
address: '上海市普陀区金沙江路 1518 弄'
}]
let hdTable = document.getElementsByTagName('hd-table')[0]
// console.log(hdTable)
hdTable.setAttribute('data', JSON.stringify(data))
</script>
table.css
css
* {
margin: 0;
padding: 0;
}
.hd__table {
width: 100%;
position: relative;
box-sizing: border-box;
max-width: 100%;
font-size: 14px;
color: #606266;
/*flex: 1;*/
}
.hd__table:before{
content: "";
position: absolute;
background-color: #ebeef5;
z-index: 1;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
}
.hd__table-header-wrapper {
width: 100%;
overflow: hidden;
}
.hd__table-header {
width: 100%;
border-collapse: separate;
table-layout:fixed;
}
.hd__table-header tr {
background-color: #fff;
color: #909399;
font-weight: 500;
box-sizing: border-box;
}
.hd__table-header tr > th {
box-sizing: border-box;
padding: 12px 0;
text-align: left;
text-overflow: ellipsis;
vertical-align: middle;
/*text-align: center;*/
border-bottom: 1px solid #ebeef5;
/*border-right: 1px solid #ebeef5;*/
}
.hd__table-header tr > th > .cell {
padding: 0 10px;
width: 100%;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
word-break: break-all;
line-height: 23px;
}
.hd__table-body-wrapper {
overflow: hidden;
position: relative;
width: 100%;
}
.hd__table-body {
width: 100%;
border-collapse: separate;
table-layout:fixed;
/*display: none;*/
}
.hd__table-row {
background-color: #fff;
}
.hd__table-row td {
box-sizing: border-box;
padding: 12px 0;
text-align: left;
text-overflow: ellipsis;
vertical-align: middle;
/*text-align: center;*/
border-bottom: 1px solid #ebeef5;
/*border-right: 1px solid #ebeef5;*/
}
.hd__table-row > td > .cell {
padding: 0 10px;
width: 100%;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
word-break: break-all;
line-height: 23px;
}
.hd__table-empty {
width: 100%;
min-height: 60px;
height: 100%;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.hd__table-empty-none {
display: none;
}
开始进入正题
table.js
ini
class Component extends HTMLElement {
static get observedAttributes() {return ['data'] }
constructor() {
super();
this.init();
}
init() {
// 顶层影子DOM
let shadow = this.attachShadow({
mode: 'open'
});
this.state = {};
}
}
// <hd-table></hd-table>
class HdTable extends Component {
constructor() {
super();
this._style()
this._html()
this.data()
this.render()
}
// 初始化数据
data() {
this.state = {
data: []
}
try {
if (this.getAttribute('data')) {
this.state.data = JSON.parse(this.getAttribute('data'));
}
} catch(e) {
this.state.data = [];
}
}
// 样式引入
_style() {
// 在shadowRoot创建css
let tableCss = document.createElement('link')
tableCss.rel = 'stylesheet';
tableCss.type = 'text/css';
tableCss.href = this._link() + 'table.css';
this.shadowRoot.appendChild(tableCss)
}
// 获取路径
_link() {
let b, a, f = window['document']['getElementsByTagName']("script");
for (let c = 0; c < f.length; c++) {
b = f[c].getAttribute("src") || "";
b = b.substr(0, b.toLowerCase().indexOf("table.js"));
a = b.lastIndexOf("/");
if (a > 0) {
b = b.substring(0, a + 1)
}
if (b) {
break;
}
}
return b
}
// html
_html() {
let container = document.createElement('div')
container.classList.add('hd__table')
container.innerHTML = `
<div class="hd__table-header-wrapper"></div>
<div class="hd__table-body-wrapper">
<table class="hd__table-body" border="0" cellspacing="0" cellpadding="0">
<tr class="hd__table-row">
<slot></slot>
</tr>
</table>
<div class="hd__table-empty hd__table-empty-none">
<span>暂无数据</span>
</div>
</div>
`
this.shadowRoot.appendChild(container);
}
render() {
let header = this.shadowRoot.querySelector('.hd__table-header-wrapper');
header.innerHTML = this._htmlHeader()
let tableBody = this.shadowRoot.querySelector('.hd__table-body-wrapper');
// tableBody.innerHTML = this._htmlColumn()
let column = this._htmlColumn()
if(column) {
tableBody.innerHTML = this._htmlColumn()
}
}
// 获取有几个hd-table-column标签
getTableColumnList() {
let childrenList = this.children
let tableColumnList = []
Object.keys(childrenList).forEach(function(key){
if(childrenList[key].nodeName == 'HD-TABLE-COLUMN') {
// childrenList[key]
let prop = childrenList[key].getAttribute('prop')
let label = childrenList[key].getAttribute('label')
let width = childrenList[key].getAttribute('width')
let type = childrenList[key].getAttribute('type')
tableColumnList.push({ prop, label, width, type })
}
})
this.state.tableColumnList = tableColumnList
}
_htmlHeader() {
this.getTableColumnList()
let str = this.state.tableColumnList.map((item, i) => {
if(item.type == 'index') {
return `<th><div class="cell"></div></th>`
} else if(item.type == "selection") {
return `<th><div class="cell"></div></th>`
} else {
return `<th><div class="cell">${item.label}</div></th>`
}
}).join('');
return `<table class="hd__table-header" border="0" cellspacing="0" cellpadding="0"><tr>${str}</tr></table>`
}
_htmlColumn() {
let empty = this.shadowRoot.querySelector('.hd__table-empty')
if(this.state.data.length == 0) {
empty.classList.remove('hd__table-empty-none')
return
} else {
empty.classList.add('hd__table-empty-none')
let row = this.shadowRoot.querySelector('.hd__table-row')
row.innerHTML = this._htmlRow()
let rows = this.state.data.map((item,index)=>{
let rowsChild = row.querySelectorAll('td .cell')
rowsChild.forEach(items => {
let type = items.getAttribute('type')
let prop = items.getAttribute('prop')
if(type == 'index') {
items.innerHTML = index
} else if(type == 'selection') {
items.innerHTML = ''
} else {
items.innerHTML = item[prop]
}
})
return `<tr class="hd__table-row">${row.innerHTML}</tr>`
}).join('')
return `<table class="hd__table-body" border="0" cellspacing="0" cellpadding="0">${rows}</table>`
}
}
_htmlRow() {
this.getTableColumnList()
let str = this.state.tableColumnList.map(item =>{
if(item.type == 'index' || item.type == 'selection') {
return `
<td rowspan="1" colspan="1" type="${item.type} prop="${item.prop} width="${item.width}">
<div class="cell" type="${item.type}"></div>
</td>`
} else {
return `
<td rowspan="1" colspan="1" type="${item.type} prop="${item.prop} width="${item.width}">
<div class="cell" prop="${item.prop}"></div>
</td>`
}
}).join('');
return str
}
// 当监听的值发送变化时
attributeChangedCallback(attrName, oldVal, newVal) {
if(attrName == 'data') {
this.state.data = JSON.parse(newVal)
let tableBody = this.shadowRoot.querySelector('.hd__table-body-wrapper');
tableBody.innerHTML = this._htmlColumn()
}
}
}
customElements.define('hd-table',HdTable);
这么看下来 就有点像react 不过这个是原生哦 很多东西我没办法写一个很好的注释去解释 因为我的基础很差 写了也只能说是我自己的理解 容易误导人 索性也就不写了 还是先来解释解释Web Components 还是再起一篇文章解释吧
最后最后给自己来句鸡汤吧 毕竟搞出来也花了不少的功夫 爬了不少的坑
别害怕,委屈只是暂时的,路会越走越亮;你年纪轻轻,心地善良,你怕什么。总有一天,你会站在最亮的地方,活成自己曾经最渴望的样子。