├── CHANGELOG.md
├── .gitignore
├── 20190429-161829.png
├── .npmignore
├── src
├── index.js
├── table-column.vue
├── table-cell.js
├── table-row.vue
├── table-column-header.vue
├── table-header.vue
├── table-content.vue
└── table.vue
├── example
├── index.js
├── index.html
└── example.vue
├── .eslintrc
├── webpack.example.config.js
├── webpack.config.js
├── package.json
├── index.html
├── README.CN.md
├── README.md
└── dist
└── index.js
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ### Features
4 |
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | coverage
4 | .idea
5 | .jshintrc
6 | *.log
--------------------------------------------------------------------------------
/20190429-161829.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cherislive/vue-snb-table/HEAD/20190429-161829.png
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | coverage
4 | .idea
5 | .jshintrc
6 | webpack.config.js
7 | webpack.base.js
8 | webpack.example.config.js
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import SnbTable from './table.vue';
2 | import SnbTableColumn from './table-column.vue';
3 | import SnbTableHeader from './table-header.vue';
4 | export {
5 | SnbTable,
6 | SnbTableColumn,
7 | SnbTableHeader
8 | };
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import hljs from 'highlight.js';
3 | import Example from './example.vue';
4 | Vue.directive('highlight',function (el) {
5 | let blocks = el.querySelectorAll('pre code');
6 | blocks.forEach((block)=>{
7 | hljs.highlightBlock(block);
8 | });
9 | });
10 | new Vue({
11 | el: '#app',
12 | render: h => h(Example)
13 | });
14 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | parserOptions:
2 | sourceType: module
3 |
4 | env:
5 | es6: true
6 | browser: true
7 |
8 | extends:
9 | - 'eslint:recommended'
10 | - 'plugin:vue/essential'
11 |
12 | rules:
13 | quotes: [ 1, single ]
14 | linebreak-style: [ 1, unix ]
15 | semi: [ 1, always ]
16 | no-undef: [ 1 ]
17 | no-console: [ 0 ]
18 | no-unused-vars: [ 1 ]
19 | space-infix-ops: [ 1 ]
20 | no-multi-spaces: [ 1 ]
21 | no-fallthrough: [ 0 ]
22 |
--------------------------------------------------------------------------------
/webpack.example.config.js:
--------------------------------------------------------------------------------
1 | const {resolve} = require('path');
2 | const options = require('./webpack.config');
3 |
4 | options.mode = 'development';
5 | options.entry = './example/';
6 |
7 | options.output.filename = 'example.js';
8 | options.output.libraryTarget = 'var';
9 | options.output.publicPath = '/dist/';
10 |
11 | options.devServer = {
12 | contentBase: [
13 | resolve(__dirname, "example"),
14 | ],
15 | publicPath: '/dist/'
16 | };
17 |
18 | module.exports = options;
19 |
20 |
--------------------------------------------------------------------------------
/src/table-column.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
--------------------------------------------------------------------------------
/src/table-cell.js:
--------------------------------------------------------------------------------
1 | export default {
2 | functional: true,
3 | props: ['column', 'row', 'colspan'],
4 | render(createElement, { props }) {
5 | const column = props.column;
6 | const data = {};
7 | data.class = 'cell';
8 | if (column.$scopedSlots.default) {
9 | return createElement('div', data, column.$scopedSlots.default(props.row));
10 | }
11 | data.domProps = {};
12 | data.domProps.innerHTML = props.column.formatter(props.row[column.prop], props.row.data);
13 | return createElement('div', data);
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('./node_modules/extract-text-webpack-plugin/dist/cjs')
3 |
4 | module.exports = {
5 | mode: 'production',
6 | entry: {
7 | 'index': './src/index.js',
8 | 'example': './example/index.js',
9 | },
10 | output: {
11 | path: path.resolve(__dirname, 'dist'),
12 | library: 'VueSnbTable',
13 | libraryTarget: 'umd',
14 | filename: '[name].js',
15 | },
16 | module: {
17 | rules: [
18 | {
19 | enforce: 'pre',
20 | test: /\.(js|vue)$/,
21 | loader: 'eslint-loader',
22 | exclude: /node_modules/
23 | },
24 | {
25 | test: /\.vue$/,
26 | loader: 'vue-loader',
27 | // options: {
28 | // extractCSS: false
29 | // }
30 | },
31 | { test: /\.js$/,
32 | loader: 'babel-loader'
33 | }
34 | ]
35 | },
36 | plugins: [
37 | new ExtractTextPlugin('[name].css'),
38 | ]
39 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-snb-table",
3 | "version": "2.6.6",
4 | "description": "Display multiple data with similar format. You can sort your data in a table.",
5 | "main": "dist/index.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server --config ./webpack.example.config.js --inline --hot",
8 | "remote-dev": "npm run dev --host",
9 | "build": "rm -rf dist && webpack -p",
10 | "release": "npm publish",
11 | "prepare": "npm run build"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/cherislive/vue-snb-table.git"
16 | },
17 | "babel": {
18 | "presets": [
19 | "env"
20 | ]
21 | },
22 | "files": [
23 | "dist",
24 | "src"
25 | ],
26 | "keywords": [
27 | "table",
28 | "ui-table",
29 | "vue"
30 | ],
31 | "author": "i@cheris.cn",
32 | "license": "MIT",
33 | "devDependencies": {
34 | "babel-core": "^6.26.0",
35 | "babel-loader": "^7.1.4",
36 | "babel-preset-env": "^1.6.1",
37 | "css-loader": "^0.28.11",
38 | "eslint": "^4.19.1",
39 | "eslint-loader": "^2.0.0",
40 | "eslint-plugin-vue": "^4.4.0",
41 | "extract-text-webpack-plugin": "4.0.0-beta.0",
42 | "style-loader": "^0.20.3",
43 | "stylus": "^0.54.5",
44 | "stylus-loader": "^3.0.2",
45 | "vue": "2.5.16",
46 | "vue-loader": "^14.2.2",
47 | "vue-template-compiler": "2.5.16",
48 | "webpack": "^4.29.6",
49 | "webpack-cli": "^3.1.1",
50 | "webpack-dev-server": "^3.1.3"
51 | },
52 | "dependencies": {
53 | "highlight.js": "^9.15.6",
54 | "lodash": "^4.17.11"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/table-row.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | |
15 |
20 | |
21 |
22 |
23 |
24 |
85 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | vue-snb-table examples
13 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | vue-snb-table examples
13 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/table-column-header.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 | {{column.label}}
10 | |
11 |
12 |
13 |
61 |
--------------------------------------------------------------------------------
/src/table-header.vue:
--------------------------------------------------------------------------------
1 |
2 |
29 |
30 |
31 |
136 |
181 |
--------------------------------------------------------------------------------
/README.CN.md:
--------------------------------------------------------------------------------
1 | [English](./README.md) | 简体中文
2 |
3 | # vue-snb-table Table 表格
4 |
5 | Table 表格. 用于展示多条结构类似的数据,可对数据进行排序操作。
6 |
7 | [](https://github.com/cherislive/vue-snb-table/stargazers)
8 | [](https://travis-ci.org/cherislive/vue-snb-table)
9 | [](https://github.com/cherislive/vue-snb-table/issues)
10 | [](https://github.com/cherislive/vue-snb-table/network)
11 | [](https://github.com/cherislive/vue-snb-table)
12 | [](https://github.com/cherislive/vue-snb-table)
13 | [](https://nodei.co/npm/vue-snb-table/)
14 | [](https://nodei.co/npm/vue-snb-table/)
15 |
16 |
17 |
18 | ## 预览
19 |
20 | 
21 |
22 | 页面预览: [https://cherislive.github.io/projrct/vue-snb-table/](https://cherislive.github.io/projrct/vue-snb-table/)
23 |
24 | ## 安装
25 |
26 | ```bash
27 | $ npm install vue-snb-table
28 | ```
29 |
30 | ## Import
31 |
32 | ### Import using module
33 |
34 | Import components to your project:
35 |
36 | ``` js
37 | // in ES6 modules
38 | import { SnbTable, SnbTableColumn, SnbTableHeader } from 'vue-snb-table';
39 |
40 | // in CommonJS
41 | const { SnbTable, SnbTableColumn, SnbTableHeader } = require('vue-snb-table');
42 |
43 | // in Global variable
44 | const { SnbTable, SnbTableColumn, SnbTableHeader } = VueSnbTable;
45 | ```
46 |
47 | And register components:
48 |
49 | ``` js
50 | Vue.component('snb-table', SnbTable);
51 | Vue.component('snb-table-column', SnbTableColumn);
52 | Vue.component('snb-table-header', SnbTableHeader);
53 | ```
54 |
55 | ### Import using script tag
56 |
57 | ``` html
58 |
59 | ```
60 |
61 | ``` js
62 | const SnbTable = VueSnbTable.SnbTable;
63 | const SnbTableColumn = VueSnbTable.SnbTableColumn;
64 | const SnbTableHeader = VueSnbTable.SnbTableHeader;
65 |
66 | new Vue({
67 | el: 'body',
68 | components: {
69 | 'snb-table': SnbTable,
70 | 'snb-table-column': SnbTableColumn,
71 | 'snb-table-header': SnbTableHeader
72 | }
73 | });
74 | ```
75 |
76 | ## Usage
77 |
78 | Work on a Vue instance:
79 |
80 | ```HTML
81 |
85 |
86 |
87 |
88 |
89 | {{scope.data3}}
90 |
91 |
92 | ```
93 | ## Table
94 |
95 | ### Attributes
96 |
97 | | Option | Type | Description | Accepted Values | Default |
98 | | ----- | ----- | ----- | ----- | ----- |
99 | | data | Array | 显示的数据。 | - | - |
100 | | showHeader | Boolean | 是否显示表头。 | - | true |
101 | | headerFixed | Object | 固定表头。 | `state`: true/false | null |
102 | | defaultSort | Object | 默认的排序列的 `prop` 和顺序。它的`prop`属性指定默认的排序的列,`order`指定默认排序的顺序 | `order`: asc, desc | 如果只指定了`prop`, 没有指定`order`, 则默认顺序是**ascending** |
103 | | sortState | Object | 可以通过该属性设置排序列的 `prop` 和顺序。它的`prop`属性指定排序的列,`order`指定默认排序的顺序 | `order`: asc, desc | - |
104 | | headerColsWidth | Array | 表头各个列宽。 | - | - |
105 |
106 | ### Events
107 |
108 | | Event Name | Description | params |
109 | | ----- | ----- | ----- |
110 | | columnsReady | 当表格的列的数据状态加载完成的时候会触发该事件,该事件用于自定义表头的情况。 | columns |
111 | | sortChange | 当表格的排序条件发生变化的时候会触发该事件。 | {sort: {prop, order}, column} |
112 | | colsWidth | 当表格的数据发生变化的时候会触发该事件,返回各个列宽。 | widths |
113 | | distanXChange | 当拖动表格横向滚动的时候会触发该事件。 | width |
114 | | rowClick | 当某一行被点击时会触发该事件。| row |
115 |
116 | ## Table-column
117 |
118 | ### Attributes
119 |
120 | | Option | Type | Description | Accepted Values | Default |
121 | | ----- | ----- | ----- | ----- | ----- |
122 | | prop | String | 对应列内容的字段名,也可以使用 property 属性。 | - | - |
123 | | label | String | 显示的标题。 | - | - |
124 | | align | String | 对齐方式。 | left/center/right | left |
125 | | width | String | 对应列的宽度。 | - | - |
126 | | fixed | String | 列是否固定在左侧。 | true, false | false |
127 | | sortable | Boolean | 对应列是否可以排序。 | true, false | false |
128 | | formatter | Function(row, column, cellValue, index) | 用来格式化内容。 | - | - |
129 |
130 | ## Table-header
131 |
132 | ### Attributes
133 |
134 | | Option | Type | Description | Accepted Values | Default |
135 | | ----- | ----- | ----- | ----- | ----- |
136 | | columns | Array | 各个列属性。 | - | - |
137 | | colsWidth | Array | 各个列宽。 | - | - |
138 | | distanX | Number | 表格横向滚动的距离。 | left/center/right | left |
139 | | defaultSort | Object | 默认的排序列的 `prop` 和顺序。它的`prop`属性指定默认的排序的列,`order`指定默认排序的顺序 | `order`: asc, desc | 如果只指定了`prop`, 没有指定`order`, 则默认顺序是ascending |
140 | | sortState | Object | 可以通过该属性设置排序列的 `prop` 和顺序。它的`prop`属性指定排序的列,`order`指定默认排序的顺序 | `order`: asc, desc | - |
141 |
142 | ### Events
143 |
144 | | Event Name | Description | params |
145 | | ----- | ----- | ----- |
146 | | sortChange | 当表格的排序条件发生变化的时候会触发该事件。 | {sort: {prop, order}, column} |
147 | | headerColsWidth | 表头各个列宽。当表格的渲染完成的时候会触发该事件。 | widths |
148 |
149 | ## Development
150 |
151 | Watching with hot-reload:
152 |
153 | ```bash
154 | $ npm run dev
155 | ```
156 |
157 | Develop on real remote device:
158 |
159 | ```bash
160 | $ npm run remote-dev {{ YOUR IP ADDRESS }}
161 | ```
162 |
163 | ## License
164 |
165 | MIT
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](./README.CN.md)
2 |
3 | # vue-snb-table
4 |
5 | vue-snb-table is a table componen for Vue.js.
6 | Display multiple data with similar format. You can sort your data in a table.
7 |
8 | [](https://github.com/cherislive/vue-snb-table/stargazers)
9 | [](https://travis-ci.org/cherislive/vue-snb-table)
10 | [](https://github.com/cherislive/vue-snb-table/issues)
11 | [](https://github.com/cherislive/vue-snb-table/network)
12 | [](https://github.com/cherislive/vue-snb-table)
13 | [](https://github.com/cherislive/vue-snb-table)
14 | [](https://nodei.co/npm/vue-snb-table/)
15 | [](https://nodei.co/npm/vue-snb-table/)
16 |
17 |
18 |
19 | ## Demo
20 |
21 | 
22 |
23 | You can see a demo here: [https://cherislive.github.io/projrct/vue-snb-table/](https://cherislive.github.io/projrct/vue-snb-table/)
24 |
25 |
26 | ## Install
27 |
28 | ```bash
29 | $ npm install vue-snb-table
30 | ```
31 |
32 | ## Import
33 |
34 | ### Import using module
35 |
36 | Import components to your project:
37 |
38 | ``` js
39 | // in ES6 modules
40 | import { SnbTable, SnbTableColumn, SnbTableHeader } from 'vue-snb-table';
41 |
42 | // in CommonJS
43 | const { SnbTable, SnbTableColumn, SnbTableHeader } = require('vue-snb-table');
44 |
45 | // in Global variable
46 | const { SnbTable, SnbTableColumn, SnbTableHeader } = VueSnbTable;
47 | ```
48 |
49 | And register components:
50 |
51 | ``` js
52 | Vue.component('snb-table', SnbTable);
53 | Vue.component('snb-table-column', SnbTableColumn);
54 | Vue.component('snb-table-header', SnbTableHeader);
55 | ```
56 |
57 | ### Import using script tag
58 |
59 | ``` html
60 |
61 | ```
62 |
63 | ``` js
64 | const SnbTable = VueSnbTable.SnbTable;
65 | const SnbTableColumn = VueSnbTable.SnbTableColumn;
66 | const SnbTableHeader = VueSnbTable.SnbTableHeader;
67 |
68 | new Vue({
69 | el: 'body',
70 | components: {
71 | 'snb-table': SnbTable,
72 | 'snb-table-column': SnbTableColumn,
73 | 'snb-table-header': SnbTableHeader
74 | }
75 | });
76 | ```
77 |
78 | ## Usage
79 |
80 | Work on a Vue instance:
81 |
82 | ```HTML
83 |
87 |
88 |
89 |
90 |
91 | {{scope.data3}}
92 |
93 |
94 | ```
95 | ## Table
96 |
97 | ### Attributes
98 |
99 | | Option | Type | Description | Accepted Values | Default |
100 | | ----- | ----- | ----- | ----- | ----- |
101 | | data | Array | Table data | - | - |
102 | | showHeader | Boolean | whether Table header is visible | - | true |
103 | | headerFixed | Object | whether Table header is fixed | `state`: true/false | null |
104 | | defaultSort | Object | set the default sort column and order. property `prop` is used to set default sort column, property `order` is used to set default sort order | `order`: asc, desc | if `prop` is set, and `order` is not set, then order is default to **ascending** |
105 | | sortState | Object | set the handle sort column and order. property `prop` is used to set default sort column, property `order` is used to set default sort order | `order`: asc, desc | - |
106 | | headerColsWidth | Array | columns width | - | - |
107 |
108 | ### Events
109 |
110 | | Event Name | Description | params |
111 | | ----- | ----- | ----- |
112 | | columnsReady | triggers when table element is ready | columns |
113 | | sortChange | triggers when sort state or sort order changes | {sort: {prop, order}, column} |
114 | | colsWidth | triggers when table data changes | widths |
115 | | distanXChange | triggers when drag table rest assured is horizontal | width |
116 | | rowClick | triggers when clicking a row | row |
117 |
118 | ## Table-column
119 |
120 | ### Attributes
121 |
122 | | Option | Type | Description | Accepted Values | Default |
123 | | ----- | ----- | ----- | ----- | ----- |
124 | | prop | String | field name. You can also use its alias: property | - | - |
125 | | label | String | column label | - | - |
126 | | align | String | alignment | left/center/right | left |
127 | | width | String | column width | - | - |
128 | | fixed | String | whether column is fixed. Will be fixed at left if true | true, false | false |
129 | | sortable | Boolean | whether column can be sorted. Remote sorting can be done by setting this attribute to 'custom' and listening to the sort-change event of Table | true, false | false |
130 | | formatter | Function(row, column, cellValue, index) | function that formats cell content | - | - |
131 |
132 | ## Table-header
133 |
134 | ### Attributes
135 |
136 | | Option | Type | Description | Accepted Values | Default |
137 | | ----- | ----- | ----- | ----- | ----- |
138 | | columns | Array | columns | - | - |
139 | | colsWidth | Array | columns width | - | - |
140 | | distanX | Number | table rest assured is horizontal | left/center/right | left |
141 | | defaultSort | Object | set the default sort column and order. property `prop` is used to set default sort column, property `order` is used to set default sort order | `order`: asc, desc | if `prop` is set, and `order` is not set, then order is default to **ascending** |
142 | | sortState | Object | set the handle sort column and order. property `prop` is used to set default sort column, property `order` is used to set default sort order | `order`: asc, desc | - |
143 |
144 | ### Events
145 |
146 | | Event Name | Description | params |
147 | | ----- | ----- | ----- |
148 | | sortChange | triggers when sort state or sort order changes | {sort: {prop, order}, column} |
149 | | headerColsWidth | triggers when table columns changes | widths |
150 |
151 | ## Development
152 |
153 | Watching with hot-reload:
154 |
155 | ```bash
156 | $ npm run dev
157 | ```
158 |
159 | Develop on real remote device:
160 |
161 | ```bash
162 | $ npm run remote-dev {{ YOUR IP ADDRESS }}
163 | ```
164 |
165 | ## License
166 |
167 | MIT
168 |
--------------------------------------------------------------------------------
/src/table-content.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
18 |
19 |
20 |
21 |
32 |
33 |
34 |
35 |
43 |
44 |
45 |
46 |
47 |
277 |
282 |
283 |
--------------------------------------------------------------------------------
/src/table.vue:
--------------------------------------------------------------------------------
1 |
2 |
55 |
56 |
57 |
246 |
293 |
--------------------------------------------------------------------------------
/example/example.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
14 |
15 |
16 |
Table 表格
17 |
用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。
18 |
19 |
20 |
21 |
基础表格
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | 默认配置
30 |
<SnbTable :data="tableData">
31 | <SnbTableColumn prop="name" label="姓名" />
32 | <SnbTableColumn prop="gender" label="性别" />
33 | <SnbTableColumn prop="email" label="邮箱" />
34 | </SnbTable>
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
固定列
43 |
横向内容过多时,可选择固定列。
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | 固定列需要使用fixed属性,它接受 Boolean 值,固定的列默认固定在左侧。
54 |
<SnbTable :data="tableData">
55 | <SnbTableColumn prop="name" label="姓名" />
56 | <SnbTableColumn prop="gender" label="性别" fixed />
57 | <SnbTableColumn prop="address" label="地址" />
58 | </SnbTable>
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
固定表头
67 |
纵向内容过多时,可选择固定表头。(本组件建议采用表头分离方式)
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 由于在移动端,通常采用lodemore滚动加载,而不是传统的分页这里的固定表头使用场景局限性比较强。这里不做演示。
76 |
<SnbTable :data="tableData" :headerFixed="{
77 | state: true,
78 | top: 200
79 | }">
80 | <SnbTableColumn prop="name" label="姓名" />
81 | <SnbTableColumn prop="gender" label="性别" fixed />
82 | </SnbTable>
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
排序
92 |
对表格进行排序,可快速查找或对比数据。
93 |
94 |
95 |
101 |
102 |
105 |
106 |
107 |
108 | 由于在移动端,通常采用lodemore滚动加载,排序建议在组件外处理。
109 |
110 | <template>
111 | <SnbTable
112 | :data="tableData"
113 | :sortState="sortState"
114 | :defaultSort="defaultSort"
115 | @sortChange="sortChange"
116 | >
117 | <SnbTableColumn prop="name" label="姓名" />
118 | <SnbTableColumn prop="gender" label="性别" fixed />
119 | </SnbTable>
120 | </template>
121 |
122 | <script>
123 | import _ from 'lodash';
124 | // some code
125 | data() {
126 | return {
127 | tableData: [],
128 | sortState: {}, // 存储手动排序的结果
129 | defaultSort: { // 列表默认排序
130 | prop: '',
131 | order: ''
132 | }
133 | };
134 | },
135 | methods: {
136 | // 数据排序
137 | sortChange (sort) {
138 | const order = sort.order === 'asc' ? 'desc' : 'asc';
139 | this.sortState = {
140 | prop: sort.prop,
141 | order: order
142 | };
143 | this.tableData = _.orderBy(this.tableData, this.sortState.prop, this.sortState.order);
144 | },
145 | }
146 | <script>
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
表头分离
157 |
纵向内容过多时,可采用表头分离方式。
158 |
159 |
160 | 表头
161 |
170 | 表内容 (通常隐藏表头)
171 |
182 |
183 |
186 |
187 |
188 |
189 |
190 |
191 | 这里的参数较多,因为表头、表body分离后,我们不仅要保证排序功能的正常使用,而且列宽度要相互撑开。例如性别,他的宽度就是由header部分撑开的。
192 |
193 | <template>
194 | <SnbTableHeader
195 | :columns="columns"
196 | :colsWidth="colsWidth"
197 | :distanX="tableHeaderDistanX"
198 | :defaultSort="defaultSort"
199 | :sortState="sortState"
200 | @sortChange="sortChange"
201 | @headerColsWidth="setHeaderColsWidth"
202 | >
203 | <SnbTable
204 | :data="tableData"
205 | :showHeader="false"
206 | :sortState="sortState"
207 | :defaultSort="defaultSort"
208 | :headerColsWidth="headerColsWidth"
209 | @columnsReady="setColumns"
210 | @colsWidth="setColsWidth"
211 | @sortChange="sortChange"
212 | @distanXChange="distanXChange"
213 | >
214 | <SnbTableColumn prop="name" label="姓名" />
215 | <SnbTableColumn prop="gender" label="性别" fixed />
216 | </SnbTable>
217 | </template>
218 |
219 | <script>
220 | import _ from 'lodash';
221 | // some code
222 | data() {
223 | return {
224 | tableData: [],
225 | columns: [], // 表头
226 | colsWidth: [], // body列宽度
227 | headerColsWidth: [], // 表头列宽度
228 | tableHeaderDistanX: 0, // 表头横向滚动宽度
229 | sortState: {}, // 存储手动排序的结果
230 | defaultSort: { // 列表默认排序
231 | prop: '',
232 | order: ''
233 | }
234 | };
235 | },
236 | methods: {
237 | // 设置表头
238 | setColumns (columns) {
239 | this.columns = columns;
240 | },
241 | // 设置列宽
242 | setColsWidth (width = []) {
243 | this.colsWidth = width;
244 | },
245 | // 设置表头列宽
246 | setHeaderColsWidth (width = []) {
247 | this.headerColsWidth = width;
248 | },
249 | // 设置表头横向滚动
250 | distanXChange (width = 0) {
251 | this.tableHeaderDistanX = width;
252 | },
253 | // 数据排序
254 | sortChange (sort) {
255 | const order = sort.order === 'asc' ? 'desc' : 'asc';
256 | this.sortState = {
257 | prop: sort.prop,
258 | order: order
259 | };
260 | this.tableData = _.orderBy(this.tableData, this.sortState.prop, this.sortState.order);
261 | },
262 | }
263 | <script>
264 |
265 |
266 |
267 |
268 |
269 |
270 |
281 |
282 |
283 |
284 |
371 |
372 |
401 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueSnbTable=e():t.VueSnbTable=e()}(window,function(){return function(t){var e={};function n(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return t[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(i,o,function(e){return t[e]}.bind(null,o));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=19)}([function(t,e,n){"use strict";function i(t,e,n,i,o,r,a,s){var l=typeof(t=t||{}).default;"object"!==l&&"function"!==l||(t=t.default);var d,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),i&&(u.functional=!0),r&&(u._scopeId=r),a?(d=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},u._ssrRegister=d):o&&(d=s?function(){o.call(this,this.$root.$options.shadowRoot)}:o),d)if(u.functional){u._injectStyles=d;var c=u.render;u.render=function(t,e){return d.call(e),c(t,e)}}else{var f=u.beforeCreate;u.beforeCreate=f?[].concat(f,d):[d]}return{exports:t,options:u}}n.d(e,"a",function(){return i})},function(t,e,n){"use strict";t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=function(t,e){var n=t[1]||"",i=t[3];if(!i)return n;if(e&&"function"==typeof btoa){var o=(a=i,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */"),r=i.sources.map(function(t){return"/*# sourceURL="+i.sourceRoot+t+" */"});return[n].concat(r).concat([o]).join("\n")}var a;return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var i={},o=0;on.parts.length&&(i.parts.length=n.parts.length)}else{var r=[];for(o=0;o0&&void 0!==arguments[0]?arguments[0]:[],e=[],n=null;t&&t.length&&(t.map(function(t){t.fixed&&!n?n=t||{}:e.push(t)}),n&&e.unshift(n)),this.panes=e,this.$emit("columnsReady",e),this.hasFixedCell=!!n},mapDataToRows:function(){var t=this.data,e=0;this.rows=t.map(function(t){return t.__vue_item_id=e++,t})},handleHeadSortClick:function(t){this.sort.prop!==t.prop?(this.sort.prop=t.prop,this.sort.order="asc"):this.sort.order=this.sort.order||"asc",this.$emit("sortChange",this.sort,t)},setColsWidth:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.colsWidth=t,this.emitColsWidth()},emitColsWidth:function(){var t=this.colsWidth;if(t&&t.length){var e=this.headerColsWidth;if(e&&e.length){var n=[];t.map(function(i,o){n[o]=Math.max(e[o]||0,t[o]||0)}),this.colsWidth=n,this.$emit("colsWidth",n),this.translateChange(this.distanX)}else this.$emit("colsWidth",t)}},translateChange:function(t){this.distanX=t,this.$emit("distanXChange",t)},rowClick:function(t){this.$emit("rowClick",t)}},watch:{data:function(){this.mapDataToRows()},sortState:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.sort.order=t.order||this.defaultSort.order||""},headerColsWidth:function(){this.emitColsWidth()}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=r(n(25)),o=r(n(28));function r(t){return t&&t.__esModule?t:{default:t}}e.default={name:"snb-table-thead",components:{TableColumnHeader:i.default,TableRow:o.default},props:{contentType:{type:String,default:""},showHeader:{type:Boolean,default:!0},panes:{type:Array,default:function(){return[]}},rows:{type:Array,default:function(){return[]}},sort:{type:Object,default:function(){}},colsWidth:{type:Array,default:function(){return[]}},distanX:{type:Number,default:0}},data:function(){return{tableContnt:null,tableWrapperWidth:0,leftColumnWidth:0,direction:null,isAnimation:!1,start:{x:null,y:null},end:{x:null,y:null},distan:{x:0,y:0}}},computed:{tableWidth:function(){if(!this.colsWidth.length)return Math.ceil(this.tableWrapperWidth);var t=0;return this.colsWidth.map(function(e){t+=1*e}),t=t?t+1:t,Math.ceil(Math.max(t,this.tableWrapperWidth))},overflowWidth:function(){return Math.ceil(Math.max(this.tableWidth-this.tableWrapperWidth,0))},isScrollTable:function(){return this.tableWidth<=this.tableWrapperWidth}},created:function(){},mounted:function(){this.tableContnt=this.$refs.tableContnt,this.setTableWrapperWidth(),this.getHeaderCellsWidth()},methods:{setTableWrapperWidth:function(){var t=this;this.$nextTick(function(){t.tableWrapperWidth=t.$refs.tableWrapper&&t.$refs.tableWrapper.offsetWidth||0})},setCellElWidth:function(t){this.leftColumnWidth=1*t},setColsWidth:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];"body"===this.contentType&&this.$emit("colsWidth",t)},getHeaderCellsWidth:function(){var t=this;this.$refs.tableTheaderWrapper&&this.$nextTick(function(){for(var e=[],n=t.$refs.tableTheaderWrapper.querySelectorAll(".table-column"),i=0;i5){var n=this.getAngle(t,e);n>=-45&&n<=45?this.direction="right":(n>=135&&n<=180||n>=-180&&n<-135)&&(this.direction="left")}else this.direction=null},rowClick:function(t){this.$emit("rowClick",t)}},watch:{distanX:function(){this.setTableDistanX()}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={name:"snb-table-column-header",props:{column:{type:Object,default:function(){}},sort:{type:Object,default:function(){}}},data:function(){return{}},computed:{isSortCell:function(){return!!this.sort&&(this.column.sortable||this.sort.prop===this.column.prop||this.sort.defaultProp===this.column.prop)},isAscending:function(){return this.sort&&this.sort.prop===this.column.prop&&"asc"===this.sort.order},isDescending:function(){return this.sort&&this.sort.prop===this.column.prop&&"desc"===this.sort.order}},created:function(){},mounted:function(){},methods:{handleClick:function(){this.isSortCell&&this.$emit("handleHeadSortClick",this.column)}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i,o=n(29),r=(i=o)&&i.__esModule?i:{default:i};e.default={name:"snb-table-row",components:{TableCell:r.default},props:{columns:{type:Array,default:function(){return[]}},row:{type:Object,default:function(){}},isLastRow:{type:Boolean,default:!1}},data:function(){return{}},computed:{},created:function(){},mounted:function(){this.getCellsWidth()},methods:{getCellsWidth:function(){var t=this;this.isLastRow&&this.$nextTick(function(){for(var e=[],n=t.$refs.tableTrWrapper.querySelectorAll(".table-column"),i=0;i0&&void 0!==arguments[0]?arguments[0]:[],e=[],n=null;t&&t.length&&(t.map(function(t){t.fixed&&!n?n=t||{}:e.push(t)}),n&&e.unshift(n)),this.hasFixedCell=!!n},handleHeadSortClick:function(t){this.sort.prop!==t.prop?(this.sort.prop=t.prop,this.sort.order="desc"):this.sort.order=this.sort.order||"desc",this.$emit("sortChange",this.sort)},setHeaderColsWidth:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.$emit("headerColsWidth",t)}},watch:{columns:function(t){this.reductionColumns(t)},sortState:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.sort.order=t.order||this.defaultSort.order||""}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t,e){for(var n=[],i={},o=0;o5},style:{width:t.leftColumnWidth+"px"},attrs:{contentType:"leftFixed",showHeader:t.showHeader,panes:t.panes,sort:t.sort,colsWidth:t.colsWidth,distanX:t.distanX,rows:t.rows},on:{handleHeadSortClick:t.handleHeadSortClick,translateChange:t.translateChange,rowClick:t.rowClick}}):t._e()],1),t._v(" "),n("table-content",{attrs:{contentType:"body",showHeader:t.showHeader,panes:t.panes,sort:t.sort,colsWidth:t.colsWidth,distanX:t.distanX,rows:t.rows},on:{handleHeadSortClick:t.handleHeadSortClick,colsWidth:t.setColsWidth,translateChange:t.translateChange,rowClick:t.rowClick}}),t._v(" "),n("div",{staticClass:"hidden-columns"},[t._t("default")],2)],1)},o=[]},function(t,e,n){"use strict";n.d(e,"a",function(){return i}),n.d(e,"b",function(){return o});var i=function(){var t=this.$createElement;this._self._c;return this._e()},o=[]},function(t,e,n){"use strict";n.d(e,"a",function(){return i}),n.d(e,"b",function(){return o});var i=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"ui-snb-table"},[n("div",{staticClass:"table-fixed"},[n("table-content",{staticClass:"table-top",attrs:{contentType:"header",panes:t.columns,sort:t.sort,colsWidth:t.colsWidth,distanX:t.distanX},on:{headerColsWidth:t.setHeaderColsWidth,handleHeadSortClick:t.handleHeadSortClick}}),t._v(" "),t.hasFixedCell?n("table-content",{staticClass:"table-fixed-left",style:{width:t.leftColumnWidth+"px"},attrs:{contentType:"leftFixed",showHeader:!0,panes:t.columns,sort:t.sort,colsWidth:t.colsWidth,distanX:t.distanX},on:{handleHeadSortClick:t.handleHeadSortClick}}):t._e()],1)])},o=[]},function(t,e,n){"use strict";n.r(e);var i=n(4),o=n.n(i);for(var r in i)"default"!==r&&function(t){n.d(e,t,function(){return i[t]})}(r);var a=n(12),s=n(0);var l=function(t){n(23)},d=Object(s.a)(o.a,a.a,a.b,!1,l,null,null);e.default=d.exports},,,function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SnbTableHeader=e.SnbTableColumn=e.SnbTable=void 0;var i=a(n(20)),o=a(n(30)),r=a(n(31));function a(t){return t&&t.__esModule?t:{default:t}}e.SnbTable=i.default,e.SnbTableColumn=o.default,e.SnbTableHeader=r.default},function(t,e,n){"use strict";n.r(e);var i=n(3),o=n.n(i);for(var r in i)"default"!==r&&function(t){n.d(e,t,function(){return i[t]})}(r);var a=n(13),s=n(0);var l=function(t){n(21)},d=Object(s.a)(o.a,a.a,a.b,!1,l,null,null);e.default=d.exports},function(t,e,n){var i=n(22);"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);(0,n(2).default)("1a187d27",i,!0,{})},function(t,e,n){(t.exports=n(1)(!1)).push([t.i,"table{border-collapse:collapse;border-spacing:0}.ui-snb-table{position:relative;width:100%;overflow:hidden}.ui-snb-table .table-fixed .table-fixed-top{position:absolute;left:0;top:0;z-index:8;overflow:hidden;width:100%}.ui-snb-table .table-fixed .table-fixed-left{position:absolute;left:0;top:0;z-index:9;overflow:hidden}.ui-snb-table .table-fixed .table-fixed-left.in-fixed-table{box-shadow:0 0 5px rgba(0,0,0,.12)}.ui-snb-table .hidden-columns{display:none}.ui-snb-table td,.ui-snb-table th{margin:0;padding:0;white-space:nowrap;border:1px solid #ebeef5;text-align:left}.ui-snb-table td .cell,.ui-snb-table th .cell{padding:10px 5px}.ui-snb-table tbody td,.ui-snb-table tbody th{background:#fff}.ui-snb-table thead td,.ui-snb-table thead th{background:#f5f7fa}.ui-snb-table .is-left{text-align:left}.ui-snb-table .is-right{text-align:right}.ui-snb-table .is-center{text-align:center}",""])},function(t,e,n){var i=n(24);"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);(0,n(2).default)("032f5d02",i,!0,{})},function(t,e,n){(t.exports=n(1)(!1)).push([t.i,".table-wrapper{width:100%;overflow:hidden}",""])},function(t,e,n){"use strict";n.r(e);var i=n(5),o=n.n(i);for(var r in i)"default"!==r&&function(t){n.d(e,t,function(){return i[t]})}(r);var a=n(10),s=n(0);var l=function(t){n(26)},d=Object(s.a)(o.a,a.a,a.b,!1,l,null,null);e.default=d.exports},function(t,e,n){var i=n(27);"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);(0,n(2).default)("47dc5156",i,!0,{})},function(t,e,n){(t.exports=n(1)(!1)).push([t.i,".caret-wrapper{position:relative;display:inline-flex;flex-direction:column;align-items:center;width:12px;height:22px;vertical-align:middle;overflow:hidden}.sort-caret{position:absolute;left:1px;width:0;height:0;border:5px solid transparent}.sort-caret.ascending{border-bottom-color:#c0c4cc;top:0}.sort-caret.descending{border-top-color:#c0c4cc;bottom:0}th.ascending .sort-caret.ascending{border-bottom-color:#f75b5b}th.descending .sort-caret.descending{border-top-color:#6282fb}",""])},function(t,e,n){"use strict";n.r(e);var i=n(6),o=n.n(i);for(var r in i)"default"!==r&&function(t){n.d(e,t,function(){return i[t]})}(r);var a=n(11),s=n(0),l=Object(s.a)(o.a,a.a,a.b,!1,null,null,null);e.default=l.exports},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={functional:!0,props:["column","row","colspan"],render:function(t,e){var n=e.props,i=n.column,o={class:"cell"};return i.$scopedSlots.default?t("div",o,i.$scopedSlots.default(n.row)):(o.domProps={},o.domProps.innerHTML=n.column.formatter(n.row[i.prop],n.row.data),t("div",o))}}},function(t,e,n){"use strict";n.r(e);var i=n(7),o=n.n(i);for(var r in i)"default"!==r&&function(t){n.d(e,t,function(){return i[t]})}(r);var a=n(14),s=n(0),l=Object(s.a)(o.a,a.a,a.b,!1,null,null,null);e.default=l.exports},function(t,e,n){"use strict";n.r(e);var i=n(8),o=n.n(i);for(var r in i)"default"!==r&&function(t){n.d(e,t,function(){return i[t]})}(r);var a=n(15),s=n(0);var l=function(t){n(32)},d=Object(s.a)(o.a,a.a,a.b,!1,l,null,null);e.default=d.exports},function(t,e,n){var i=n(33);"string"==typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);(0,n(2).default)("6035e855",i,!0,{})},function(t,e,n){(t.exports=n(1)(!1)).push([t.i,".ui-snb-table{position:relative;width:100%;overflow:hidden}.ui-snb-table .table-fixed .table-fixed-top{position:absolute;left:0;top:0;z-index:8;overflow:hidden;width:100%}.ui-snb-table .table-fixed .table-fixed-left{position:absolute;left:0;top:0;z-index:9;overflow:hidden}.ui-snb-table .table-fixed .table-fixed-left.in-fixed-table{box-shadow:0 0 5px rgba(0,0,0,.12)}.ui-snb-table .hidden-columns{display:none}.ui-snb-table td,.ui-snb-table th{margin:0;padding:0;white-space:nowrap;border:1px solid #ccc;text-align:left}.ui-snb-table td .cell,.ui-snb-table th .cell{padding:10px 5px}.ui-snb-table tbody td,.ui-snb-table tbody th{background:#fff}.ui-snb-table thead td,.ui-snb-table thead th{background:#f5f7fa}.ui-snb-table .is-left{text-align:left}.ui-snb-table .is-right{text-align:right}.ui-snb-table .is-center{text-align:center}",""])}])});
--------------------------------------------------------------------------------