ããã«ã¡ã¯ãKINTO Technologiesã°ããŒãã«éçºéšã§ããã³ããšã³ãéçºãããŠããã¯ãªã¹ã§ãã æ®æ®µããã³ããšã³ãéçºã§ã³ã³ããŒãã³ããéçºããéã¯propsãå©çšããŠå¿
èŠãªæ
å ±ãæž¡ãããšãã話ã¯ããè³ã«ãããšæããŸããAngular, React, Vue, Svelteãšãã£ãä»ãã䜿ãããŠãããã¬ãŒã ã¯ãŒã¯ã§ã¯ããããã®æžãæ¹ã§ãã®æ©èœãå®çŸããŠããŸãããã¹ãŠã®ãã¬ãŒã ã¯ãŒã¯ãèšåãããšéåžžã«é·ãèšäºã«ãªã£ãŠããŸãã®ã§ãä»åã¯ã°ããŒãã«éçºéšã§è¯ã䜿ã£ãŠããVueã«ã€ããŠè©±ããããšæããŸãã ã³ã³ããŒãã³ãã®åå©çšæ§ãèããæã«ãpropsã ãã§ã¯å®çŸãã«ããå¯èœæ§ããããŸããããã§ç»å Žããã®ãslotãšããæ©èœã§ããæ¬èšäºã¯äž¡è
ã«ã€ããŠèª¬æããå©çšäºäŸãæ¯èŒããããšæããŸãã Propsã§æ
å ±ãæž¡ã äŸãã°ãã¿ã€ãã«ãã€ããŠããããŒãã«æ
å ±ãåå©çšã§ããã³ã³ããŒãã³ããšããŠå®è£
ããå¿
èŠããããšããŸããã¿ã€ãã«ãããããŒãšããŒã¿ãæž¡ãããã«ããããã®propsãæž¡ãã°ãããããããšãããå®çŸã§ããŸãã # ã³ã³ããŒãã³ã <template> <div> <h5>{{ title }}</h5> <table> <tr> <th v-for="header in headers" :key="header">{{ header }}</th> </tr> <tr v-for="(row, i) in data" :key="i"> <td v-for="(column, j) in row" :key="`${i}-${j}`">{{ column }}</td> </tr> </table> </div> </template> <script> export default { name: 'DataTable', props: { title, headers, data }, } </script> # ã³ã³ããŒãã³ããåŒã³åºã芪 <template> <DataTable :title="title" :headers="headers" :data="data"/> </template> <script> // ã³ã³ããŒãã³ãã®importæãçç¥ããŸã export default { data() { return { title: 'Title', headers: ['C1', 'C2', 'C3', 'C4'], data: [ { c1: `R1-C1`, c2: `R1-C2`, c3: `R1-C3`, c4: `R1-C4`, }, { c1: `R2-C1`, c2: `R2-C2`, c3: `R2-C3`, c4: `R2-C4`, }, ] } }, } </script> äžèšã®ã³ãŒãã§ä»¥äžã®ããŒãã«ãäœæããããšãã§ããŸããïŒCSSã«ããç°¡åãªã¹ã¿ã€ãªã³ã°ãã€ããŠããŸãããæ¬èšäºãšé¢ä¿ãªããã岿ããŸããïŒ Propsã®å©çšã«ã€ããŠå°ãè£è¶³ãããšãVue.jsã§ã¯TypeScriptãå©çšããªããŠããç°¡åãªåãã§ãã¯ãã§ããããåŒã³åºãå
ããããã£ãããŒã¿ã«å¯ŸããŠããªããŒã·ã§ã³ãããããããããŸãã以äžãäŸã«ãªããŸããã詳ããã¯Vue.jsã® å
¬åŒããã¥ã¡ã³ã ãã確èªããŠã¿ãŠãã ãããïŒæ¬èšäºã®å
šãµã³ãã«ã³ãŒãã«ãã®ãããªèšå®ãã€ããé·ããªã£ãŠããŸãããã岿ããŸãïŒ <script> export default { props: { title: { // Stringåã®propãäºã€ä»¥äžã®åãããåŸãå Žåã¯[String, Number]ãªã©ã§æžããŸã type: String, // ãã®propã¯å¿
ãåŒã³åºãå
ããæž¡ããŠãããå¿
èŠããããŸã required: true, // propã®ããªããŒã·ã§ã³ãã§ãã¯ãBooleanãè¿ãããšã§çµæãå€å®ããŸã validator(value) { return value.startsWith('Title') } }, }, } </script> Propsã®ã¿ãå©çšããéã®åé¡ç¹ åã®æå®ãå€ã®ããªããŒã·ã§ã³ãªã©ã®æ©èœãã€ããŠããpropsã¯ç¢ºãã«äŸ¿å©ã§ãããããããããšã«ãã£ãŠã¯ç©è¶³ããªããšæããŠããŸãæããããŸããäŸãã°ãã®ãããªèŠä»¶ãèããããšãããŸãããïŒ ããŒãã«ã»ã«ã«è¡šç€ºããŠããå€ãæ¡ä»¶ã«ãã£ãŠå€ªæåã ã£ãããæäœã ã£ãããããã¹ãã®è²ãå€ããããããã«ãã ããŒãã«ã®åè¡ã«äžã€ä»¥äžã®ã¢ã¯ã·ã§ã³ãèµ·ãããã¿ã³ã衚瀺ã§ããããã«ããæ¡ä»¶ã«ãã£ãŠdisabledã§ããããã«ãã èããšæ®éã«çŽåŸã§ããããªèŠä»¶ã§ãããpropsã®ã¿ã§å®çŸããããšãããšãè€éãªã³ãŒãã«ãªããã¡ã§ãã ã»ã«ã®ã¹ã¿ã€ã«ã倿Žããã«ã¯ãå€å®ã®ããžãã¯ãpropsãšããŠã³ã³ããŒãã³ãã«æž¡ãããã«ãããããã®å€ã¯ã¹ã¿ã€ã«å€æŽãå¿
èŠãšããããŒãã³ã°ãããŒã¿ãªããžã§ã¯ãã«è¿œå ããå¿
èŠããããããŒã¿è¡ããšã«ãã¿ã³ãã€ããã«ã¯ä»¥äžã®ããã«ãã¿ã³ã®æ
å ±ãpropsãšããŠã³ã³ããŒãã³ãã«æž¡ãå¿
èŠããããŸãã äŸãã°æåã«åºãããµã³ãã«ã³ãŒãã远å å®è£
ãããšã以äžã®ãããªã³ãŒãã«ãªããŸãã <template> <div> <h5>{{ title }}</h5> <table> <tr> <th v-for="header in headers" :key="header">{{ header }}</th> </tr> <tr v-for="(row, i) in data" :key="i"> <!-- åãåã£ãã¹ã¿ã€ã«ãå€å®ãã颿°ã§ã¯ã©ã¹æ
å ±ãååŸ --> <td v-for="(value, j) in row" :class="cellStyle(value)" :key="`${i}-${j}`" > {{ value }} </td> <!-- ãã¿ã³ãããå Žåã¯ãã¿ã³ã®åãå¥éçšæ --> <td v-if="buttons.length > 0"> <button v-for="button in buttons" :class="button.class" :disabled="button.disabled(row)" @click="button.onClick(row)" :key="`${button}-${i}`" > {{ button.text }} </button> </td> </tr> </table> </div> </template> <script> export default { props: { title, headers, data, // ã»ã«ã®ã¹ã¿ã€ã«ã決ããããžãã¯ãpropsãšããŠåãåã cellStyle, // ãã¿ã³æ
å ±ãpropãšããŠåãåã buttons, }, } </script> <template> <!-- ã¯ã©ã¹æ
å ±ãè¿ã颿°ãšbuttonsã«é¢ããæ
å ±ãpropsãšããŠæž¡ã --> <DataTable :title="title" :headers="headers" :data="data" :cell-style="cellStyle()" :buttons="buttons" /> </template> <script> export default { data() { return { // ãã®ä»ã®dataæ
å ±ãçç¥ buttons: [ { text: 'ç·šé', class: 'btn-primary', disabled: (rowData) => { // ãã¿ã³ãdisabledã«ãããã©ããã®å€æããžã㯠}, onClick: (rowData) => { // ãã¿ã³ã®æŒäžåŸããžã㯠}, }, { text: 'åé€', class: 'btn-danger', disabled: (rowData) => { // ãã¿ã³ãdisabledã«ãããã©ããã®å€æããžã㯠}, onClick: (rowData) => { // ãã¿ã³ã®æŒäžåŸããžã㯠}, }, ], } }, methods: { cellStyle() { return (val) => { // å¿
èŠãªã¹ã¿ã€ã«ã¯ã©ã¹æ
å ±ãè¿ãããžã㯠} } } } </script> ãã¡ãã®ã¹ã¯ã·ã§ã¯ãã¿ã³ã®è¡šç€ºãšãšãã«ãæ¡ä»¶ã«å¿ããŠã»ã«ã®ããã¹ãã«ã¹ã¿ã€ã«ãããããã衚瀺ãããã¿ã³ãdisabledã«ããããžãã¯ãå
¥ããçµæã«ãªããŸãã ãã ãããããã«ã»ã«å
ã®htmlæ§é ãã®ãã®ãå¶åŸ¡ãããå ŽåïŒäŸïŒ <p> ã¿ã°ã <span> ã¿ã°ã <li> ã¿ã°ãªã©ãå
¥ããïŒã htmlã³ãŒããæååã®propsãšããŠåã³ã³ããŒãã³ãã«æž¡ããv-htmlã䜿ã£ãŠè¡šç€ºããå¿
èŠããããŸãã v-htmlãšããã®ã䟿å©ãªããæ¹ã§ãããhtmlã³ãŒããæååã§æ§ç¯ãããããããããã®åçãªèŠçŽ ãå
¥ãããšèªã¿ã¥ãããªã£ãŠããŸããŸãã äžèšã®è©±ããŸãšãããšãpropsã®ã¿ãå©çšããå Žå㯠åã³ã³ããŒãã³ããšããŠã©ãåãåãã ãæ·±ãæ©ãå¿
èŠããããŸãã Slotã§propsã®è¶³ããªãéšåãè£ã ããã§slotæ©èœã®åºçªã§ãã å
¬åŒããã¥ã¡ã³ã ã«ããã®æ©èœã®èª¬æããããŸãããã³ã³ããŒãã³ãã«slotæ ãäœæããåŒã³åºãå
ããæå®ããtemplateæ å
ã®htmlæ
å ±ãæž¡ãããšã«ãã£ãŠãå®è£
ãããå
容ã察象ã®slotæ ã«åœãŠã¯ããããšãã§ããŸãã äžèšã®ã€ã©ã¹ãã¯ãããŸã§ã€ã¡ãŒãžã§ãããå·ŠåŽã®ç®±ã¯propsãå©çšããã³ã³ããŒãã³ãã§ãå³åŽã®ç®±ã¯slotãå©çšããã³ã³ããŒãã³ãã§ãã Propsã®å Žåãåå
¥å£ãçããåãæ±ºãŸã£ãŠãããããå®è£
è
ããã¯ã³ã³ããŒãã³ããæ±ºããæ
å ±ããæž¡ããªãã€ã¡ãŒãžã§ãããslotã®å Žåã¯å
¥å£ãã ãã¶åºããªããããäœãã³ã³ããŒãã³ãã«æž¡ããã¯å®è£
è
ãããæ±ºå®æš©ãæã£ãŠããŸãã äŸãã°ãååã§äŸãšããŠãããããŒã¿ããŒãã«ã®å®è£
ã§slotã䜿ã£ãŠã¿ããšããŸãã <template> <div> <!-- default slot --> <slot /> <!-- tableãšããslot --> <slot name="table" /> </div> </template> <template> <DataTable> <!-- ã³ã³ããŒãã³ãã®äžã«htmlã³ãŒããæžããšãèªåçã«ã³ã³ããŒãã³ãåŽã§å®£èšãããslotã«åœãŠã¯ããŸã --> <!-- ç¹ã«templateã§å²ãŸãªããã°defaultã®slotã«åœãŠã¯ããŸã --> <h5>Title</h5> <!-- tableãšããslotã«åœãŠã¯ããŸã --> <template #table> <table> <tr> <th v-for="header in headers" :keys="header">{{ header }}</th> </tr> <tr v-for="(row, i) in data" :keys="`row-${i}`"> <td v-for="(column, j) in row" :class="{ 'font-italic': italicFont(column), 'font-weight-bold': boldFont(column) }" :key="`row-${i}-col-${j}`" > {{ column }} </td> <td> <button :disabled="editDisabled(column.c1)" @click="edit(column.c1)">ç·šé</button> <button :disabled="destroyDisabled(column.c1)" @click="click(column.c1)">åé€</button> </td> </tr> </table> </template> </DataTable> </template> <script> export default { // dataæ
å ±ãçç¥ methods: { edit(id) { // ãã®è¡ã®ããŒã¿ãç·šéããããžã㯠}, destroy(id) { // ãã®è¡ã®ããŒã¿ãåé€ããããžã㯠}, italicFont(val) { // æäœã«ãã倿ããžã㯠}, boldFont(val) { // 倪æåã«ãã倿ããžã㯠}, editDisabled(id) { // ç·šéãã¿ã³ãdisabledãã倿ããžã㯠}, destroyDisabled(id) { // åé€ãã¿ã³ãdisabledãã倿ããžã㯠} }, } </script> ãã®äŸã§ãããšãã³ã³ããŒãã³ãã«propsãæž¡ããŠããããããªããã£ããããŠèŠããŸãããäžã€åé¡ããããŸããããã¯ãå®è£
è
ã®å¥œããªããã«ãªãã§ãå®è£
ã§ããŠããŸãããšã§ããäŸãã°äžèšã®ã³ã³ããŒãã³ããå©çšãããšã芪ãã¡ã€ã«ã§ä»¥äžã®ããã«æå®ã®ã¿ã°ïŒã¿ã€ãã«ã¯h5ã¿ã°ãããŒãã«ã¯tableã¿ã°ãªã©ïŒãå©çšããé©åãªã¹ã¿ã€ã«ãã€ããã¹ããªã®ã«ãå®è£
è
ãžã®å
±æäžè¶³ããããã¯å®è£
ã®ç¥èäžè¶³ã§å¥ã®ã¿ã°ãå©çšããŠããŸãå¯èœæ§ããããŸãããããªããšãå®éã®èŠãç®ã§ã¯éãèŠããŠããŸããããããŸãããããã¹ãã®éã«åç»é¢ãµã€ãºã§åŽ©ããŠããªããå確èªããå¿
èŠããããŸãã <template> <DataTable> <!-- h5ã§ã¯ãªããh1ãå©çš --> <h1>Title</h1> <template #table> <!-- <table>, <tr>ã<th>ãå©çšãã<div>ãå©çš --> <div> <div> <div v-for="header in headers" :keys="header">{{ header }}</div> <div></div> </div> <div v-for="(row, i) in data" :keys="`row-${i}`"> <div v-for="(column, j) in row" :key="`row-${i}-col-${j}`"> {{ column }} </div> <div> <button :disabled="editDisabled(column.c1)" @click="edit(column.c1)">ç·šé</button> <button :disabled="destroyDisabled(column.c1)" @click="click(column.c1)">åé€</button> </div> </div> </div> </template> </DataTable> </template> ããŒãã«ãªã®ã«ãã¹ãŠ <div> ã¿ã°ãå©çšãããšã¯æ¥µç«¯ãªäŸãããããŸããããå¿
èŠä»¥äžãªèªç±åºŠã¯äžããªãæ¹ãç¡é£ã§ããäŒç€ŸãããŒã ã«ãã£ãŠè§£éãéããŸãããç§ã«ãšã£ãŠã®çæ³ã¯ããã¶ã€ããŒãšçžè«ããäžã§ãå¿
èŠãªéšåã ãèªç±ãäžããããšã§ããã©ã®éšåãå®è£
æã®ä»æ§ã«å¿ããŠèªç±ã«å®è£
ããŠããã£ãŠããããã©ã®éšåãå¿
ãäžã€ã®ããæ¹ã«åŸã£ãŠããããªããšãããªãããæ±ºããŠãããpropsã®å©çšããslotã䜿ãåããã¹ããšæããŸãã <template> <div> <!-- å¿
ãããã¹ãã<h5>ã«å
¥ãããã«propsãå©çš --> <h5>{{ title }}</h5> <!-- å¿
ã<table>ã¿ã°ãå©çš --> <table> <tr> <!-- headeræ
å ±ãpropsã§æž¡ãããšã§ãå¿
ã<th>ãå©çšãã --> <th v-for="header in headers" :key="header">{{ header }}</th> </tr> <!-- æž¡ãããããŒã¿ã®è¡æ°ã«å¿ããŠåçã«slotãçæ --> <!-- v-bindãå©çšããŠãåŒã³åºãå
ã®templateã«ããŒã¿ãæž¡ã --> <slot name="table-item" v-for="row in data" v-bind="row" /> </table> </div> </template> <script> export default { data() { return { title, headers, data } } } </script> <template> <!-- ã¿ã€ãã«ãšããããŒã¯propsã§æž¡ã --> <DataTable title="Title" :headers="headers" :data="data"> <!-- ã³ã³ããŒãã³ãåŽã®v-bindãããããŒã¿ãåãåã --> <template #table-item="row"> <!-- è¡ã®ããŒã¿ãåãåããè¡šç€ºæ¹æ³ãå®çŸ© --> <tr> <td v-for="(column, i) in row" :key="`col-${i}`"> {{ column }} </td> <td> <button :disabled="editDisabled(column.c1)" @click="edit(column.c1)">ç·šé</button> <button :disabled="destroyDisabled(column.c1)" @click="click(column.c1)">åé€</button> </td> </tr> </template> </DataTable> </template> ã¡ãªã¿ã«ãslotãå©çšããéã«ãã³ã³ããŒãã³ãåŽã§ this.$scopedSlots ãå©çšããããšã§ãã©ã®slotãåŒã³åºãå
ã«å©çšããããŸãã©ã®ããã«å©çšãããŠããã確èªããããšãã§ããŸãããŠãŒã¹ã±ãŒã¹ã¯æ§ã
ãããŸãããäŸãã°å©çšãããŠããslotã®äžã§ã©ããªã¿ã°ãå©çšãããŠããã調ã¹ãããšãã§ããŸããããã¯å
è¿°ããslotã®èªç±åºŠãé«ãããåé¡ã«å¯ŸããŠãäžçš®ã®ãã€ã«ããªããªããŒã·ã§ã³ããããããšãå¯èœã«ãªããŸãã <template> <DataTable title="Title" :headers="headers" :data="data"> <template #table-item="row"> <!-- <tr>ã§ã¯ãªãå Žåã¯äœãããã®æ¹æ³ã§å®è£
è
ã«ãç¥ãããããªã© --> <div> <td v-for="(column, i) in row" :key="`col-${i}`"> {{ column }} </td> </div> </template> </DataTable> </template> ãŸãšã æåŸã®ãŸãšãã§ãããVueã«ããåå©çšã³ã³ããŒãã³ãã®éçºã§ã¯propsãå©çšããã®ãäžçªç°¡åãªãã®ã®ãæ¬èšäºã«ããäºäŸã®ããã«æè»æ§ãæ¬ ããŠããŸããäžæ¹ãslotãå©çšãããšãå®è£
è
ãããèªç±ã«å®è£
ã§ããŸãããæ§ã
ãªçç±ã§ãæ³å®ããªãã£ãå®è£
æ¹æ³ãå©çšããããšã«ãã£ãŠãå質æ
ä¿ãã§ããªããªãå¯èœæ§ããããŸãã ããã§ãã³ã³ããŒãã³ãã®éçºé¢ä¿è
ã亀ããŠãããããã³ã³ããŒãã³ãã®ã©ã®éšåã«ã©ã®ã¬ãã«ã®èªç±ãäžããããæ±ºããäžãäžããŠãããèªç±åºŠã«åãããŠpropsãšslotã䜿ãåããŠéçºããã³ã³ããŒãã³ãã®å©çšè
ã«å¯ŸããŠãããã¥ã¡ã³ããªã©ãéããŠã仿§ãçè§£ããŠããã£ãã»ãããããšæããŸãã