shu-c-view
Version:
rollup 打包vue组件库框架
409 lines (407 loc) • 13.6 kB
JavaScript
/**
* @desc 列表内容自动定时滚动 table(不建议数据量比较大,因为滚动 table 不分页)
* [Vue无缝滚动](https://chenxuan1993.gitee.io/component-document/index_prod#/component/seamless-default)
*/
import VueSeamlessScroll from 'vue-seamless-scroll';
import _isEmpty from 'lodash/isEmpty';
import _has from 'lodash/has';
import _omit from 'lodash/omit';
import _pick from 'lodash/pick';
import _assign from 'lodash/assign';
import _isNil from 'lodash/isNil';
import _isArray from 'lodash/isArray';
import _get from 'lodash/get';
import _find from 'lodash/find';
import _forEach from 'lodash/forEach';
import _keys from 'lodash/keys';
import _set from 'lodash/set';
import { devConsole, apply } from '../helper/util.js';
const BaseRollTable = {
name: 'BaseRollGrid',
inheritAttrs: false,
components: {
VueSeamlessScroll
},
props: {
// 列 el-table-column 的配置
columns: {
type: Array,
default() {
return [];
}
},
// 静态数据
options: {
type: Array
},
// 自定义样式
ctCls: {
type: String
},
// vue-seamless-scroll [配置项](https://madewith.cn/74)
classOption: {
type: Object,
default: () => ({ step: 0.5 })
},
// Table Attributes
tableAttributes: {
type: Object,
default() {
return {};
}
}
},
computed: {
tableColumn() {
// const h = this.$createElement;
const aTableColumnList = [];
// eslint-disable-next-line no-restricted-syntax
for (let i = 0, len = this.columns.length; i < len; i += 1) {
const oColumnItem = this.columns[i];
const oColumnRender = [];
if (_has(oColumnItem, 'hide') && oColumnItem.hide) {
// oColumnRender.push(this.$createElement()); // 列的隐藏
} else {
oColumnRender.push(
this.$createElement(
'el-table-column',
{
props: {
..._omit(oColumnItem, ['header', 'renderHeader']),
renderHeader: (h, { column, $index }) => {
const outColumn = _find(
this.columns,
c => c.prop === column.property
);
if (_has(outColumn, 'renderHeader')) {
/* return h('div', {}, [
outColumn.renderHeader(h, { column, $index })
]); */
return outColumn.renderHeader(h, { column, $index });
}
return column.label;
}
}
},
[]
)
);
aTableColumnList.push(oColumnRender);
}
/* const oColumnRender = [
h('el-table-column', { props: { ...oColumnItem } }, [])
]; */
}
return aTableColumnList;
},
// 内部滚动的table
innerScrollTable() {
const h = this.$createElement;
const aTableColumnList = [];
// eslint-disable-next-line no-restricted-syntax
for (let i = 0, len = this.columns.length; i < len; i += 1) {
const oColumnItem = this.columns[i];
if (_has(oColumnItem, 'hide') && oColumnItem.hide) {
// aTableColumnList.push(this.$createElement());
} else {
const oColumnRender = [
h(
'el-table-column',
{
props: {
..._omit(oColumnItem, ['sortable', 'header', 'renderHeader'])
},
scopedSlots: {
default: ({ row, column, $index }) => {
// console.log('row: ', row);
const rowKeys = _keys(row);
const oAttrVal = {
rowIndex: $index,
'data-column-label': column.label,
'data-column-property': column.property,
'data-column-value': row[column.property]
};
_forEach(rowKeys, rowKey => {
_set(oAttrVal, `data-${rowKey}`, _get(row, rowKey));
});
// 作用域插槽自定义列的内容
if (_has(oColumnItem, 'renderSlotName')) {
return h(
'div',
{
class: 'base-roll-grid__dataSetCell',
attrs: oAttrVal
},
[
this.$scopedSlots[oColumnItem.renderSlotName]({
row,
column,
index: $index
})
]
);
}
if (_has(oColumnItem, 'render')) {
return h(
'div',
{
class: 'base-roll-grid__dataSetCell',
attrs: oAttrVal
},
[
oColumnItem.render(
this.$createElement,
row,
column,
$index
)
]
);
}
const valueNode = `${row[column.property]}${_get(
oColumnItem,
'unit',
''
)}`;
if (
_isNil(this.$listeners['row-click']) &&
_isNil(this.$listeners['cell-click'])
) {
// 没有行和列点击事件
return valueNode;
}
// 行和列点击事件
return h(
'div',
{
class: 'base-roll-grid__dataSetRow',
attrs: oAttrVal
},
[valueNode]
);
}
}
},
[]
)
];
aTableColumnList.push(oColumnRender);
}
}
return h(
'el-table',
{
ref: this.innerTableRef,
class: 'inner-table_box',
props: _assign(
{
data: this.tableData,
showHeader: false,
emptyText: ''
},
_omit(this.tableAttributes, ['data', 'showHeader'])
)
// on: this.$listeners
},
[
aTableColumnList,
_has(this.$slots, 'empty')
? h('template', { slot: 'empty' }, [this.$slots.empty])
: h()
]
);
},
classOptionComputed() {
// vue-seamless-scroll 配置项
const oDefaultClassOption = {
step: 1, // 数值越大速度滚动越快
limitMoveNum: 5, // 开启无缝滚动的数据量,如果传入的options数量小于5则无法进行滚动
hoverStop: true, // 是否启用鼠标hover控制
direction: 1, // 方向(0 往下 1 往上 2向左 3向右)
openTouch: true, // 移动端开启touch滑动
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 1000, // 单步停止等待时间(默认值1000ms)
autoPlay: true, // 手动切换时候需要置为false
switchSingleStep: 134, // 手动单步切换step值(px)
switchDelay: 400 // 单步切换的动画时间(ms)
};
if (!_isEmpty(this.classOption)) {
apply(oDefaultClassOption, this.classOption);
}
if (
_has(this.classOption, 'direction') &&
this.classOption.direction > 1
) {
console.warn('滚动的方向必须是:0 往下 1 往上');
oDefaultClassOption.direction = 1;
}
return oDefaultClassOption;
}
},
watch: {
options(val) {
if (!_isNil(val)) {
this.tableData = [];
this.$nextTick(() => {
this.tableData = val;
if (!_isNil(this.$refs[this.innerTableRef])) {
this.$refs[this.innerTableRef].doLayout();
}
});
}
},
columns: {
handler() {
// 如果列发生了改变那么重新生成外部table的key,重新生成el-table-column
// default-sort 配合 列的 hide 属性生效
this.key = `roll-table-key${Math.floor(Math.random() * (100 - 1))}${1}`;
},
deep: true
}
},
data() {
this.oEvents = {
ScrollEnd: 'ScrollEnd' // 一次滚动完成的回调事件
};
this.innerTableRef = 'scroll-table-ref';
return {
tableData: this.options,
key: 'roll-table-key'
};
},
methods: {
/**
* @description 强制刷新表格ui
*/
refreshTable() {
this.$nextTick(() => {
this.$refs.rollGridRef.doLayout();
this.$refs[this.innerTableRef].doLayout();
});
}
},
render(h) {
return h(
'el-table',
{
ref: 'rollGridRef',
class: {
'base-roll-grid': true,
[this.ctCls]: !_isNil(this.ctCls)
},
props: _assign(
{ data: [], height: '100%', 'empty-text': '' },
_pick(this.tableAttributes, [
'stripe',
'border',
'size',
'fit',
'show-header',
'highlight-current-row',
'header-row-class-name',
'header-row-style',
'header-cell-class-name',
'header-cell-style',
'default-sort'
])
),
key: this.key,
on: {
// 当表格的排序条件发生变化的时候会触发该事件
'sort-change': ({ column, prop, order }) => {
if (
_has(this.$listeners, 'sort-change') &&
column.sortable === 'custom'
) {
// 外部定义了 sort-change 事件
this.$listeners['sort-change']({ column, prop, order });
} else {
this.tableData = [];
this.$nextTick(() => {
this.tableData = this.options;
this.$refs[this.innerTableRef].sort(prop, order);
});
}
}
}
},
[
this.tableColumn,
h('template', { slot: 'empty' }, [h('base-render-self')]),
h('template', { slot: 'append' }, [
h(
'div',
{
on: {
click: e => {
// 代理点击事件,`vue-seamless-scroll` 组件会使得 el-table-column 的 row-click 事件失效
let row = null;
if (_isEmpty(e.target.dataset)) {
// console.log('empty ', e.target.childNodes[0].dataset);
const { dataset: childDataset } = e.target.childNodes[0]; // render
const { dataset: parentDataset } = e.target.parentNode; // renderSlotName
if (!_isEmpty(childDataset)) {
row = childDataset;
}
if (!_isEmpty(parentDataset)) {
row = parentDataset;
}
} else {
// console.log(e.target.dataset.projectname);
row = e.target.dataset; // 没有 render 和 renderSlotName
}
const objRow = apply({}, row);
if (_has(this.$listeners, 'row-click')) {
this.$listeners['row-click'](objRow);
}
if (_has(this.$listeners, 'cell-click')) {
const cell = {
label: objRow.columnLabel,
property: objRow.columnProperty,
value: objRow.columnValue
};
this.$listeners['cell-click'](apply({}, cell));
}
e.preventDefault();
e.stopPropagation();
return false;
}
}
},
[
h(
'vue-seamless-scroll',
{
props: {
data: this.tableData,
'class-option': this.classOptionComputed
},
on: {
ScrollEnd: () => {
this.$emit('scroll-end');
}
}
},
[this.innerScrollTable]
)
]
)
])
]
);
}
};
BaseRollTable.install = function(Vue, ElComponents) {
// 用于按需加载的时候独立使用
devConsole(`按需加载独立组件:${BaseRollTable.name}`);
if (_isArray(ElComponents) && !_isEmpty(ElComponents)) {
for (let i = 0; i < ElComponents.length; i++) {
if (ElComponents[i].name !== BaseRollTable.name) {
Vue.use(ElComponents[i]);
}
}
}
Vue.component(BaseRollTable.name, BaseRollTable);
};
export { BaseRollTable };