ã¯ããã«
ä»åãVue.jsãã¿ãã(æ¬å½ã¯ãã£ã¨AWSãServerless Frameworkãªã©ããã¯ã¨ã³ãçãªãã¿ãæ¸ããããã¦ãä»äºã§ãããããã...)
æè¿ãããã³ãå´ã触ãæ©ä¼ãããã®ã§ãããã³ã³ãã¼ãã³ããã¼ã¹ã§ã®éçº(ãããããã³ã³ãã¼ãã³ãé§åéçº(CDD)ã)ãè¡ãäºãå¤ãã§ãã(ç¹ã«Reactã§ã¯å¤ãã®ãã)
ãã ãã®éãã³ã³ãã¼ãã³ããå®éã«ã¢ããªã«çµã¿è¾¼ã¾ãªãã¨ç¢ºèªãã§ããªãã®ã§(ããã¾ã§ãã³ã³ãã¼ãã³ãããªã®ã§)ãã©ããããã®ããªã...ã¨æã£ã¦ã¾ããã
ããããStorybookãã¨ãããã¼ã«ã使ãã°ãã³ã³ãã¼ãã³ãåä½ã§ã®åä½ç¢ºèªãå¯è½ã«ãªãã¾ãã
ä»åã¯ãã®ãStorybookãã«ã¤ãã¦ã®è¨äºã§ãã
ããã¨ãã
storybookã«é¢ããããã°ã¯ã»ã¨ãã©ãReactãªã®ã§ãç§ã¯Vue.jsã使ããã¨æãã¾ãã(Reactã¯ä»ã®æ¹ã®è¨äºããã£ã±ãããã¾ãã)
Storybookã«ã¤ãã¦ã®è©³ç´°ã¯ãStorybookå
¬å¼ãµã¤ã(ä¸è¨)ãåç
§ãã¦ãã ããã
https://storybook.js.org/
ã¤ã³ã¹ãã¼ã«ï¼åæè¨å®
ã¤ã³ã¹ãã¼ã«
ã«ã¼ããã©ã«ãã§ä¸è¨ã³ãã³ããæå®ããã°OKã§ãã
â»Vue.js3ã®ãµãã¼ãã¯ç¾å¨ãå®è£
ä¸ã¨ã®ãã¨ãªã®ã§ãåããªãæ©è½ãããããã
åç
§ï¼ Install Storybook (ãtroubleshootingããåç
§)
# storybookã®ã¤ã³ã¹ãã¼ã«(è¨èª(=Vue.js)ãèªåã§å¤å¥ãã) > npx sb init # æ示çã«Vue2ã§ãããã¨ãæå®ãã¦ã¤ã³ã¹ãã¼ã«ãã > npx sb init --type vue # æ示çã«Vue3ã§ãããã¨ãæå®ãã¦ã¤ã³ã¹ãã¼ã«ãã > npx sb init --type vue
ãã®å¾ãä¸è¨ã³ãã³ããå®è¡ãã¦æ£å¸¸ã«èµ·åããã°OKã
â»ç§ã®ç°å¢(Windows10 + WSL2 Ubuntu)ã§ã¯ãä¸åº¦PCãåèµ·åããªãã¨ãã¡ã§ããã®ã§ããã¾ãèµ·åããªãã¨ããå ´åãä¸åº¦PCåèµ·åããæ¹ãè¯ãããã
# ãã¡ããnpm run â yarnã§ãOK > npm run storybook
åæè¨å®
ã.storybook/main.jsããã¡ã¤ã«ãç·¨éãã¦ãstoriesãã«éçºãã©ã«ãã追å ããã
ããããªãã¨ãéçºãã©ã«ãå
ã®ã¹ãã¼ãªã¼ãã¡ã¤ã«(å¾è¿°)ãèªèãã¦ãããªãã
â»ã.storybook/main.jsããã¡ã¤ã«ã¯ãStorybookã¤ã³ã¹ãã¼ã«æã«èªåã§ä½æããã
module.exports = { "stories": [ // ããã©ã«ãã¯ãã®2ã¤ã®ã¿ "../stories/**/*.stories.mdx", "../stories/**/*.stories.@(js|jsx|ts|tsx)", // èªåã®éçºç°å¢ãã好ã¿ã§è¿½å ããã¨ä¾¿å© "../makky12/src/components/**/*.stories.mdx", "../makky12/src/components/**/*.stories.@(js|jsx|ts|tsx)", ], "addons": [ "@storybook/addon-links", "@storybook/addon-essentials" ], "framework": "@storybook/vue" }
ã¹ãã¼ãªã¼ã³ã¼ããæ¸ã
Storybookã§ã®åä½ç¢ºèªã¯ããã¹ãã¼ãªã¼ã(=ãã¹ããã¿ã¼ã³ã®ãããªãã®)ãã¹ãã¼ãªã¼ãã¡ã¤ã«ã«å®ç¾©ãããã¨ã§è¡ãã¾ãã(ã¹ãã¼ãªã¼ã«ã¤ãã¦ã®è©³ç´°ã¯ãä¸è¨å ¬å¼ãµã¤ããåç §)
- https://storybook.js.org/docs/vue/get-started/whats-a-story
- https://storybook.js.org/docs/vue/writing-stories/introduction
ä¸è¨ãµã¤ãã«ãããéããã¹ãã¼ãªã¼ã®åºæ¬ã®æµãã¯ä»¥ä¸ã®éãã§ãã
- 対象ã³ã³ãã¼ãã³ããimportãã
- 対象ã³ã³ãã¼ãã³ãã使ç¨ãããã³ãã¬ã¼ããä½æãã
- ä¸è¨ãã³ãã¬ã¼ããbindãã
- å¿ è¦ã«å¿ãã¦ãargsã«å種propsã®å¤ãè¨å®ãã
ç¾èã¯ä¸è¦ã«å¦ããã¨ãããã¨ã§ããµã³ãã«ãä½æãã¾ããã(Sample.jsã対象ã®ã³ã³ãã¼ãã³ããSample.stories.jsããã®ã¹ãã¼ãªã¼å®ç¾©ãã¡ã¤ã«ã§ã)
â»ã¹ãã¼ãªã¼ãã¡ã¤ã«åãå è¿°ã®ã.storybook/main.jsããã¡ã¤ã«ã®ãstoriesãã«è¨è¼ã®ãã¿ã¼ã³ã¨ããããã¦ããªãã¨ãStorybookã®ç»é¢ã«è¡¨ç¤ºãããªãã®ã§æ³¨æã§ãã
// Sample.js <template> <div> <input type="text" :placeholder="placeHolder" :value="defaultValue" @change="onChange" /> </div> </template> <script> export default { name:"Sample", props: { placeHolder: { type: String, required: false, default: "" }, defaultValue: { type: String, required: false, default: "" }, }, data: function () { return {} }, methods: { onChange(e) { this.$emit('onChange', e.target.value); }, }, } </script> <style> </style>
// Sample.stories.vue import Sample from './Sample.vue'; const Template = (args, { argTypes }) => ({ props: Object.keys(argTypes), components: { Sample }, template: '<Sample @onChange="onChange" v-bind="$props" />', }); export const noProps = Template.bind({}); export const withplaceHolder = Template.bind({}); withplaceHolder.args = { placeHolder: 'I am placeholder.' }; export const withBoth = Template.bind({}); withBoth.args = { placeHolder: 'I am placeholder.', defaultValue: 'I am default value.' }; export default { title: 'Example/Sample', component: Sample, };
ä¸è¨ã¹ãã¼ãªã¼ãã¡ã¤ã«ãå®ç¾©ãã¦Storybookãèµ·åããã¨ãä¸è¨ç»é¢ã表示ããã¾ãã
å·¦å´ã®ãExampleãå ã«ãStoriesã(=export defaultã®title)ã表示ããããã®ä¸ã«å®ç¾©ããåã¹ãã¼ãªã¼ã®å¤æ°åã表示ããã¦ãã¾ãã(åèªåä½ã§åºåãããã¿ããã§ãã)
â»Sample以å¤ã¯ãããã©ã«ãã§ã¤ã³ã¹ãã¼ã«ãããã¹ãã¼ãªã¼ã§ãã
åã¹ãã¼ãªã¼ã®å¤æ°åãã¯ãªãã¯ããã¨ãã¡ããã¨argsã«å¿ããpropsã®å¤ãåæ ããã¦ãããã¨ãåããã¾ãã(With Bothã¯åæå¤ãè¨å®ãã¦ããã®ã§ãplaceholderã¯è¡¨ç¤ºããã¾ããã)
ã¾ããç»é¢ä¸é¨ã®ãControlsãã¿ãå ã®ãPropsãã«åã¹ãã¼ãªã¼ã§æ¸¡ããpropsã表示ããã¦ãããããã®å¤ãå¤æ´ãããã¨ã§propsã®å¤ãç´æ¥å¤æ´ãããã¨ãã§ãã¾ãã
Actionsã«ã¤ãã¦
ã¾ãStorybookã«ã¯ãActionsãã¨ãããã®ãããããããç¨ãããã¨ã§ãemitããã¤ãã³ãã®ç¢ºèªãã§ãã¾ãã
emitã確èªããå ´åãç¹å¥ãªãã¨ã¯å¿ è¦ãªããå è¿°ã®ãµã³ãã«ã½ã¼ã¹ã®ããã«ãã³ãã¬ã¼ãã«é常ã®Vue.jsã®emitã¨åãããã«å®ç¾©ãããã¨ã§ãã¤ãã³ãã®çºç«ã確èªã§ãã¾ãã
ãã®å ´åãç»é¢ä¸é¨ã®ãActionsãã¿ãã«emité¢æ°ã«æ¸¡ãããå¤ã表示ããã¾ãã(ãã³ãã¬ã¼ãã®ã@emitå¤æ°å="XXX"ãã®XXXã®ç®æãããActionsãã¿ãã®ãã¼ã¨ãã¦è¡¨ç¤ºããã¾ã)
â»è©³ç´°ã¯ãããã©ã«ãã§ã¤ã³ã¹ãã¼ã«ãããã¹ãã¼ãªã¼ã®ãButtonãã®ã½ã¼ã¹ãè¦ãã¨ãããã¾ãã
ã¡ãªã¿ã«ããã¡ãã®ãã¼ã¸ã«è¨è¼ã®ããæ¹ã§ããemitã確èªã§ãã¾ãã(ãã¡ãã¯Reactãªã©ã§ãè¡ãããæ¹)
ãã ããã¡ãã®å ´åã§ããé常ã®Vue.jsã®emitã¨åãå®ç¾©ã¯å¿
è¦ã§ãã
ãã¡ãã®æ¹æ³ã®å ´åãä¸è¨ãå¿ è¦ã«ãªãã¾ãã(ãã ãsb initã³ãã³ãã§ã¤ã³ã¹ãã¼ã«ããã°ãæåããä¸è¨ãå®äºããç¶æ ã«ãªã£ã¦ãã¾ãã)
- ã@storybook/addon-essentialsãã®ã¤ã³ã¹ãã¼ã«
- ã.storybook/main.jsããã¡ã¤ã«ã®addonsã«ã@storybook/addon-essentialsãã追å ãã
- å è¿°ã®ã.storybook/main.jsãã½ã¼ã¹ãåç §
åç §ï¼https://storybook.js.org/docs/vue/essentials/introduction
// export defaultã®argTypesã§æå®ããæ¹æ³(å ¨ã¹ãã¼ãªã¼ã«é©ç¨) export default { title: 'Example/Sample', component: Sample, argTypes: { onChange: { action: 'changed' } }, }; // actionã@storybook/addon-essentialsããã¤ã³ãã¼ãããæ¹æ³ // (ã¹ãã¼ãªã¼åå¥ã«é©ç¨å¯è½) import { action } from '@storybook/addon-actions'; export const withBoth = Template.bind({}); withBoth.args = { placeHolder: 'I am placeholder.', defaultValue: 'I am default value.', methods: { onChange: action('change'), }, };
ã¾ã¨ã
以ä¸ãæ¥ã足ã§ããããStorybookã®ä½¿ãæ¹ã§ããã
èªåãæè¿Storybookã®ãã¨ãç¥ã£ã...ã¨ããããã¾ãããã³ãå´ã®ãã¹ãã確èªã«ã¤ãã¦ã¯ç¥ããªãã£ãã®ã§ã便å©ã ãªãã¨æãã¾ããã
ã¦ãããã¤ã¦é¢ãã£ãVue.jsã®æ¥åããã£ãæã«ãããç¥ã£ã¦ããã°ãªã...ã¨æã£ãããã¾ãã
ã§ããã£ã±ããæ¬å½ã¯ãã£ã¨AWSãServerless Frameworkãªã©ã®æè¡ã«æºãããããªã...
ããã§ã¯ãè¯ããå¹´ãï¼