Vueには多くのテーブルコンポーネントがあります。 さまざまな機能を備えています。 また、さまざまな方法でテーブルがテンプレートページまたはコンポーネントに組み込まれます。
基本的には次のようになります。
<template> <cmp-table :items="items" :columns="columns"/> </template> <script> export default { name: 'page', data() { return { items: [ { id: 1, name: 'Sony' } , { id: 2, name: 'Apple' }, { id: 3, name: 'Samsung' } ], columns: [ { prop: 'id', title: 'ID' }, { prop: 'name', title: 'Name' } ] } } } </script>
ここでは、 cmp-tableコンポーネントデータ( items )と列設定( columns )を渡します 。 そして、コンポーネント自体はすでにこれらの設定のテーブルをレンダリングしています。
設定はすべての人のために整理されています。 列設定、またはヒープ内のすべてを分離するだけです-列設定、テーブル、一部のアクションなど
このアプローチでは、列のレンダリング設定を整理する方法が好きではありません。 theadテーブルのヘッダーにある名前と、列の内容の両方。
テンプレート自体でこの機能を確認し、そこに列(コンテンツとヘッダー)を作成します。 より視覚的で便利です。 私は。
たとえば、このアプローチは、今日最も人気のあるコンポーネントコレクションであるElementで使用されています。
そこでは次のようになります:
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180"/> <el-table-column prop="name" label="Name" width="180"/> <el-table-column prop="address" label="Address"/> </el-table> </template> <script> export default { name: 'page', data() { return { tableData: [{ date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' }] } } } </script>
ここではすべてが明確です。 列とセルの一般的なビューをすぐに想像できます。 そして、 el-tableコンポーネントでは、テーブル自体のデータと設定のみを転送します。
そして、すべては何もないでしょう。 私は一般的に要素が好きです。 しかし、テーブルが遅くなっていることにしばしば気づきました。 私は彼らのコードに入りました。 そして、行、セル、その他すべてのレンダリングがどれほど混乱しているかということから、ofigel。 大量のコード。 そして、私は彼らと同じようにテーブルを作る方法を考え始めました。 はるかに簡単です。
今、私がやったことを教えて見せます。
最終的に私たちのコンポーネントになるものについてすぐに。 さらに理解しやすくするために:
- Element(el-table)に似た列の構築
- セルのタイプをカスタマイズする機能
- 非常に少ないコード
- 問題なく機能を拡張する機能
テーブルは2つの部分で構成されます。
- TableColumnのコンポーネント-その助けを借りて、テーブルヘッダーとセルのビューを形成します
- テーブルコンポーネント-すべてが組み立てられ、レンダリングされます
TableColumnコンポーネント-または簡潔さがすべてです
table-column.js :
export default { name: 'vu-table-column', props: ['prop', 'title'] };
これは、 vu-table-columnという名前のVueコンポーネントといくつかの入力パラメーターです。
- prop-その中で、転送されたデータの行プロパティの名前をテーブルに転送します。
- title-このプロパティの名前。テーブルのヘッダーに表示されます。
はい-コンポーネントの現在の要件を実装するために必要なのはこれだけです。 さらに、ここですべてが非常に単純である理由が明らかになります。
テーブルコンポーネント-または、可能性が少ない場合にコードを増やす理由
table.js
import './style.scss' import { get } from 'lodash' export default { name: 'vu-table', props: { rows: { type: Array, required: true } }, methods: { renderColumns(h, row, columnsOptions) { return columnsOptions.map((column, index) => { return h('td', { class: 'vu-table__tbody-td' }, [ column.scopedSlot ? column.scopedSlot({row, items: this.rows}) : row[column.prop] ]) }) } }, render(h) { const columnsOptions = this.$slots.default.filter(item => { return (item.componentOptions && item.componentOptions.tag === 'vu-table-column') }).map(column => { return Object.assign({}, column.componentOptions.propsData, { scopedSlot: get(column, 'data.scopedSlots.default') } ) }) const columnsHead = columnsOptions.map((column, index) => { return h('th', { class: 'vu-table__thead-th', key: index}, column.title) }) const rows = this.rows.map((row, index) => { return h('tr', { key: index }, [ this.renderColumns(h, row, columnsOptions) ]) }) return h('table', { class: 'vu-table' }, [ h('thead', { class: 'vu-table__thead' }, [ h('tr', [ columnsHead ]) ]), h('tbody', { class: 'vu-table__tbody' }, [ rows ]) ]) } };
そして、コードを確認します。
import './style.scss' import { get } from 'lodash' export default { name: 'vu-table', props: { rows: { type: Array, required: true } } ... }
まず、表スタイルをインポートします。
そして、ここではlodash get関数を使用します。 これは必要ありません。 彼女はコードを短くするためにここにいます。
次に、入力パラメーターrows 。データを文字列の配列として転送します。
レンダリング機能の場合:
render(h) { const columnsOptions = this.$slots.default.filter(item => { return (item.componentOptions && item.componentOptions.tag === 'vu-table-column') }).map(column => { return Object.assign({}, column.componentOptions.propsData, { scopedSlot: get(column, 'data.scopedSlots.default') } ) }) const columnsHead = columnsOptions.map((column, index) => { return h('th', { class: 'vu-table__thead-th', key: index}, column.title) }) const rows = this.rows.map((row, index) => { return h('tr', { key: index }, [ this.renderColumns(h, row, columnsOptions) ]) }) return h('table', { class: 'vu-table' }, [ h('thead', { class: 'vu-table__thead' }, [ h('tr', [ columnsHead ]) ]), h('tbody', { class: 'vu-table__tbody' }, [ rows ]) ]) }
columnOptionsでは、列とセルの設定を構成します。
これを行うには、まず、 テーブルコンポーネントのデフォルトスロット( this。$ Slots.default )からvu-table-columnタグ( TableColumnコンポーネント)を持つすべての要素を収集し、フィルタリングします。
これまでのところ、便利で視覚的な方法で列設定を転送するためにのみTableColumnコンポーネントが必要です。 これが、 TableColumnに レンダリング関数がない理由です。 このコンポーネントをレンダリングしないためです。 データを取得するだけです。
そして、フィルタリングされたvu-table-columnの配列を調べて 、vu-table-columnからの入力小道具でオブジェクトの配列を形成し、 scopedSlotプロパティを追加します。 ページテンプレートのvu-table-columnに渡された場合、限られたスコープのデフォルトスロットを保存します(存在する場合)。 これは、このスロットの内容をレンダリングする関数です。 また、このスロットのテンプレートで使用されるパラメーターを渡すことができます。 このスロットは、カスタムタイプのセルに使用します。
次に、 columnsHead (テーブルヘッダーのセル)を収集します-上記で定義した列設定( columnOptions )を調べて、 title - vu-table-columnに渡した列の名前を引き出します 。
行の配列(実際にはテーブルの最終行)を形成します-入力行を調べ 、各tr要素でrenderColumnsメソッドを使用してセルを表示します:
renderColumns(h, row, columnsOptions) { return columnsOptions.map((column, index) => { return h('td', { class: 'vu-table__tbody-td' }, [ column.scopedSlot ? column.scopedSlot({row, items: this.rows}) : row[column.prop] ]) }) }
h-関数( vNodeをレンダリングする $ createElement関数のエイリアス)をmethod 、rowデータ、 columnOptions列設定の配列に渡します 。
そして、レンダリングするセルの配列を収集します。
- または、 行パラメーター( 行オブジェクトを含む)およびアイテム (vu-tableに転送されるデータ)を指定してscopedSlot関数を実行することにより、列設定の可視性が制限されたスロットがある場合はカスタムビュー。 ここで必要なものすべてを伝えることができます
- 行の column.propというプロパティの値のみ
要素配列をレンダリングするときは、各要素にキーパラメータを割り当てることを忘れないでください。 そうしないと、データを更新するときに、表示されたデータに衝突が生じる可能性があります。そして、 レンダリング機能の最後に、ヘッダーセルが挿入された最終テーブルと、レンダリングされた行を表示します。
それだけです!
セルとヘッダーを描画するためのすべてのコードです。
さらに、フィルタリング、列の非表示/表示、ソート、および魂が望むすべてのものを貼り付けることはすでに可能です。 これは次の話です。 そして、それは次の記事にあります。 無限のテキストを書かないために。
そして、書かれたコンポーネントを使用する例:
example.vue
<template lang="html"> <div> <vu-table :rows="rows"> <vu-table-column prop="id" title="ID"> <template slot-scope="{ row }"> <b>{{ row.id }}</b> </template> </vu-table-column> <vu-table-column prop="name" title="Name"/> <vu-table-column prop="rating" title="Rating"> <template slot-scope="{ row, items }"> {{ row.rating }} <b v-if="items.every(item => item.rating <= row.rating)">Best choie!</b> </template> </vu-table-column> </vu-table> </div> </template> <script> export default { name: 'example-page', data() { return { rows: [ { id: 1, name: 'Sony', rating: 777 }, { id: 2, name: 'Apple', rating: 555 }, { id: 3, name: 'Samsung', rating: 333 } ] } } }; </script>
ここでは、通常のタイトルとセルのカスタムルックの両方を使用します。
評価セルでは、 アイテムデータ( scopedSlot関数に渡され、文字列を含む受信配列を含む)と評価プロパティの値を使用して、現在の行が最高評価であるかどうかを判断します。 「はい」の場合、「最良の選択!」
そして、完成した結果:

最終的にそのようなコンポーネントが判明しました。
今は見ています。 機能を追加します。 次の記事では、機会の拡大について説明します。