UNPKG

shu-c-view

Version:

rollup 打包vue组件库框架

409 lines (407 loc) 13.6 kB
/** * @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 };