<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
</head>
<body>
<div id="app">
<el-table :data="tableData">
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column label="地址">
<template slot-scope="scope">{{scope.row.address}}</template>
</el-table-column>
</el-table>
</div>
</body>
<script>
class TableStore {
constructor(){
this.states = {
data: null,
columns: []
}
}
commit(name, ...args){
this.mutations[name].apply(this, [this.states].concat(args))
}
}
TableStore.prototype.mutations = {
setData(states, data) {
states.data = data
},
insertColumn(states, column) {
states.columns.push(column)
}
}
Vue.component('el-table',{
template: `<div class="el-table">
<!-- 隐藏列: slot里容纳table-column -->
<div class="hidden-columns">
<slot></slot>
</div>
<!-- 表头 -->
<div class="el-table__header-wrapper">
<table-header :store="store"></table-header>
</div>
<!-- 表体 -->
<div class="el-table__body-wrapper">
<table-body :store="store"></table-body>
</div>
</div>`,
props: ['data'],
data(){
return {
store: new TableStore()
}
},
watch: {
data: {
immediate: true,
handler(value) {
this.store.commit('setData', value)
}
}
}
})
Vue.component('table-header',{
props: ['store'],
computed: {
columns() {
return this.store.states.columns;
}
},
render(createElement) {
return createElement('table',{class: {'el-table__header': true}}, [
createElement('thead',
this.columns.map(column=>{
return createElement('th',[createElement('div',column.label)])
})
)
])
}
})
Vue.component('table-body',{
props: ['store'],
computed: {
data() {
return this.store.states.data;
},
columns() {
return this.store.states.columns;
}
},
render(createElement) {
return createElement('table',{class: {'el-el-table__body': true}},
this.data.map((row)=>{
return createElement('tr', this.columns.map(column=>{
return createElement('td',[column.renderCell.call(null,createElement,{row})])
}))
})
)
},
})
Vue.component('el-table-column',{
template: `<div class="ttt"></div>`,
props: ['label', 'prop'],
computed: {
owner() {
return this.$parent;
}
},
created() {
let column = {
label: this.label,
property: this.prop,
renderCell: null
};
let renderCell = column.renderCell;
let _self = this;
console.log(_self);
column.renderCell = function (createElement, data) {
if (_self.$scopedSlots.default) {
renderCell = () => _self.$scopedSlots.default(data);
}else{
renderCell = function () {
let { row } = data
let property = column.property;
return row[property]
}
}
return createElement('div', {
'class': {
cell: true
}
},renderCell())
}
this.columnConfig = column
},
mounted(){
this.owner.store.commit('insertColumn', this.columnConfig)
}
})
var vm = new Vue({
el: '#app',
data: {
tableData: [{
name: '张三',
address: '成都市青羊区清源路1号'
}, {
name: '李四',
address: '成都市青羊区清源路2号'
}]
}
})
</script>