UNPKG

nly-adminlte-vue

Version:
1,211 lines (1,035 loc) 98.8 kB
# Table > 一个支持分页,过滤,排序,异步数据等功能的表格. 如果只需要简单的展示数据可以使用组件 `nly-table-lite` 和 `nly-table-simple` > 通常情况下可以配合分页组件 `nly-bootstrap-pagination` 使用,如果需要高度定制分页功能和函数, 请使用 `nly-pagination` 组件 **带有分页的加单用法** ```html <template> <div class="overflow-auto" style="width:100%"> <nly-bootstrap-pagination v-model="currentPage" :total-rows="rows" :per-page="perPage" aria-controls="my-table" ></nly-bootstrap-pagination> <p class="mt-3">Current Page: {{ currentPage }}</p> <nly-table id="my-table" :items="items" :per-page="perPage" :current-page="currentPage" small ></nly-table> </div> </template> <script> export default { data() { return { perPage: 3, currentPage: 1, items: [ { id: 1, first_name: "张三", last_name: "张" }, { id: 2, first_name: "李四", last_name: "李" }, { id: 3, first_name: "王五", last_name: "王" }, { id: 4, first_name: "赵一", last_name: "赵" }, { id: 5, first_name: "钱二", last_name: "钱" }, { id: 6, first_name: "孙六", last_name: "孙" }, { id: 7, first_name: "左七", last_name: "左" }, { id: 8, first_name: "右八", last_name: "右" }, { id: 9, first_name: "龙九", last_name: "龙" } ] }; }, computed: { rows() { return this.items.length; } } }; </script> <!-- 带有分页.name --> <!-- with pagination.vue --> ``` **简单用法** ```html <template> <div> <nly-table striped hover :items="items"></nly-table> </div> </template> <script> export default { data() { return { items: [ { age: 40, first_name: "诸葛亮", last_name: "诸葛" }, { age: 21, first_name: "刘备", last_name: "刘" }, { age: 89, first_name: "曹操", last_name: "曹" }, { age: 38, first_name: "郭嘉", last_name: "郭" } ] }; } }; </script> <!-- 简单用法.name --> <!-- demo.vue --> ``` ## 表格数据主体(items) items 是数组类型的,且每个元素都是 `key-value`对象。 是表格渲染数据主体。 ```js const items = [ { age: 32, first_name: "Cyndi" }, { age: 27, first_name: "Havij" }, { age: 42, first_name: "Robert" } ]; ``` `<nly-table>` 会自动提取 `items` 第一个元素的 `key` 来生成表头,并会对 `kebab-case`, `snake_case`, `camelCase` 写法的 key 进行转化, 转为 `Kebab Case` 这样的写法。 - `first_name` 转为 `First Name` - `last-name` 转为 `Last Name` - `age` 转为 `Age` - `YEAR` 转为 `YEAR` - `isActive` 转为 `Is Active` - `key` 可以是中文,但是不会进行转化 提取出来生成表头的 `key` 会按照在 `items` 中第一条数据中的顺序渲染在表头。 至于自定义表头,请查看下面 **[自定义表头](#自定义表头)** **注意** 表头的顺序并不能保证一定是按照 `items` 中第一条数据中的顺序渲染,在不同的浏览器中可能会出现不同的顺序。如果需要保证顺序, 请查看 [自定义表头](#自定义表头) `items` 每个元素还有一部分可选属性,用来设置每个单元格的颜色或着触发单元格事件。支持的可选属性如下: | 属性 | 类型 | 描述 | | --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `_cellVariants` | Object | 设置每一个单元格的背景颜色. 可选 `primary`, `secondary`, `dark`, `light`, `info`, `danger`, `warning`, `success` . 这些 prop 会渲染成 `table-${variant}` 或者 `bg-${variant}` (设置 `dark`) | | `_rowVariant` | String | 设置每一行的背景颜色. 可选 `primary`, `secondary`, `dark`, `light`, `info`, `danger`, `warning`, `success` . 这些 prop 会渲染成 `table-${variant}` 或者 `bg-${variant}` (设置 `dark`) | | `_showDetails` | Boolean | 用来显示 `row-details` 插槽的内容. 具体请查看 | | [Row details 插槽](#每行详细数据) | ```html <template> <div> <nly-table hover :items="items"></nly-table> </div> </template> <script> export default { data() { return { items: [ { age: 40, first_name: "诸葛亮", last_name: "孔明" }, { age: 21, first_name: "赵云", last_name: "子龙" }, { age: 89, first_name: "张飞", last_name: "翼德", _rowVariant: "danger" }, { age: 40, first_name: "关羽", last_name: "云长", _cellVariants: { age: "info", first_name: "warning" } }, { age: 29, first_name: "曹操", last_name: "沙雕" } ] }; } }; </script> <!-- items 可选属性.vue --> <!-- items 可选属性.name --> ``` `items` 可以是一个函数,函数的返回值应该是一个数组,函数可以支持异步数据 - 返回 `null` 或者 `undefined` 直到异步结束, 当数据回调成功之后,返回唯一一个参数,这个参数应该是 `items` 类似的数组 - `Promise` 到达 resolves 状态之后,函数应该返回一个数组结果 点击 [函数类型 items](#函数类型(items)) 查看详情 **注意** - 请不要直接修改操作 `items` , 因为修改 `items` 会导致 表格重新渲染, 如果需要修好某些数据, 请查看 [Primary Key](#primary-key) - `items` 数组应该是一个简单的数组对象,并且必须避免在某一行的值中添加可能具有循环引用的数据。`<nly-table>` 将对行数据序列化为字符串进行排序和筛选,循环引用将导致堆栈溢出并导致 应用程序崩溃 ## 自定义表头 `fields` prop 会渲染为表格的表头,并按照顺序来渲染每一个列。 fields 中对象的 key 会被提取出来渲染表头,并用来完成其他功能,比如 **[排序](#排序)** `fields` 应该是一个简单的数组对象, 在表格内部, `fields` 会被转化为一个标准的数组 ### 简单数组 简单数组的 `fields`, 表头会严格按照数组顺序来渲染 ```html <template> <div> <nly-table striped hover :items="items" :fields="fields"></nly-table> </div> </template> <script> export default { data() { return { fields: ["first_name", "last_name", "age"], items: [ { isActive: true, age: 40, first_name: "诸葛亮", last_name: "诸葛孔明" }, { isActive: false, age: 21, first_name: "张飞", last_name: "张翼德" }, { isActive: false, age: 89, first_name: "刘备", last_name: "刘阿斗" }, { isActive: true, age: 38, first_name: "赵云", last_name: "赵子龙" } ] }; } }; </script> <!-- simple fields.name --> <!-- simple fields.vue --> ``` ### 对象数组 对象数组 `fields` 可以给列设置更多的属性,比如 `sortable`(允许排序), `variant`(颜色) 等。只有 `fields` 中每个元素中的 `key` 对应的 列名才会渲染出来,没有设置的 `key` 的列不会渲染。 **注意:** 下面这个 demo 中, `isActive` 这列在 `fields` 中没有对应的 `key`, 所以没有渲染出来 ```html <template> <div> <nly-table striped hover :items="items" :fields="fields"></nly-table> </div> </template> <script> export default { data() { return { fields: [ { key: "last_name", sortable: true }, { key: "first_name", sortable: false }, { key: "age", label: "Person age", sortable: true, variant: "danger" } ], items: [ { isActive: true, age: 40, first_name: "nly", last_name: "adminlte" }, { isActive: false, age: 21, first_name: "张飞", last_name: "翼德" }, { isActive: false, age: 89, first_name: "赵云", last_name: "子龙" }, { isActive: true, age: 38, first_name: "刘备", last_name: "玄德" } ] }; } }; </script> <!-- 对象数组 fields.name --> <!-- fields.vue --> ``` ### fields 自定义属性 | 属性 | 类型 | 描述 | | -------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `key` | String | 需要渲染的列名, `items` 数组中的键, `fields` 为数组对象的时候, `key` 必须设置。 `key` 也可以 用于[自定义渲染数据](#自定义渲染数据) and [插槽自定义头部和底部](#插槽自定义头部和底部) names. | | `label` | String | 每一列的别名,如果没有提供,则会用 `key`(对 key 进行内部格式转化[表格数据主体(items)](#表格数据主体(items))) 来代替, 如果设置了 `foot-clone` true, 底部列名也会用 `label代替`, 可以设置空字符(`label=""`)显示空白列名 | | `headerTitle` | String | 设置表头中 `<th>` 的 `title` 属性., 默认是没有这个属性的 | | `headerAbbr` | String | 设置表头中 `<th>` 的 `abbr` 属性, 如果标签(或标题)是缩写,则将其设置为标签(或标题)的未缩写版本。默认为无 abbr 属性 | | `class` | String or Array | 自定义 css 类型, 会添加到每一列的 `<th>` **和** `<td>` 元素中 | | `formatter` | String or Function | 列数据格式化函数, 调用方式为 `formatter(value, key, item)`. 更多详情请查看 [自定义渲染数据](#自定义渲染数据) | | `sortable` | Boolean | 设置 `true` 允许排序, 更多详情请查看 [排序](#排序) | | `sortKey` | String | <span class="badge badge-secondary">v0.7.0+</span> 当 `no-local-sorting` 是 `true` 的时候请设置 `sortBy` | | `sortDirection` | String | 设置排序方向,正序,倒序等, 更多详情请查看[修改排序方向](#修改排序方向) | | `sortByFormatted` | Boolean or Function | 设置 true 的时候会按照上面的 `formatter` 属性格式化的值排序, 默认是 `false`。如果没有 `formatter` 属性, `sortByFormatted` 不起作用。 可以接受一个格式化的函数来格式化排序的数据,但是不会渲染到表格中,仅仅用来排序, 更多详情请查看 [排序](#排序) | | `filterByFormatted` | Boolean or Function | 设置 true 的时候会按照上面的 `formatter` 属性格式化的值过滤, 默认是 `false`。如果没有 `formatter` 属性, `filterByFormatted` 不起作用。 可以接受一个格式化的函数来格式化过滤的数据,但是不会渲染到表格中,仅仅用来过滤, 更多详情请查看 [过滤](#过滤) | | `tdClass` | String or Array or Function | `<tbody>` 中的 `<td>` 单元格自定义 css 类, 如果每个单元格都需要自定义 css 类, 请传入一个 `tdClass(value, key, item)` 函数,来设置, 返回值必须是 `Array`(数组) 或者 `String` 字符串 | | `thClass` | String or Array | 自定义 `<thead>`/`<tfoot>` 中的 `<th>` 单元格 css 类 | | `thStyle` | Object | 自定义 `<thead>`/`<tfoot>` 中 `<th>` 元素的 style 属性 | | `variant` | String | 每列中 `<th>` **和** `<td>` 元素的颜色。 值 `active`, `success`, `info`, `warning`, `danger` 会在表格 header 渲染`thead-${variant}` css 类, 表格 body 渲染 `table-${variant}` css 类, 如果设置 `dark` 会渲染 `bg-${variant}` css 类 | | `tdAttr` | Object or Function | JavaScript object, 自定义 `<tbody>` 中 `<td>` 单元格的 attr 属性。 如果每个单元格都需要自定义 attr 属性, 请传入一个 `tdAttr(value, key, item)` 来设置,函数返回值必须是一个 `Object`(对象) | | `thAttr` | Object or Function | JavaScript object, 自定义 `<thead>`/`<tfoot>` 中 `<th>` 单元格的 attr 属性。 如果每个单元格都需要自定义 attr 属性, 请传入一个 `thAttr(value, key, item)` 来设置,函数返回值必须是一个 `Object`(对象) | | `isRowHeader` | Boolean | 设置 `true`, 单元格标签会渲染成 `<th>`, 默认渲染成`<td>` | | `stickyColumn` | Boolean | 设置 true, 表格会处于 [列浮动模式](#列浮动模式), 如果滚动条出现且滚动, 每一列会悬浮固定在左侧, 且会重叠, 查看更多详情 [列浮动模式](#列浮动模式) | | `fixed` | Boolean, String | `fixed` 可选 `true`, `left`, `right`。 当 `stickyColumn` 设置为 `true` 的时候, 设置 `fixed` 值, 表格会处于 [冻结列模式](#冻结列模式)。 如果 `fixed= true`, 且表格出现滚动条,随着滚动条滚动, `fixed=true` 的列依次会悬浮在左侧(不会重叠)并随着滚动条滚动。 如果 `fixed='left'`, 这些列会提取到最左侧渲染,依次排列(不会重叠), 悬浮固定在左侧,且随着滚动条滚动而滚动。如果 `fixed='right'`, 这些列会提取到最又侧渲染,依次排列(不会重叠), 悬浮固定在右侧,且随着滚动条滚动而滚动。 | | 查看更多详情 [冻结列模式](#冻结列模式) | **注意** - `fields` 的属性,如果不是格外说明, 默认值都是 `null` - `class`, `thClass`, `tdClass` 等自定义 css 不会在 `scoped CSS` 中生效, 必须使用 [VueLoader's Deep selector](https://vue-loader.vuejs.org/zh/guide/scoped-css.html#%E6%B7%B7%E7%94%A8%E6%9C%AC%E5%9C%B0%E5%92%8C%E5%85%A8%E5%B1%80%E6%A0%B7%E5%BC%8F) - 关于 `thStyle` 语法信息,请查看 [Class 与 Style 绑定](https://cn.vuejs.org/v2/guide/class-and-style.html) - 自定义属性可以通过作用域插槽 `data`, `header`, 和 `footer` 访问, 详情请查看 [自定义渲染数据](#自定义渲染数据) `fields` 支持混合使用字符串和对象 ```js const fields = [ { key: "first_name", label: "First" }, { key: "last_name", label: "Last" }, "age", "sex" ]; ``` ## Primary key `<nly-table>` 提供了一个 prop `primary-key`,用于给每列的行的 `key` 提供唯一标识 `primary-key` 的值必须是字符串或数字,并且在表的所有行中都必须唯一 `primary-key` 不需要出现在 `fields` 的可显示列中 ### 表格每行的 id 如果设置了 `primary-key`, 表格的每一行的 `<tr>` 元素会自动生成一个唯一的 id, id 渲染的格式是 `{table-id}__row_{primary-key-value}`, 其中 `{table-id}` 是 `<nly-table>` 的唯一 id, `{primary-key-value}` 是 `primary-key` 的值和对应列的值。 ### 表格渲染和动画 `primary-key` 会优化表格的渲染,在表格内部,由 `primary-key` prop 指定的列的对应每行的值会作为 `Vue :key` 作用于<tr>元素 如果使用第三方表转换或拖放插件,则指定主键列非常方便,因为它们依赖于每行都有且唯一的 `Vue :key` 如果没有提供 `primary-key`, `<nly-table>` 将根据显示行的索引号(即在显示的表行中的位置)自动生成键。这可能会导致 GUI 问题, 比如使用数据改变之前的数据进行渲染的子组件/元素指定主键列可以缓解此问题(或者可以在自定义格式字段槽中的元素/组件上设置唯一的 `:key`) 查看更多 [表格主体动画](#表格主体动画) ## 表格样式选项 | prop | 类型 | 描述 | | -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `striped` | Boolean | `<tbody>` 斑马纹式样 , 即条纹式样 | | `bordered` | Boolean | 给所有单元格和头部添加圆角边框式样 | | `borderless` | Boolean | 移除所有单元格的内置边框 table. | | `outlined` | Boolean | 给表格添加外边框, 如果 `bordered` prop 设置为 true, `outlined`会失效 | | `small` | Boolean | 小型表格 | | `hover` | Boolean | 给`<tbody>` 中的每行添加添加鼠标悬浮效果 | | `dark` | Boolean | 反转颜色-在深色背景上使用浅色文本 | | `fixed` | Boolean | 设置每列等宽,会加快渲染速度 | | `responsive` | Boolean or String | 使得表格自适应宽度并添加水平滚动条,可选 'sm', 'md', 'lg', 'xl' 或者 'true', 由于 adminlte3 的 bug,(其实是 bootstrap 的 bug), 通常水平滚动条并不会出现。可以在 table 外面套一层'<div class='table-responsive'>', 查看等多详情 [响应模式](#响应模式) | | `sticky-header` | Boolean or String | 设置 true 会使得头部悬浮. 并且表格的最大高度为 300px, 使用其他 css 或者 style 可以设置表格的高度,查看更多详情 [头部浮动模式](#头部浮动模式) | | `stacked` | Boolean or String | 表格堆叠模式. 设置 true 使得表格一直处于堆叠模式, 或者可以设置为对应的 'sm', 'md', 'lg', 'xl' 断点来使得表格在对应的断点变成堆叠模式, 查看更多详情 [堆叠模式](#堆叠模式) | | `caption-top` | Boolean | 如果表格有标题, 设置 `caption-top` 为 `true`, 标题会放置在表格上方, 如果设置为 `false` (默认值), 标题会放在表格底部 | | `table-variant` | String | 表格颜色, 可选 'primary','secondary','info','danger','warning','success','light', 'dark' | | `head-variant` | String | 头部颜色,可选 `'light'` or `'dark'`, 会覆盖 `head-row-variant` | | `foot-variant` | String | 底部颜色,可选 `'light'` or `'dark'`, 如果没有传入值, 默认会使用 `head-variant` prop 的值,如果没有设置 `foot-clone` 则无效, 会覆盖 `foot-row-variant` | | `foot-clone` | Boolean | 复制头部的内容到底部,并集成头部的功能 | | `no-footer-sorting` | Boolean | 设置为 true 的时候, 如果 `foot-clone` 为 true 且每列设置 `sortable`, 会禁用排序功能 | | `no-border-collapse` | Boolean | 禁用表格边框的可重叠性。主要用于 [头部浮动模式](#头部浮动模式) 和 [列浮动模式](#列浮动模式)。在某些情况下会导致出现双重边界 | 示例 Demo ```html <template> <div> <nly-form-group label="Table Options" label-cols-lg="2"> <nly-form-checkbox v-model="striped" inline>Striped</nly-form-checkbox> <nly-form-checkbox v-model="bordered" inline>Bordered</nly-form-checkbox> <nly-form-checkbox v-model="borderless" inline >Borderless</nly-form-checkbox > <nly-form-checkbox v-model="outlined" inline>Outlined</nly-form-checkbox> <nly-form-checkbox v-model="small" inline>Small</nly-form-checkbox> <nly-form-checkbox v-model="hover" inline>Hover</nly-form-checkbox> <nly-form-checkbox v-model="dark" inline>Dark</nly-form-checkbox> <nly-form-checkbox v-model="fixed" inline>Fixed</nly-form-checkbox> <nly-form-checkbox v-model="footClone" inline >Foot Clone</nly-form-checkbox > <nly-form-checkbox v-model="noCollapse" inline >No border collapse</nly-form-checkbox > </nly-form-group> <nly-form-group label="Head Variant" label-cols-lg="2"> <nly-form-radio-group v-model="headVariant" class="mt-lg-2"> <nly-form-radio :value="null" inline>None</nly-form-radio> <nly-form-radio value="light" inline>Light</nly-form-radio> <nly-form-radio value="dark" inline>Dark</nly-form-radio> </nly-form-radio-group> </nly-form-group> <nly-form-group label="Table Variant" label-for="table-style-variant" label-cols-lg="2" > <nly-form-select v-model="tableVariant" :options="tableVariants" id="table-style-variant" > <template #first> <option value="">-- None --</option> </template> </nly-form-select> </nly-form-group> <nly-table :striped="striped" :bordered="bordered" :borderless="borderless" :outlined="outlined" :small="small" :hover="hover" :dark="dark" :fixed="fixed" :foot-clone="footClone" :no-border-collapse="noCollapse" :items="items" :fields="fields" :head-variant="headVariant" :table-variant="tableVariant" ></nly-table> </div> </template> <script> export default { data() { return { fields: ["first_name", "last_name", "age"], items: [ { age: 40, first_name: "nly", last_name: "adminlte" }, { age: 21, first_name: "张飞", last_name: "翼德" }, { age: 89, first_name: "赵云", last_name: "子龙" } ], tableVariants: [ "primary", "secondary", "info", "danger", "warning", "success", "light", "dark" ], striped: false, bordered: false, borderless: false, outlined: false, small: false, hover: false, dark: false, fixed: false, footClone: false, headVariant: null, tableVariant: "", noCollapse: false }; } }; </script> <!-- 式样demo.name --> <!-- style-demo.vue --> ``` ### 行式样和属性 你可以使用 prop `tbody-tr-class` 给你每行设置自定义 css 类, 也可以使用 `tbody-tr-attr` 给每一行设置 attr 属性 | 属性 | 类型 | 描述 | | ---------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `tbody-tr-class` | String, Array or Function | 给表格每行设置自定义 css 类, 如果接受的是一个函数, 调用方式是 `tbodyTrClass( item, type )` , 函数必须返回一个 `Array`, `Object` 或者 `String` | | `tbody-tr-attr` | Object or Function | 给表格每行设置自定义 attrs 属性, 如果接受的是一个函数, 调用方式是 `tbodyTrAttr( item, type )` , 函数必须返回一个 `Object` | 如果将函数传给 `tbody-tr-class` 和 `tbody-tr-attr`, 函数参数应该是: - `item`, items 中每一行的数据, 如果数据不在 items 中, 那么 item 会自动转换为 `null` 或者 `undefined` - `type`, 将要渲染在表格的哪个地方, 可选 `'row'`, `'row-details'`, `'row-top'`, `'row-bottom'`, `'table-busy'`。 `'row'` 是渲染在每一行数据, `'row-details'` 是渲染在每一行的 `row-detail` 插槽中,`'row-top'` 用于固定行顶部插槽,`'row-bottom'` 用于固定行底部插槽, `'table-busy'` 用于表格繁忙插槽 ```html <template> <div> <nly-table :items="items" :fields="fields" :tbody-tr-class="rowClass" ></nly-table> </div> </template> <script> export default { data() { return { fields: ["first_name", "last_name", "age"], items: [ { age: 40, first_name: "nly", last_name: "adminlte", status: "awesome" }, { age: 21, first_name: "张飞", last_name: "翼德" }, { age: 89, first_name: "赵云", last_name: "子龙" } ] }; }, methods: { rowClass(item, type) { if (!item || type !== "row") return; if (item.status === "awesome") return "table-success"; } } }; </script> <!-- row-style.name --> <!-- row-style.vue --> ``` ### 响应模式 prop `responsive` 可以让表格出现水平滚动条, 设置 `true` 可以使表格一直出现滚动条, 也可以设置为 `sm`, `md`, `lg`, `xl`, 使表格在对应的断点出现滚动条 ```html <template> <div> <nly-table responsive :items="items"></nly-table> </div> </template> <script> export default { data() { return { items: [ { heading1: "算尽天机-诸葛半仙", heading2: "算尽天机-诸葛半仙", heading3: "算尽天机-诸葛半仙", heading4: "算尽天机-诸葛半仙", heading5: "算尽天机-诸葛半仙", heading6: "算尽天机-诸葛半仙", heading7: "算尽天机-诸葛半仙", heading8: "算尽天机-诸葛半仙", heading9: "算尽天机-诸葛半仙", heading10: "算尽天机-诸葛半仙", heading11: "算尽天机-诸葛半仙", heading12: "算尽天机-诸葛半仙" }, { heading1: "算尽天机-诸葛半仙", heading2: "算尽天机-诸葛半仙", heading3: "算尽天机-诸葛半仙", heading4: "算尽天机-诸葛半仙", heading5: "算尽天机-诸葛半仙", heading6: "算尽天机-诸葛半仙", heading7: "算尽天机-诸葛半仙", heading8: "算尽天机-诸葛半仙", heading9: "算尽天机-诸葛半仙", heading10: "算尽天机-诸葛半仙", heading11: "算尽天机-诸葛半仙", heading12: "算尽天机-诸葛半仙" }, { heading1: "算尽天机-诸葛半仙", heading2: "算尽天机-诸葛半仙", heading3: "算尽天机-诸葛半仙", heading4: "算尽天机-诸葛半仙", heading5: "算尽天机-诸葛半仙", heading6: "算尽天机-诸葛半仙", heading7: "算尽天机-诸葛半仙", heading8: "算尽天机-诸葛半仙", heading9: "算尽天机-诸葛半仙", heading10: "算尽天机-诸葛半仙", heading11: "算尽天机-诸葛半仙", heading12: "算尽天机-诸葛半仙" } ] }; } }; </script> <!-- responsive.name --> <!-- responsive.vue --> ``` ```html <template> <div class="table-responsive"> <nly-table sticky-header :items="items"></nly-table> </div> </template> <script> export default { data() { return { items: [ { heading1: "算尽天机-诸葛半仙", heading2: "算尽天机-诸葛半仙", heading3: "算尽天机-诸葛半仙", heading4: "算尽天机-诸葛半仙", heading5: "算尽天机-诸葛半仙", heading6: "算尽天机-诸葛半仙", heading7: "算尽天机-诸葛半仙", heading8: "算尽天机-诸葛半仙", heading9: "算尽天机-诸葛半仙", heading10: "算尽天机-诸葛半仙", heading11: "算尽天机-诸葛半仙", heading12: "算尽天机-诸葛半仙" }, { heading1: "算尽天机-诸葛半仙", heading2: "算尽天机-诸葛半仙", heading3: "算尽天机-诸葛半仙", heading4: "算尽天机-诸葛半仙", heading5: "算尽天机-诸葛半仙", heading6: "算尽天机-诸葛半仙", heading7: "算尽天机-诸葛半仙", heading8: "算尽天机-诸葛半仙", heading9: "算尽天机-诸葛半仙", heading10: "算尽天机-诸葛半仙", heading11: "算尽天机-诸葛半仙", heading12: "算尽天机-诸葛半仙" }, { heading1: "算尽天机-诸葛半仙", heading2: "算尽天机-诸葛半仙", heading3: "算尽天机-诸葛半仙", heading4: "算尽天机-诸葛半仙", heading5: "算尽天机-诸葛半仙", heading6: "算尽天机-诸葛半仙", heading7: "算尽天机-诸葛半仙", heading8: "算尽天机-诸葛半仙", heading9: "算尽天机-诸葛半仙", heading10: "算尽天机-诸葛半仙", heading11: "算尽天机-诸葛半仙", heading12: "算尽天机-诸葛半仙" } ] }; } }; </script> <!-- responsive.name --> <!-- responsive.vue --> ``` **注意** - 由于 adminlte3 的 bug,(其实是 bootstrap 的 bug), 可能水平滚动条并不会出现。可以在 table 外面套一层 `<div class='table-responsive'>` - 这个 prop 可能会出现各种无法预料的 bug, 比如表格超出父元素等等,请在 table 外面套一层 `<div class='table-responsive'>` - 同时使用 `responsive` 和 `fixed`, 会出现冲突。 这时候请给每列设置宽度, 文档中可以设置列宽的方法都可以 ### 堆叠模式 prop `stacked` 可以让表格出现水平滚动条, 设置 `true` 可以使表格一直出现滚动条, 也可以设置为 `sm`, `md`, `lg`, `xl`, 使表格在对应的断点渲染成堆叠表 堆叠模式在应用于小屏或者移动端很有用处 每列的列名将会使用 `CSS::before` 伪元素呈现在每个字段值的左侧,宽度为 40% `stacked` prop 的优先级高于 `responsive` prop,[`sticky-header`](#头部浮动模式) prop 和 [`sticky-column`](#列浮动模式) prop ```html <template> <div> <nly-table stacked :items="items"></nly-table> </div> </template> <script> export default { data() { return { items: [ { age: 40, first_name: "nly", last_name: "adminlte" }, { age: 21, first_name: "张飞", last_name: "翼德" }, { age: 89, first_name: "赵云", last_name: "子龙" } ] }; } }; </script> <!-- 堆叠模式.name --> <!-- stacked.vue --> ``` ### 表格标题 使用 `caption` prop 或者使用 `caption` 插槽可以给表格添加标题或者注释,默认 `caption` 在表格下方 ```html <template> <div> <nly-table :items="items" :fields="fields" caption="这是一个注释"> </nly-table> </div> <div> <nly-table :items="items" :fields="fields"> <template #table-caption>这是一个注释</template> </nly-table> </div> </template> <script> export default { data() { return { fields: ["first_name", "last_name", "age"], items: [ { age: 40, first_name: "nly", last_name: "adminlte" }, { age: 21, first_name: "张飞", last_name: "翼德" }, { age: 89, first_name: "赵云", last_name: "子龙" } ] }; } }; </script> <!-- caption.name --> <!-- caption.vue --> ``` 使用 `caption-top` prop, 设置为 `true` 可以让标题或者注释渲染在表格上方 ```html <template> <div> <nly-table :items="items" :fields="fields" caption="这是一个注释" caption-top > </nly-table> </div> </template> <script> export default { data() { return { fields: ["first_name", "last_name", "age"], items: [ { age: 40, first_name: "nly", last_name: "adminlte" }, { age: 21, first_name: "张飞", last_name: "翼德" }, { age: 89, first_name: "赵云", last_name: "子龙" } ] }; } }; </script> <!-- caption-top.name --> <!-- caption-top.vue --> ``` ### 作用域插槽 `table-colgroup` 使用作用域插槽 `table-colgroup` 设置每列的 `<colgroup>` 和 `<col>` 元素的式样 插槽 `table-colgroup` 可以接受以下参数: | 属性 | 类型 | 描述 | | --------- | ------ | ----------------------------------------------------------------- | | `columns` | Number | 表格中的列数 | | `fields` | Array | `fields` 数组中定义的元素, 更多详情请查看 [对象数组](#对象数组)) | 如果设置了 `table-colgroup`, 会把插槽内容嵌入到 `<colgroup>` 元素中, 您不需要额外设置 `<colgroup>` 元素, 如果辅助技术需要对表列进行分组, 请设置 `<col span="#">` (请使用一分组的列数来代替`#`)。 在某些情况下, 使用 `style` 或者 `css class` 来给 `<col>` 元素设置列宽的时候, 可能会使表格渲染成列的等宽模式, 可以结合使用 `responsive` 模式, 给每一列 `<col>` 元素设置显性的列宽和最小列宽 ```html <nly-table fixed responsive :items="items" :fields="fields" ...> <template #table-colgroup="scope"> <col v-for="field in scope.fields" :key="field.key" :style="{ width: field.key === 'foo' ? '120px' : '180px' }" /> </template> </nly-table> ``` ### 表格加载状态 `nly-table` 提供了一个 `busy` prop 来在视觉上显示表格加载状态, 在加载数据之前设置 `busy` 为 `true` 来展示加载状态, 加载完数据之后设置 `busy` 为 `false` 关闭加载提示。 加载状态会自动添加 attr 属性 `aria-busy="true"` 可以通过设置 `css` 来调整加载状态透明度 ```css table.nly-table[aria-busy="true"] { opacity: 0.6; } ``` 如果设置 `busy` prop 为 `true` 时, 也可以使用 `table-busy` 插槽来自定义加载状态消息。 ```html <template> <div> <nly-button @click="toggleBusy">切换加载状态</nly-button> <nly-table :items="items" :busy="isBusy" class="mt-3" outlined> <template #table-busy> <div class="text-center text-danger my-2"> <nly-spinner class="align-middle"></nly-spinner> <strong>加载中...</strong> </div> </template> </nly-table> </div> </template> <script> export default { data() { return { isBusy: false, items: [ { age: 40, first_name: "nly", last_name: "adminlte" }, { age: 21, first_name: "张飞", last_name: "翼德" }, { age: 89, first_name: "赵云", last_name: "子龙" } ] }; }, methods: { toggleBusy() { this.isBusy = !this.isBusy; } } }; </script> <!-- 加载状态.name --> <!-- busy.vue --> ``` ## 自定义渲染数据 可以使用 `scoped slots` 或者 `formatter` 函数来自定义每一列数据渲染形式 ### Scoped fields slots `scoped fields slots` 可以帮助更好的展示每一列的数据, 您可以使用 `scoped slots` 自定义渲染 `fields` 中指定列数据。如果您需要额外渲染一个不在 `items` 中的列, 在 `fields` 中添加列名, 在 scoped slots 中指定列名就可以了。 使用方式为 `cell(' + field key + ')` ```html <template> <div> <nly-table small :fields="fields" :items="items" responsive="sm"> <template #cell(index)="data"> {{ data.index + 1 }} </template> <template #cell(name)="data"> <b class="text-info">{{ data.value.last.toUpperCase() }}</b>, <b>{{ data.value.first }}</b> </template> <template #cell(nameage)="data"> {{ data.item.name.first }} is {{ data.item.age }} years old </template> <template #cell()="data"> <i>{{ data.value }}</i> </template> </nly-table> </div> </template> <script> export default { data() { return { fields: [ "index", { key: "name", label: "Full Name" }, "age", "sex", { key: "nameage", label: "First name and age" } ], items: [ { name: { first: "张", last: "翼德" }, sex: "男", age: 42 }, { name: { first: "诸葛", last: "孔明" }, sex: "女", age: 36 }, { name: { first: "关", last: "云长" }, sex: "男", age: 73 }, { name: { first: "赵", last: "子龙" }, sex: "女", age: 62 } ] }; } }; </script> <!-- scoped slots.name --> <!-- scoped-slots.vue --> ``` `scoped slots` 中的变量具有以下属性: | 属性 | 类型 | 描述 | | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `index` | Number | 每一个的行数,当前行的索引 (默认从 0 开始) | | `item` | Object | 每当前行的数据, 即 `items` 中代表当前行数据(未进进行内部格式化的数据) | | `value` | Any | `fileds` 中当前列的 `key` 值, 如果是一个额外的虚拟列,值会是 `null` 或者 `undefined`。 如果在 `fields` 中设置了 [`formatter`](#格式化函数), 值是 `formatter` 返回的值 | | `unformatted` | Any | `fileds` 中当前列的 `key` 值, 是[`formatter`](#格式化函数) 格式化之前的数据, 如果是一个额外的虚拟列,值会是 `null` 或者 `undefined`。 | | `field` | Object | `fields` 中的元素 | | `detailsShowing` | Boolean | 设置为 `true` 会显示 `row-details` 插槽内容, 查看更多详情 [每行详情数据](#每行详情数据) | | `toggleDetails` | Function | 可以切换 `row-details` 插槽可见状态, 查看更多详情 [每行详情数据](#每行详情数据) | | `rowSelected` | Boolean | 如果选中当前行 `rowSelected` 为 `true`, 更多详情请查看 [可选中模式](#可选中模式) | | `selectRow` | Function | 一个调用可以选中指定行的函数, 查看更多详情 [可选中模式](#可选中模式) | | `unselectRow` | Function | 一个调用可以取消选中指定行的函数, 查看更多详情 [可选中模式](#可选中模式) | **注意:** - `index` 并不是每一行真正的所有,他只是在经过过滤, 排序, 分页之后根据当前页需要渲染的数据算出来的, 默认的 `index` 是显示每一行的行号, 将与可选的 v-model 绑定变量中的索引对齐 - 使用新版本的 V ue 2.6 `v-slot` 语法时,请注意插槽名称不能包含空格,而在浏览器中使用 DOM 模板时,插槽名称应该是小写。要解决这个问题,可以使用 Vue 的[动态插槽名称](https://cn.vuejs.org/v2/guide/components-slots.html#%E5%8A%A8%E6%80%81%E6%8F%92%E6%A7%BD%E5%90%8D)传递插槽名称 ### 渲染 html 字符串 默认情况下, `nly-table` 会自动转义 `items` 中的 `html` 字符串,如果需要在 `nly-table` 中显示渲染 `html` 字符串, 请在 `scoped slots` 中使用 `v-html` 指令 ```html <template> <div> <nly-table :items="items"> <template #cell(html)="data"> <span v-html="data.value"></span> </template> </nly-table> </div> </template> <script> export default { data() { return { items: [ { text: "This is <i>escaped</i> content", html: 'This is <i>raw <strong>HTML</strong></i> <span style="color:red">content</span>' } ] }; } }; </script> <!-- html字符串.name --> <!-- html.vue --> ``` <div class="alert alert-warning"> <p class="mb-0 small"> <strong>注意:</strong> 使用 (<code class="notranslate" translate="no" >html</code >) 字符串的属性可能会引起 <nly-link href="https://en.wikipedia.org/wiki/Cross-site_scripting" class="alert-link" target="_blank" > 脚本攻击 (XSS), </nly-link> 当用户使用这类属性的时候,您应该谨慎 <nly-link href="https://en.wikipedia.org/wiki/HTML_sanitization" class="alert-link" target="_blank" > 处理 </nly-link> 这类值 </p> </div> ### 格式化函数 可以使用 `formatter` 函数格式化对应 `field`(列) 的渲染, `formatter` 必须接受一个字符串或者函数。 如果接受的是字符串, 字符串对应的函数名函数应该在父组件中定义好。 如果接受的是函数, 函数应该在全局范围内申明,或者绑定到 `this`。 `formatter` 函数可以接受三个参数,分别是 `value`, `key`, `item`, 返回值必须是一个字符串。 ```html <template> <div> <nly-table :fields="fields" :items="items"> <template #cell(name)="data"> <a :href="`#${data.value.replace(/[^a-z]+/i,'-').toLowerCase()}`" >{{ data.value }}</a > </template> </nly-table> </div> </template> <script> export default { data() { return { fields: [ { key: "name", label: "Full Name", formatter: "fullName" }, "age", { key: "sex", formatter: value => { return value.charAt(0).toUpperCase(); } }, { key: "birthYear", label: "Calculated Birth Year", formatter: (value, key, item) => { return new Date().getFullYear() - item.age; } } ], items: [ { name: { first: "张", last: "翼德" }, sex: "男", age: 42 }, { name: { first: "诸葛", last: "孔明" }, sex: "女", age: 36 }, { name: { first: "关", last: "云长" }, sex: "男", age: 73 }, { name: { first: "赵", last: "子龙" }, sex: "女", age: 62 } ] }; }, methods: { fullName(value) { return `${value.first} ${value.last}`; } } }; </script> <!-- formatter.name --> <!-- formatter.vue --> ``` ## 插槽自定义头部和底部 `nly-table` 支持自定义设置页眉和页脚(头部和底部),在默认情况下,可以设置 `foot_clone` 为 true 来 copy 一个页眉作为页脚 页眉页脚每一个单元格的**作用域插槽**使用方式为 `#head(<fieldkey>)='data'`, `#foot(<fieldkey>)='data'`。 如果没有设置页 脚插槽 `#foot(<fieldkey>)='data'`,而设置了 `foot-clone` 的话, 页眉会默认使用页眉插槽 `#head(<fieldkey>)='data'` 也可以使用 `#head()` 或者 `#foot()` 来代替作用域插槽,这种写法没有可调用的显性参数 **注意** - `<fieldkey>` 为列名的 key - `#head()` 和 `#foot()` 会作用于那些没有作用于插槽 `#head(<fieldkey>)='data'`, `#foot(<fieldkey>)='data'` 的列上 ```html <template> <div> <nly-table :fields="fields" :items="items" foot-clone> <template #cell(name)="data"> {{ data.value.first }} {{ data.value.last }} </template> <template #head(name)="data"> <span class="text-info">{{ data.label.toUpperCase() }}</span> </template> <template #foot(name)="data"> <span class="text-danger">{{ data.label }}</span> </template> <template #foot()="data"> <i>{{ data.label }}</i> </template> </nly-table> </div> </template> <script> export default { data() { return { fields: [{ key: "name", label: "全名" }, "age", "sex"], items: [ { name: { first: "飞", last: "张" }, sex: "男", age: 42 }, { name: { first: "云", last: "赵" }, sex: "男", age: 36 }, { name: { first: "羽", last: "关" }, sex: "女", age: 73 }, { name: { first: "孔明", last: "诸葛" }, sex: "女", age: 62 } ] }; } }; </script> <!-- head-foot.name --> <!-- head-foot.vue --> ``` 页眉页脚的作用域可调用参数 | 参数 | 类型 | 描述 | | --------------- | ------ | ------------------------------------------------------------------ | | `column` | String | fields prop 的 `key` 值 | | `field` | Object | 列对象 (`fields` prop 中当前列对应的对象元素) | | `label` | String | `fields` prop 中的 `label` 值 (也可以用 `data.field.label` 来代替) | | `selectAllRows` | Method | 选中所有所有行 (只有处于 [`可选中模式`](#可选中模式) 模式才有效 | | `clearSelected` | Method | 取消选中行 (只有处于 [`可选中模式`](#可选中模式) 模式才有效 | 如果往插槽 `head(...)` 和 `foot(...)` 插入 `inputs`, `buttons`, `selects` 或者 `links` 组件时和元素时,请注意: - 点击 `input`, `select`, `textarea` 的时候, `head-clicked` 不会被触发 - 点击 `links`, `buttons` 时, `head-clicked` 不会触发 - 使用 `vue 2.6` 的 `v-slot` 写法时, 插槽明不能包含空格。 使用浏览器 dom 元素的时候,插槽名应该小写。如果需要以上情况以外的写法,请查看 [Vue's dynamic slot names](https://cn.vuejs.org/v2/guide/components-slots.html#%E5%8A%A8%E6%80%81%E6%8F%92%E6%A7%BD%E5%90%8D) ### 添加自定义表头 使用作用域插槽 `thead-top` 向表头添加额外的行内容, 这些行内容会插入 `fields` 表头之前,且不会被 `<tr>..</tr>` 标签包裹 不建议插入原生 dom 元素,您可以查看 [表格组件](#表格组件) 来选择需要插入的组件 `rowspan` 可以设置占用列高, `colspan`可以设置占用列宽 ```html <template> <div> <nly-table :items="items" :fields="fields" responsive="sm"> <template #thead-top="data"> <nly-tr> <nly-th rowspan="2" colspan="2" ><span class="sr-only">空列名</span></nly-th > <nly-th variant="secondary">列1</nly-th> <nly-th variant="primary" colspan="3">列2</nly-th> <nly-th variant="danger">列3</nly-th> </nly-tr> <nly-tr> <nly-th variant="secondary">列1</nly-th> <nly-th variant="primary" colspan="3">列2</nly-th> <nly-th variant="danger">列3</nly-th> </nly-tr> </template> </nly-table> </div> </template> <script> export default { data() { return { items: [ { name: "Stephen Hawking", id: 1, type1: false, type2a: true, type2b: false, type2c: false, type3: false }, { name: "Johnny Appleseed", id: 2, type1: false, type2a: true, type2b: true, type2c: false, type3: false }, { name: "George Washington", id: 3, type1: false, type2a: false, type2b: false, type2c: false, type3: true