ããï½ï½ãããããFlash ã Silverlight ã¿ãããªãã©ã¦ã¶ã¼ãã©ã°ã¤ã³ç³»ã®ãªããã¯ã©ã¤ã¢ã³ãã¢ããªã±ã¼ã·ã§ã³ã®ãã©ãããã©ã¼ã 㨠HTML 5 ãè¦æ¨©ãäºã£ã¦ãæä»£ãããã¾ãããç§ã¯ãã©ã¦ã¶ã¼ãã©ã°ã¤ã³å¯ãã®äººã§ãDataGrid ã³ã³ããã¼ã«ãããã ãã§ãã©ã°ã¤ã³ç³»ã®ã»ã使ãããã£ã¦æã£ã¦ã¾ããã
ããããã£ããã¨ã¯
- 表形å¼ã§ãã¼ã¿ã表示ããã
- 表ã縦横ã¹ã¯ãã¼ã«ããã
- ã¹ã¯ãã¼ã«ãã¦ãåºå®åãåºå®è¡ã¯ã¹ã¯ãã¼ã«ããªãã§æ¬²ãã
JavaScript ã§é å¼µããã¨ã§å½æã§ãã§ãã¦ã¾ããããçµæ§ããã©ãã£ããéãã ã£ããã¨ä½ãã¨åé¡ããããã¡ã ã£ãæ°ãããã®ã§ä¾ãã°
<DataGrid ItemsSource="{Binding People}"> <DataGrid.Columns> <DataGridTextColumn Header="ID" Binding="{Binding ID}" /> <DataGridTextColumn Header="åå" Binding="{Binding Name}" /> </DataGrid.Columns> </DataGrid>
ã¿ããã«æ¸ãã ãã§å®å®ãããã¼ã¿ã°ãªãããåºã¦ãããã®ã§å°ãªãã¨ã社å ã·ã¹ãã ã§ä½¿ãããªããã£ã¡ã®ã»ããæ¥½ãªã®ã§ã¯â¦ã¨æã£ã¦ã¾ããã
HTML 5 ãè¦æ¨©ãæ¡ã£ã¦ãã©ã°ã¤ã³ç³»ãæ·æ±°ããã¦ãããããªããªãããããã®å®è£ ããã®ããã©ããããã ãªãã¨æã£ã¦ã¦ãèªåããããªãã©ã£ãããè²·ããã£ã¦æã£ã¦ãã®ã§ããå æ¥åãã¦ã¿ãã¨â¦
cssã®gridã¨position:stickyã ãã§ã»ã¼ããã¾ãã髿©è½ãªã©ã¤ãã©ãªãããã¾ãããReactã¨ã使ã£ãSPAåæãªããèªåã§å®è£ ããã»ããæ¥½ã§ãã
— æçåº/HAYASHI Masahiro (@masaha03) July 20, 2019
ã¾ãã§ããã
ãã£ã¦ã¿ãã
ã¨ãããã¨ã§ãVue.js ã®ããã¸ã§ã¯ãã vue cli ã§ããã£ã¨ä½ãã¾ãããApp.vue ã«å ¨é¨è©°ãè¾¼ãã·ã³ãã«æ§æã§ä½ã£ã¦ããã¾ãã ã¡ãã£ã¨ä»¶æ°å¤ãã®ãã¼ã¿ä½ãã®ãã ããã£ãã®ã§ãmanipula ã¨ãã LINQ ãå®è£ ãã¦ãã¨ããã©ã¤ãã©ãªãå°å ¥ãã¾ããã
ã¨ãããã¨ã§ä»¥ä¸ã®ã³ãã³ãã§ããã£ã¨ãã
npm i manipula
filter 㨠map 㨠reduce ã§çµæ§ãªã±ã¼ã¹ãã«ãã¼ã§ãããã©ãè¾¼ã¿å ¥ã£ããã¨ãããã¨ãã¨ãçã©ããã¦ããã ãããªãã
ã¨ãããã¨ã§ App.vue ã以ä¸ã®ããã«å¤æ´ãã¦ãããããã®å¤§ããã®ãã¼ãã«ãåºãã¾ããã
<template> <div id="app"> <h1 class="title">ãã¼ãã«ã¹ã¯ãã¼ã«ãã¹ã</h1> <div class="table-scroll-host"> <table> <thead> <tr> <th>ID</th> <th>Name</th> <th>Comment1</th> <th>Comment2</th> <th>Comment3</th> <th>Comment4</th> <th>Comment5</th> <th>Comment6</th> <th>Comment7</th> <th>Comment8</th> <th>Comment9</th> <th>Comment10</th> </tr> </thead> <tbody> <tr v-for="x in people" :key="x.id"> <td>{{ x.id }}</td> <td>{{ x.name }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> </tr> </tbody> </table> </div> </div> </template> <script lang="ts"> import Vue from 'vue'; import Manipula from 'manipula'; class Person { constructor(public id: string, public name: string, public comment: string) {} } export default Vue.extend({ name: 'app', data() { return { people: Manipula.range(1, 1000) // 1000 ä»¶ã®ãã¼ã¿ä½æ .select( (x) => new Person( x.toString(), `Tanaka taro ${x}`, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ), ) .toArray(), }; }, }); </script> <style> #app { height: 100%; display: grid; grid-template-rows: auto 1fr; grid-template-columns: 100%; grid-template-areas: "title" "content"; } .title { grid-area: title; } .table-scroll-host { grid-area: content; } </style>
The table ã¿ã°ï¼ï¼ã£ã¦æãã§ããã
ã¹ã¯ãã¼ã«ãã¤ããã
ããã¯ç°¡åãtable ã¿ã°ãè¦ã£ã¦ã div ã¿ã°ï¼ä»å㯠class="table-scroll-host" ã®ãã¤) ã«é«ããæå®ãã¦ãªã¼ãã¼ããã¼ãã¹ã¯ãã¼ã«ã«ããã ãã
.table-scroll-host { grid-area: content; overflow: scroll; }
ã¹ã¯ãã¼ã«ãã¼ãã¤ãã¾ãããã¡ãã£ã¨ã¹ã¯ãã¼ã«ãããã¨ãããã¼è¡ã¨ããæ²ããã¹ã¯ãã¼ã«ã¢ã¦ããã¦ããã®ããããã¾ãã
ãããã¼è¡ãåºå®ããã
th ã¿ã°ã®ã¹ã¿ã¤ã«ã§ display ãsticky ã«è¨å®ãã¾ãããããªã®åºæ¥ã¦ããã§ãããç¥ããªãã£ãã
ã¨ãããã¨ã§ display ã sticky ã«ã㦠top ã 0 ã«ãã¾ãã ä»ã®ã¾ã¾ã 㨠th ã®èæ¯ãéæãªã®ã§ã¹ã¯ãã¼ã«ããã¨ãã«è£å´ãéãã¦ãã£ãæªãã®ã§è²ãã¤ãã¾ããã
table th { position: sticky; top: 0; background-color: black; color: white; }
ããã£ã¨ãããã¼è¡åºå®ããã¾ããã
ãããã¼ååºå®ãããã
æ¬¡ã¯æ¨ªã¹ã¯ãã¼ã«ããã¨ãã« ID åã¯æ®ãããã«ãããã¨æãã¾ãã
ã¨ãããã¨ã§æåã® th 㨠td ã«å¯¾ã㦠left 0 ã§ position ã sticky ã«ãã¦åºå®ãã¾ããããã¦ã¹ã¯ãã¼ã«æã«ä»ã®ã»ã«ãä¸ã«éãªã£ããããªãããã« z-index ãæå®ãã¦ããã¾ãã th ã¯ä¸ã¹ã¯ãã¼ã«æã«ä¸ã«ãã td ãããä¸ã«ãªãã¨ãããªãã®ã§ z-index 㯠2 ã«ãã¦ã¾ãã
æå¾ã« td ãããã©ã«ãã§èæ¯éæã§ãã¹ã¯ãã¼ã«æã«ã»ã«ãéãªãã¨æ®å¿µãªè¦ãç®ã«ãªãã®ã§ãã¨ããããç½ã§å¡ã£ã¦ããã¾ãã
table th:nth-child(1) { position: sticky; left: 0; z-index: 2; } table td:nth-child(1) { position: sticky; left: 0; z-index: 1; background-color: white; }
ããã§åããã¨â¦
ã°ã£ã¡ãï¼ï¼
å é 2 åãåºå®åã«ããã
1 åã¨ããªããããã§ããã®ã§ããè¤æ°åãªãã©ããªãã ããï¼left: 0;
ã 2 åç®ã«æå®ãã㨠1 åç®ã 2 åç®ãå·¦ç«¯ã§æ¢ã¾ãã®ã§ã¡ãã£ã¨æ®å¿µãªæãã«ãªãã¾ããã¨ãããã¨ã§ã2 åã¾ã¨ãã¦åºå®åã«ãããªãåå¹
ãæå®ããæãããªã
å³å¯ãªå¹ è¨ç®ã¨ãããã¨ãªãã¨ãã¼ãã¼ãéªéãªã®ã§é ãã¦â¦ååã®æå°å¹ ãæå®ãã¦â¦ãstyle ã¯ãããªæãã«ãªãã¾ããã
#app { height: 100%; display: grid; grid-template-rows: auto 1fr; grid-template-columns: 100%; grid-template-areas: "title" "content"; } .title { grid-area: title; } .table-scroll-host { grid-area: content; overflow: scroll; } table th { position: sticky; top: 0; background-color: black; color: white; } table { width: auto; min-width: 100%; table-layout: fixed; border-collapse: collapse; } table td, th { min-width: 100px; } table th:nth-child(1) { position: sticky; left: 0; z-index: 2; width: 100px; } table td:nth-child(1) { position: sticky; left: 0; z-index: 1; background-color: white; width: 100px; } table th:nth-child(2) { position: sticky; left: 100px; z-index: 2; width: 100px; } table td:nth-child(2) { position: sticky; left: 100px; z-index: 1; background-color: white; width: 100px; }
å®è¡ããã¨â¦
ããæãã«åºå®åãã¿ã®ã¹ã¯ãã¼ã«ãã¦ããã¾ããã
ã¾ã¨ã
ã¨ãããã¨ã§ãæçµç㪠App.vue
ã¯ä»¥ä¸ã®ãããªæãã«ãªãã¾ããã
<template> <div id="app"> <h1 class="title">ãã¼ãã«ã¹ã¯ãã¼ã«ãã¹ã</h1> <div class="table-scroll-host"> <table> <thead> <tr> <th>ID</th> <th>Name</th> <th>Comment1</th> <th>Comment2</th> <th>Comment3</th> <th>Comment4</th> <th>Comment5</th> <th>Comment6</th> <th>Comment7</th> <th>Comment8</th> <th>Comment9</th> <th>Comment10</th> </tr> </thead> <tbody> <tr v-for="x in people" :key="x.id"> <td>{{ x.id }}</td> <td>{{ x.name }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> <td>{{ x.comment }}</td> </tr> </tbody> </table> </div> </div> </template> <script lang="ts"> import Vue from 'vue'; import Manipula from 'manipula'; class Person { constructor(public id: string, public name: string, public comment: string) {} } export default Vue.extend({ name: 'app', data() { return { people: Manipula.range(1, 1000) // 1000 ä»¶ã®ãã¼ã¿ä½æ .select( (x) => new Person( x.toString(), `Tanaka taro ${x}`, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ), ) .toArray(), }; }, }); </script> <style> #app { height: 100%; display: grid; grid-template-rows: auto 1fr; grid-template-columns: 100%; grid-template-areas: "title" "content"; } .title { grid-area: title; } .table-scroll-host { grid-area: content; overflow: scroll; } table th { position: sticky; top: 0; background-color: black; color: white; } table { width: auto; min-width: 100%; table-layout: fixed; border-collapse: collapse; } table td, th { min-width: 100px; } table th:nth-child(1) { position: sticky; left: 0; z-index: 2; width: 100px; } table td:nth-child(1) { position: sticky; left: 0; z-index: 1; background-color: white; width: 100px; } table th:nth-child(2) { position: sticky; left: 100px; z-index: 2; width: 100px; } table td:nth-child(2) { position: sticky; left: 100px; z-index: 1; background-color: white; width: 100px; } </style>
HTML / CSS ãé²åãã¦ããªãâ¦ã