├── public ├── favicon.ico └── images │ ├── item1.jpg │ ├── item2.jpg │ ├── item3.jpg │ ├── item4.jpg │ └── logo.svg ├── docs ├── images │ ├── sample.png │ ├── vscode.png │ ├── vite-app.png │ ├── favicon-32.png │ ├── v_for_result1.png │ └── v_for_result2.png ├── .gitignore ├── public │ └── vue3-lab-handson-images.zip ├── .vitepress │ ├── theme │ │ └── index.ts │ ├── components │ │ └── PlusOne.vue │ └── config.ts ├── package.json ├── overview.md ├── index.md ├── setup.md ├── create.md ├── v-if.md ├── rendering.md ├── v-for.md ├── methods.md ├── event.md ├── component.md ├── slot.md └── package-lock.json ├── .prettierrc.js ├── src ├── main.js ├── components │ └── Card.vue └── App.vue ├── examples ├── event │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── slot │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ ├── components │ │ │ └── Card.vue │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── v-for │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── v-if │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── methods │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── component │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ ├── components │ │ │ └── Card.vue │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── overview │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── item1.jpg │ │ │ ├── item2.jpg │ │ │ ├── item3.jpg │ │ │ ├── item4.jpg │ │ │ └── logo.svg │ ├── src │ │ ├── main.js │ │ ├── assets │ │ │ ├── logo.svg │ │ │ ├── main.css │ │ │ └── base.css │ │ ├── components │ │ │ ├── icons │ │ │ │ ├── IconSupport.vue │ │ │ │ ├── IconTooling.vue │ │ │ │ ├── IconCommunity.vue │ │ │ │ ├── IconDocumentation.vue │ │ │ │ └── IconEcosystem.vue │ │ │ ├── HelloWorld.vue │ │ │ ├── WelcomeItem.vue │ │ │ └── TheWelcome.vue │ │ └── App.vue │ ├── vite.config.js │ ├── package.json │ ├── style.css │ └── index.html └── rendering │ ├── public │ ├── favicon.ico │ └── images │ │ ├── item1.jpg │ │ ├── item2.jpg │ │ ├── item3.jpg │ │ ├── item4.jpg │ │ └── logo.svg │ ├── src │ ├── main.js │ └── App.vue │ ├── vite.config.js │ ├── package.json │ └── index.html ├── .vscode ├── extensions.json └── settings.json ├── .editorconfig ├── .gitignore ├── .textlintrc ├── vite.config.js ├── index.html ├── .github └── workflows │ ├── textlint.yaml │ └── vitepress.yml ├── .eslintrc.cjs ├── LICENSE ├── package.json ├── README.md └── GUIDE.md /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /docs/images/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/images/sample.png -------------------------------------------------------------------------------- /docs/images/vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/images/vscode.png -------------------------------------------------------------------------------- /public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/public/images/item1.jpg -------------------------------------------------------------------------------- /public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/public/images/item2.jpg -------------------------------------------------------------------------------- /public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/public/images/item3.jpg -------------------------------------------------------------------------------- /public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/public/images/item4.jpg -------------------------------------------------------------------------------- /docs/images/vite-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/images/vite-app.png -------------------------------------------------------------------------------- /docs/images/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/images/favicon-32.png -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | semi: false, 4 | trailingComma: 'none' 5 | } 6 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | 4 | # vitepress build output 5 | .vitepress/dist 6 | .vitepress/cache 7 | -------------------------------------------------------------------------------- /docs/images/v_for_result1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/images/v_for_result1.png -------------------------------------------------------------------------------- /docs/images/v_for_result2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/images/v_for_result2.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/event/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/event/public/favicon.ico -------------------------------------------------------------------------------- /examples/slot/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/slot/public/favicon.ico -------------------------------------------------------------------------------- /examples/v-for/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-for/public/favicon.ico -------------------------------------------------------------------------------- /examples/v-if/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-if/public/favicon.ico -------------------------------------------------------------------------------- /examples/methods/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/methods/public/favicon.ico -------------------------------------------------------------------------------- /examples/component/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/component/public/favicon.ico -------------------------------------------------------------------------------- /examples/event/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/event/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/event/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/event/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/event/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/event/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/event/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/event/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/event/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/overview/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/overview/public/favicon.ico -------------------------------------------------------------------------------- /examples/rendering/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/rendering/public/favicon.ico -------------------------------------------------------------------------------- /examples/slot/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/slot/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/slot/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/slot/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/slot/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/slot/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/slot/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/slot/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/slot/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/v-for/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-for/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/v-for/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-for/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/v-for/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-for/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/v-for/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-for/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/v-for/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/v-if/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-if/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/v-if/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-if/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/v-if/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-if/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/v-if/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/v-if/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/v-if/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /docs/public/vue3-lab-handson-images.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/docs/public/vue3-lab-handson-images.zip -------------------------------------------------------------------------------- /examples/component/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/methods/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/methods/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/methods/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/methods/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/methods/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/methods/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/methods/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/methods/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/methods/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/rendering/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /examples/component/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/component/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/component/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/component/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/component/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/component/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/component/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/component/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/overview/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/overview/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/overview/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/overview/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/overview/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/overview/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/overview/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/overview/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/rendering/public/images/item1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/rendering/public/images/item1.jpg -------------------------------------------------------------------------------- /examples/rendering/public/images/item2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/rendering/public/images/item2.jpg -------------------------------------------------------------------------------- /examples/rendering/public/images/item3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/rendering/public/images/item3.jpg -------------------------------------------------------------------------------- /examples/rendering/public/images/item4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-jp/handson-vue3/HEAD/examples/rendering/public/images/item4.jpg -------------------------------------------------------------------------------- /examples/overview/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | import './assets/main.css' 5 | 6 | createApp(App).mount('#app') 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "editorconfig.editorconfig", 4 | "dbaeumer.vscode-eslint", 5 | "esbenp.prettier-vscode", 6 | "vue.vscode-typescript-vue-plugin", 7 | "vue.volar" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": true 4 | }, 5 | "editor.defaultFormatter": "esbenp.prettier-vscode", 6 | "editor.formatOnSave": true, 7 | "editor.formatOnSaveMode": "modifications" 8 | } 9 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import Theme from 'vitepress/theme' 2 | import PlusOne from '../components/PlusOne.vue' 3 | 4 | export default { 5 | ...Theme, 6 | 7 | enhanceApp({ app }) { 8 | app.component('PlusOne', PlusOne) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /examples/overview/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /docs/dist 5 | 6 | 7 | # local env files 8 | .env.local 9 | .env.*.local 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /examples/overview/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.textlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "filters": { 3 | "allowlist": { 4 | "allow": [ 5 | "/<< 2 | 3 | 4 | 5 | 6 | 7 | handson-vue3-examples 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/rendering/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | handson-vue3-examples 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "handson-vue3-examples-docs", 3 | "version": "2.1.0", 4 | "description": "", 5 | "main": "index.ts", 6 | "scripts": { 7 | "dev": "vitepress dev .", 8 | "build": "vitepress build .", 9 | "preview": "vitepress preview ." 10 | }, 11 | "author": "Vue.js 日本ユーザーグループ", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "vitepress": "^1.0.0-beta.5", 15 | "vue": "^3.3.4" 16 | }, 17 | "volta": { 18 | "node": "18.16.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/textlint.yaml: -------------------------------------------------------------------------------- 1 | name: textlint 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | env: 12 | NODE_VERSION: '16.x' 13 | 14 | jobs: 15 | textlint: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | - uses: actions/setup-node@v2 21 | with: 22 | node-version: ${{ env.NODE_VERSION }} 23 | cache: npm 24 | - name: Restore Packages 25 | run: npm ci 26 | - name: Run textlint 27 | run: npm run textlint:docs 28 | -------------------------------------------------------------------------------- /examples/slot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | handson-vue3-examples 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/v-if/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | handson-vue3-examples 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/component/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | handson-vue3-examples 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/event/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | handson-vue3-examples 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/methods/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | handson-vue3-examples 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/v-for/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | handson-vue3-examples 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/overview/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import "./base.css"; 2 | 3 | #app { 4 | max-width: 1280px; 5 | margin: 0 auto; 6 | padding: 2rem; 7 | 8 | font-weight: normal; 9 | } 10 | 11 | a, 12 | .green { 13 | text-decoration: none; 14 | color: hsla(160, 100%, 37%, 1); 15 | transition: 0.4s; 16 | } 17 | 18 | @media (hover: hover) { 19 | a:hover { 20 | background-color: hsla(160, 100%, 37%, 0.2); 21 | } 22 | } 23 | 24 | @media (min-width: 1024px) { 25 | body { 26 | display: flex; 27 | place-items: center; 28 | } 29 | 30 | #app { 31 | display: grid; 32 | grid-template-columns: 1fr 1fr; 33 | padding: 0 2rem; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | require('@rushstack/eslint-patch/modern-module-resolution') 2 | 3 | module.exports = { 4 | root: true, 5 | env: { 6 | node: true, 7 | 'vue/setup-compiler-macros': true 8 | }, 9 | extends: [ 10 | 'plugin:vue/vue3-recommended', 11 | 'eslint:recommended', 12 | '@vue/eslint-config-prettier' 13 | ], 14 | rules: { 15 | 'vue/html-closing-bracket-newline': [ 16 | 'error', 17 | { 18 | singleline: 'never', 19 | multiline: 'never' 20 | } 21 | ], 22 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 23 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 24 | 'prettier/prettier': 'off' // eslint-plugin-prettierの部分だけoffにする 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/overview/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 44 | -------------------------------------------------------------------------------- /public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/event/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/slot/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/v-for/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/v-if/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/component/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/methods/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/overview/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/rendering/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/overview/src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /examples/overview/src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /examples/overview/src/App.vue: -------------------------------------------------------------------------------- 1 | // region script 2 | 6 | // endregion script 7 | 8 | // region template 9 | 22 | // endregion template 23 | 24 | // region style 25 | 53 | // endregion style 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Vue.js Japan User Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/.vitepress/components/PlusOne.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 22 | 23 | 56 | -------------------------------------------------------------------------------- /examples/overview/src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/components/Card.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 41 | 42 | 72 | -------------------------------------------------------------------------------- /examples/slot/src/components/Card.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 41 | 42 | 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "handson-vue3-examples", 3 | "version": "1.1.1", 4 | "scripts": { 5 | "dev": "vite", 6 | "dev:methods": "npm run dev -w=methods", 7 | "dev:rendering": "npm run dev -w=rendering", 8 | "dev:event": "npm run dev -w=event", 9 | "dev:overview": "npm run dev -w=overview", 10 | "dev:v-for": "npm run dev -w=v-for", 11 | "dev:v-if": "npm run dev -w=v-if", 12 | "dev:component": "npm run dev -w=component", 13 | "dev:slot": "npm run dev -w=slot", 14 | "build": "vite build", 15 | "preview": "vite preview --port 4173", 16 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore", 17 | "textlint": "textlint --format pretty-error", 18 | "textlint:docs": "textlint --format pretty-error docs/**" 19 | }, 20 | "dependencies": { 21 | "vue": "^3.2.37" 22 | }, 23 | "devDependencies": { 24 | "@rushstack/eslint-patch": "1.1.0", 25 | "@vitejs/plugin-vue": "^3.0.1", 26 | "@vue/eslint-config-prettier": "7.0.0", 27 | "eslint": "8.5.0", 28 | "eslint-plugin-vue": "8.4.1", 29 | "prettier": "2.5.1", 30 | "textlint": "12.1.0", 31 | "textlint-filter-rule-allowlist": "4.0.0", 32 | "textlint-rule-preset-vuejs-jp": "github:vuejs-jp/textlint-rule-preset-vuejs-jp", 33 | "vite": "^3.0.1" 34 | }, 35 | "workspaces": [ 36 | "examples/*" 37 | ], 38 | "browserslist": [ 39 | "> 1%", 40 | "last 2 versions", 41 | "not dead", 42 | "not ie 11" 43 | ], 44 | "volta": { 45 | "node": "18.6.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/component/src/components/Card.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 46 | 47 | 77 | -------------------------------------------------------------------------------- /docs/.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress' 2 | 3 | export default defineConfig({ 4 | lang: 'ja-JP', 5 | title: 'Vue3 Hands-on', 6 | description: 'Vue.js-jp Vue3 Hands-on', 7 | head: [['link', { rel: 'icon', href: '/images/favicon-32.png' }]], 8 | themeConfig: { 9 | siteTitle: 'Vue3 ハンズオン', 10 | sidebar: [ 11 | { 12 | text: '準備編', 13 | items: [ 14 | { 15 | text: '環境構築', 16 | link: '/setup' 17 | }, 18 | { 19 | text: 'プロジェクトの作成', 20 | link: '/create' 21 | } 22 | ] 23 | }, 24 | { 25 | text: '本編', 26 | items: [ 27 | { 28 | text: 'ハンズオンの概要', 29 | link: '/overview' 30 | }, 31 | { 32 | text: 'data を定義し、商品をレンダリングする', 33 | link: '/rendering' 34 | }, 35 | { 36 | text: 'v-for で商品を複数表示する', 37 | link: '/v-for' 38 | }, 39 | { 40 | text: 'v-if で表示・非表示を切り替える', 41 | link: '/v-if' 42 | }, 43 | { 44 | text: '関数で価格にカンマを入れる', 45 | link: '/methods' 46 | }, 47 | { 48 | text: '@click で商品を選択する', 49 | link: '/event' 50 | }, 51 | { 52 | text: '商品をコンポーネント化する', 53 | link: '/component' 54 | }, 55 | { 56 | text: 'コンポーネントにスロットを使用する', 57 | link: '/slot' 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | }) 64 | -------------------------------------------------------------------------------- /examples/overview/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | margin: 0; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | #app { 9 | width: 90%; 10 | margin: 0 5%; 11 | text-align: center; 12 | color: #242424; 13 | } 14 | 15 | .header { 16 | display: flex; 17 | align-content: center; 18 | align-items: center; 19 | margin-top: 40px; 20 | margin-bottom: 40px; 21 | } 22 | 23 | .header > img { 24 | width: 100px; 25 | height: 100px; 26 | margin-right: 20px; 27 | } 28 | 29 | .header > h1 { 30 | font-size: 80px; 31 | font-weight: bold; 32 | line-height: 80px; 33 | margin-top: 0; 34 | margin-bottom: 0; 35 | } 36 | 37 | .main { 38 | display: grid; 39 | grid-template-columns: 3fr 3fr 3fr 3fr; 40 | column-gap: 24px; 41 | row-gap: 24px; 42 | } 43 | 44 | .item { 45 | padding: 10px; 46 | cursor: pointer; 47 | } 48 | 49 | .item:hover { 50 | transition: 0.2s transform ease-out; 51 | transform: scale(1.05); 52 | } 53 | 54 | .item > div.thumbnail > img { 55 | width: 100%; 56 | height: calc(100%); 57 | object-fit: cover; 58 | } 59 | 60 | .item > div.description { 61 | text-align: left; 62 | margin-top: 20px; 63 | } 64 | 65 | .item > div.description > p { 66 | margin-top: 0px; 67 | margin-bottom: 0px; 68 | font-size: 18px; 69 | line-height: 25px; 70 | } 71 | 72 | .item > div.description > span { 73 | display: block; 74 | margin-top: 10px; 75 | font-size: 20px; 76 | } 77 | 78 | .item > div.description > span > .price { 79 | font-size: 28px; 80 | font-weight: bold; 81 | } 82 | 83 | .selected-item { 84 | background: #e3f2fd; 85 | } 86 | -------------------------------------------------------------------------------- /examples/overview/src/components/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue.js 3 ハンズオン 2 | 3 | [![MIT License](https://img.shields.io/apm/l/atomic-design-ui.svg?)](https://github.com/tterb/atomic-design-ui/blob/master/LICENSEs) 4 | 5 | Vue.js 3 ハンズオンへようこそ😀 このハンズオンは、初めて Vue.js に触れる人がスムーズに学習できるように作られた学習用教材です。この教材は、以下の2通りの方法でご利用いただけます。 6 | 7 | ## ✏利用方法 8 | ### 1. Vue.js 日本ユーザーグループの公式ハンズオンに参加する 9 | 本ハンズオンを作成した [Vue.js 日本ユーザーグループ](https://vuejs-jp.org/) では、定期的にこの教材を使ったハンズオンイベントの開催を予定しています。ハンズオンイベントは誰でも自由に参加できます。イベントの予定は [connpass](https://vuejs-meetup.connpass.com/event/) に掲載していますので、ぜひチェックしてください。 10 | 11 | ### 2. 自由に利用する 12 | 本ハンズオンの文章、ソースコードを含むあらゆる内容は、自由にご利用いただけます。個人の学習や、グループ・会社での勉強会、もくもく会、セミナーなど、あらゆる用途にご活用ください。 13 | 14 | ## 💪コントリビューター 15 | 誤りやよりよい改善を見つけた方は、[Issues](https://github.com/vuejs-jp/handson-vue3-examples/issues) または [Pull requests](https://github.com/vuejs-jp/handson-vue3-examples/pulls) を作成してください。 16 | 17 | - [MIYAKE Kazuyuki](https://github.com/k-miyake) 18 | - [NAKATA Kazuhiro](https://github.com/nalpan) 19 | - [ISHIBASHI Yuuki](https://github.com/YuukiIshibashi) 20 | - [happylifetaka](https://github.com/happylifetaka) 21 | - [OKI Yoshiya](https://github.com/448jp) 22 | - [KAWAGUCHI Kazuya](https://github.com/kazupon) 23 | - Photo by Tyler Nix, matthew reyes, Amy Flak, Elena Rabkina on Unsplash 24 | 25 | ## ©ライセンス 26 | [MIT](https://opensource.org/licenses/MIT) 27 | -------------------------------------------------------------------------------- /.github/workflows/vitepress.yml: -------------------------------------------------------------------------------- 1 | name: VitePress CI/CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - '.github/workflows/vitepress.yml' 9 | - 'docs/**' 10 | pull_request: 11 | branches: 12 | - main 13 | paths: 14 | - '.github/workflows/vitepress.yml' 15 | - 'docs/**' 16 | workflow_dispatch: 17 | 18 | permissions: 19 | pages: write 20 | id-token: write 21 | 22 | concurrency: 23 | group: "pages" 24 | cancel-in-progress: false 25 | 26 | jobs: 27 | build: 28 | if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed') 29 | runs-on: ubuntu-latest 30 | defaults: 31 | run: 32 | working-directory: docs 33 | steps: 34 | - uses: actions/checkout@v3 35 | - name: Use Node.js 36 | uses: actions/setup-node@v3 37 | with: 38 | node-version: '18.x' 39 | cache: 'npm' 40 | cache-dependency-path: docs/package-lock.json 41 | - run: npm ci 42 | - run: npm run build --if-present 43 | - run: echo 'handson.vuejs-jp.org' > CNAME 44 | working-directory: docs/.vitepress/dist 45 | - uses: actions/upload-artifact@v3 46 | with: 47 | name: dist 48 | path: docs/.vitepress/dist 49 | 50 | deploy: 51 | if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' # PR 時はデプロイを実行しない 52 | runs-on: ubuntu-latest 53 | needs: build 54 | 55 | environment: 56 | name: github-pages 57 | url: ${{ steps.deployment.outputs.page_url }} 58 | 59 | steps: 60 | - uses: actions/download-artifact@v3 61 | with: 62 | name: dist 63 | - uses: actions/upload-pages-artifact@v1 64 | with: 65 | path: . 66 | - name: Deploy to GitHub Pages 67 | id: deployment 68 | uses: actions/deploy-pages@v1 69 | -------------------------------------------------------------------------------- /examples/overview/src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /docs/overview.md: -------------------------------------------------------------------------------- 1 | # ハンズオンの概要 2 | 3 | ## 本章の概要とゴール 4 | 本章では、Vue.js を使用する場合と使用しない場合を比較して、このハンズオンの全体像を把握します。 5 | 本章を実践すると、このハンズオンを通してどんなものを実装し学んでいくのかイメージができ、実践の準備が整います。 6 | 7 | ## 作成するもの 8 | 9 | このハンズオンでは、簡単な商品の一覧を表示し、購入する商品を選択できるプログラムを作成します。プログラムを作成する過程で Vue.js の基本を学べます。 10 | 11 | ![vue-app](./images/sample.png) 12 | 13 | > このハンズオンを完了した場合の完成イメージは [こちら](https://handson-example.vuejs-jp.org/) で確認できます。 14 | 15 | ## Vue.js を使わない場合 16 | 17 | Vue.js でのハンズオンに入る前に Vue.js を使わないで実装した場合のプログラムを見てみましょう。 18 | 19 | index.html 20 | 21 | <<< @/../examples/overview/index.html 22 | 23 | style.css 24 | 25 | <<< @/../examples/overview/style.css 26 | 27 | ## 商品表示部分の説明 28 | 29 | 簡単ですが、商品表示部分を説明します。 30 | 31 | - `
~
` の部分では商品のサムネイル画像を表示しています。 32 | - `
~
` の部分では商品の名前と説明を表示しています。 33 | - `~` の部分では商品の値段を表示しています。 34 | 35 | 36 | ```html 37 |
38 |
39 | 40 |
41 |
42 |

アボカドディップバケット

43 |

44 | 刻んだ野菜をアボカドと混ぜてディップに。こんがり焼いたバゲットとお召し上がりください。 45 |

46 | ¥480 47 |
48 |
49 | ``` 50 | 51 | ## Vue.js を使わない場合の問題点 52 | 53 | Vue.js を使わない場合、例えば次のような問題が発生します。 54 | 55 | - 商品の情報と HTML のタグが混ざっていて見通しが悪い 56 | - 複数の商品を記述するとき、同じ構造のタグを繰り返す必要がある 57 | - 商品を増減するとき、タグを追加・削除する手間がかかる 58 | - 商品の状態(売り切れや金額表記など)によって情報やタグを書き分ける必要がある 59 | - インタラクションを実装するとき、HTML と JavaScript が依存関係になる 60 | 61 | ## Vue.js を使った場合のプログラム 62 | 63 | 記述の意味はハンズオンで順を追って説明していきますが、 Vue.js に変更後のコードをみてみましょう。 64 | 65 | App.vue 66 | 67 | <<< @/../src/App.vue 68 | 69 | `` 部分は見た目の表示が記述されています。冗長な記述が減っていて Vue.js を使わない場合に比べてとても短いですね。 70 | 71 | `` 部分は商品の情報や動作等が記述されています。特に `items` では商品の情報や状態だけのデータで HTML のタグがなくなっています。「見た目、処理、商品のデータ」がスマートに分かれており、見通しがよくなっているのが、既に感じられるかと思います。 72 | 73 | 他にも Vue.js の便利な機能はありますが、実際にハンズオンを進めていく中で体験していきましょう! 74 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Vue.js 3 ハンズオン 2 | 3 | Vue.js 3 ハンズオンへようこそ😀 このハンズオンは、初めて Vue.js に触れる人がスムーズに学習できるように作られた学習用教材です。 4 | 5 | ## 利用方法 6 | 本ハンズオンの文章、ソースコードを含むあらゆる内容は、自由にご利用いただけます。個人の学習や、グループ・会社での勉強会、もくもく会、セミナーなど、あらゆる用途にご活用ください。 7 | 8 | 現在は、Vue.js のプロジェクト作成から基本的な実装方法を解説した「Vue.js をはじめよう!」を公開しています。その他のハンズオンは鋭意制作中です。 9 | 10 | ## Vue.js をはじめよう! 11 | 12 | ### 準備編 13 | 14 | - [開発環境の構築](./setup.md '開発環境の構築') 15 | - [プロジェクトの作成](./create.md 'プロジェクトの作成') 16 | 17 | ### 本編 18 | 19 | 1. [ハンズオンの概要](./overview.md 'ハンズオンの概要') 20 | 1. [data を定義し、商品をレンダリングする](./rendering.md 'data を定義し、商品をレンダリングする') 21 | 1. [v-for で商品を複数表示する](./v-for.md 'v-for で商品を複数表示する') 22 | 1. [v-if で表示・非表示を切り替える](./v-if.md 'v-if で表示・非表示を切り替える') 23 | 1. [methods で価格にカンマを入れる](./methods.md 'methods で価格にカンマを入れる') 24 | 1. [@click で商品を選択する](./event.md '@click で商品を選択する') 25 | 1. [商品をコンポーネント化する](./component.md '商品をコンポーネント化する') 26 | 1. [コンポーネントにスロットを使用する](./slot.md 'コンポーネントにスロットを使用する') 27 | 28 | ## コントリビューター 29 | 誤りやよりよい改善を見つけた方は、[Issues](https://github.com/vuejs-jp/handson-vue3-examples/issues) または [Pull requests](https://github.com/vuejs-jp/handson-vue3-examples/pulls) を作成してください。 30 | 31 | - [MIYAKE Kazuyuki](https://github.com/k-miyake) 32 | - [nalpan](https://github.com/nalpan) 33 | - [ISHIBASHI Yuuki](https://github.com/YuukiIshibashi) 34 | - [happylifetaka](https://github.com/happylifetaka) 35 | - [OKI Yoshiya](https://github.com/448jp) 36 | - [KAWAGUCHI Kazuya](https://github.com/kazupon) 37 | - [KAMENOUE Takao](https://github.com/totocalcio) 38 | - [HIROTAKA Ishiwata](https://github.com/watasan1012) 39 | - [shiyuu](https://github.com/shiyuu33) 40 | - Photo by Tyler Nix, matthew reyes, Amy Flak, Elena Rabkina on Unsplash 41 | 42 | ## ライセンス 43 | [MIT](https://opensource.org/licenses/MIT) 44 | -------------------------------------------------------------------------------- /GUIDE.md: -------------------------------------------------------------------------------- 1 | # Vue3.x ハンズオン執筆ガイド 2 | 3 | 本ドキュメントは、本ハンズオンを執筆する人(コントリビューター)のためのガイドです。どう書いたらいいか迷った時に参考にしてください。また、ガイドにないことで悩んだら [新規 Issue を作成](https://github.com/vuejs-jp/handson-vue3-examples/issues/new) してご相談ください。 4 | 5 | ## 主題と関係が薄い話題について 6 | JavaScript のビルトインクラスや正規表現など、主題と関係が薄い話題を書く時は、本文と区別が付きやすいように対応します。 7 | 8 | - 文章で説明したいとき 9 | - 適切なレベルで見出しを付け、冒頭に「参考:」を記載します。 10 | ```md 11 | ### 本文用の見出し1 12 | 本文があります。本文があります。本文があります。 13 | 14 | ### 参考:正規表現について 15 | 正規表現とは、正規な表現のことです。説明つらつら。 16 | 17 | ### 本文用の見出し2 18 | 本文があります。本文があります。本文があります。 19 | ``` 20 | - 外部リンクを表示したいとき 21 | - 引用 `> ` でリンクを表現します。 22 | ```md 23 | 本文があります。 24 | 25 | > [String() に関する詳細](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/String) 26 | 27 | 本文があります。 28 | ``` 29 | 30 | ## 外部リンク先について 31 | - 原則として、リンク先は公式ドキュメントとします 32 | - 例えば、Vue.js 本体に関しては Vue.js 公式ドキュメント([V3](https://v3.ja.vuejs.org/guide/introduction.html) 、 [V2](https://jp.vuejs.org/v2/guide/))にリンクします 33 | - HTML、CSS、JavaScript の仕様に関しては [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web) にリンクします 34 | 35 | ## 改行について 36 | マークダウンでは、原則では改行されないためひとつの文章内では改行させない。改行したい場合は明示的に空行を入れて改行させるようにする 37 | 38 | ## 文章の校正( textlint )について 39 | 40 | ドキュメントは、 [textlint](https://github.com/textlint/textlint) を使って校正を行います。校正のチェックルールは、Vue.js 日本ユーザーグループが翻訳プロジェクト等で利用している [プリセット](https://github.com/vuejs-jp/textlint-rule-preset-vuejs-jp) を参照しています。 41 | 42 | ### Pull Request 時の自動チェック 43 | 44 | Pull Request を発行すると、GitHub Actions によって自動的に textlint によるルール評価が行われます。ルールに合わない問題が見つかった場合は、Pull Request のステータスチェックがエラー表示になるので、対応する PR の `Checks` タブで GitHub Actions のログから `Run textlint` の詳細を展開してエラー内容を確認してください。 45 | 46 | ### ローカルでのチェック方法 47 | 48 | Pull Request で textlint のエラーが出た場合や、PR 前に事前にチェックをしたい場合は、ローカルで以下のコマンドを実行して確認することができます。 49 | 50 | ```bash 51 | npm run textlint {チェックしたいファイル名} 52 | ``` 53 | 54 | エラーが無い場合は何も表示されませんが、エラーが見つかった場合はログに問題の箇所と内容が表示されるので、ログに従って修正してください。 55 | 56 | ```bash 57 | ✓ vuejs-jp/ja-space-between-half-and-full-width: 原則として、全角文字と半角文字の間にスペースを入れます。 58 | /Users/miyake/repos/handson-vue3-examples/GUIDE.md:45:22 59 | v 60 | 44. 61 | 45. Pull Request でtextlintのエラーが出た場合や、PR 前に事前にチェックをしたい場合は、ローカルで以下のコマンドを実行して確認することができます。 62 | 46. 63 | ``` 64 | -------------------------------------------------------------------------------- /examples/overview/src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | position: relative; 59 | font-weight: normal; 60 | } 61 | 62 | body { 63 | min-height: 100vh; 64 | color: var(--color-text); 65 | background: var(--color-background); 66 | transition: color 0.5s, background-color 0.5s; 67 | line-height: 1.6; 68 | font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 69 | Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 70 | font-size: 15px; 71 | text-rendering: optimizeLegibility; 72 | -webkit-font-smoothing: antialiased; 73 | -moz-osx-font-smoothing: grayscale; 74 | } 75 | -------------------------------------------------------------------------------- /examples/overview/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | handson-vue3-examples 8 | 9 | 10 | 11 | 14 |
15 |
16 | 17 |

Vue.js ハンズオン

18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 |

アボカドディップバケット

26 |

27 | 刻んだ野菜をアボカドと混ぜてディップに。こんがり焼いたバゲットとお召し上がりください。 28 |

29 | ¥480 30 |
31 |
32 |
33 |
34 | 35 |
36 |
37 |

あの日夢見たホットケーキ

38 |

39 | 子供のころに食べたかった、あのホットケーキを再現しました。素朴でどこか懐かしい味をどうぞ。 40 |

41 | ¥1,180 42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 |

HOP WTR

50 |

51 | ロサンゼルス生まれのスパークリングウォーター。ノンカロリー、ノンアルコールの新感覚飲料です。 52 |

53 | ¥320 54 |
55 |
56 |
57 |
58 | 59 |
60 |
61 |

チーズフレンチフライ

62 |

63 | イタリア産チーズをたっぷりかけたアツアツのフレンチフライ。みんな大好きな一品です。 64 |

65 | ¥670 66 |
67 |
68 |
69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /examples/rendering/src/App.vue: -------------------------------------------------------------------------------- 1 | // #region script 2 | 13 | // #endregion script 14 | 15 | // region template 16 | 38 | // endregion template 39 | 40 | // region style 41 | 123 | // endregion style -------------------------------------------------------------------------------- /docs/setup.md: -------------------------------------------------------------------------------- 1 | # 開発環境の構築 2 | 3 | ## 前提とする環境 4 | 5 | - エディタ: Visual Studio Code(以下、VS Code) 6 | - VS Code の拡張機能:Vue Language Features (Volar) 7 | - 開発言語: JavaScript 8 | - 利用するツール: Node.js 9 | 10 | ## ターミナルの準備 11 | 12 | このハンズオンでは、主にターミナルを使ってコマンドを実行していきます。 13 | 14 | ::: tip ヒント 15 | ターミナルとは、コマンドと呼ばれる命令文を用いて OS やアプリケーションの操作や設定を行うツールです。 16 | ::: 17 | 18 | ### Mac でのターミナル利用方法 19 | 20 | - `アプリケーション - ユーティリティ` 内に標準でインストールされている `ターミナル.app` を起動します 21 | - 利用方法の詳細は Google 検索で "Mac ターミナル 使い方" 等で検索してください 22 | 23 | ### Windows でのターミナル利用方法 24 | 25 | - スタートメニューから `Windows Terminal` を選択して起動します 26 | - なければ、Microsoft Store からインストールします 27 | - 利用方法の詳細は [公式ドキュメント](https://docs.microsoft.com/ja-jp/windows/terminal/) を参照してください 28 | 29 | ## Node.js のインストール 30 | 31 | ### 既にインストールされているかどうかの確認 32 | 33 | ターミナルに以下のコマンドを入力し、return キーで実行します。 34 | 35 | ```sh 36 | node -v 37 | ``` 38 | 39 | バージョン番号が表示されたら、Node.js はインストールされていますので、セットアップの手順は飛ばして構いません。 40 | 41 | ```sh 42 | v20.9.0 43 | ``` 44 | 45 | ::: warning 注意 46 | 表示されるバージョンはインストールするタイミングによって異なります。 47 | 48 | [Vue アプリケーションの作成 - 前提条件](https://ja.vuejs.org/guide/quick-start.html#creating-a-vue-application)より、Node.js のバージョンは 16.0 より最新バージョンをインストールする必要があります。 49 | ::: 50 | 51 | ### セットアップ 52 | 53 | Node.js がインストールされていない場合は、 以下のページから各 OS 用のインストーラーをダウンロードして、セットアップしてください。 54 | 55 | - [Node.js 公式サイトのダウンロードページ](https://nodejs.org/en/download) 56 | 57 | なお、ダウンロードページでは `LTS` と `最新版` が選択できるようになっていますが、このハンズオンでは安定版である `LTS` を使うことを推奨します。 58 | 59 | ::: tip ヒント 60 | LTS は、Long-term Support の略で、長期間サポートされる安定バージョンです。 61 | ::: 62 | 63 | もし、Node.js のバージョンを切り替えて使いたい場合は、バージョンマネージャーの利用を検討してください。以下は主要なバージョンマネージャーへのリンクです。セットアップについては、それぞれのドキュメントを参照してください。 64 | 65 | #### Mac でよく使われるバージョンマネージャー 66 | 67 | - [Volta](https://volta.sh/) 68 | - [nodenv](https://github.com/nodenv/nodenv) 69 | 70 | #### Windows でよく使われるバージョンマネージャー 71 | 72 | - [Volta](https://volta.sh/) 73 | - [nvm-windows](https://github.com/coreybutler/nvm-windows) 74 | 75 | ## VS Code のセットアップ 76 | 77 | このハンズオンでは、VS Code を使って開発していきます。 78 | 79 | ::: tip ヒント 80 | VS Code を既にお使いの場合はこのセクションは飛ばしてください。 81 | ::: 82 | 83 | ### VS Code のインストール 84 | 85 | 1. [VS Code 公式ダウンロードページ](https://code.visualstudio.com/download) からお使いの OS に合わせたインストーラーをダウンロードします 86 | 1. インストーラーの指示に従ってインストールします 87 | - インストールの詳細は [公式ドキュメント](https://code.visualstudio.com/docs/setup/setup-overview) を確認してください 88 | 89 | ### Vue Language Features (Volar) 拡張機能のインストール 90 | 91 | `Vue Language Features (Volar)` は Vue.js の開発をサポートする VS Code の拡張機能です。`.vue` ファイルのシンタックスハイライトやインテリセンスによる補完ができるようになります。詳細は、[language-tools の GitHub リポジトリ](https://github.com/vuejs/language-tools) を参照してください。 92 | 93 | Volar をインストールするには、VS Code が入っているマシンで、 [Vue Language Features (Volar) - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=Vue.volar) にアクセスし Install ボタンをクリックします。 94 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 80 | 81 | 139 | -------------------------------------------------------------------------------- /examples/component/src/App.vue: -------------------------------------------------------------------------------- 1 | // region script 2 | 50 | // endregion script 51 | 52 | // region template 53 | 79 | // endregion template 80 | 81 | // region style 82 | 140 | // endregion style 141 | -------------------------------------------------------------------------------- /docs/create.md: -------------------------------------------------------------------------------- 1 | # プロジェクトの作成 2 | 3 | ## create-vue でのプロジェクト新規作成 4 | 5 | [create-vue](https://github.com/vuejs/create-vue) を使って生成されるアプリケーションをプロジェクトと呼びます。ここではプロジェクトを新しく作成してみましょう。 6 | 7 | 1. アプリケーションを作成するディレクトリを決めておきます(この例では `vue3-lab` としています)。`create-vue` でプロジェクトを作成すると、決めたディレクトリの配下にファイル群が生成されます。 8 | 9 | 2. ターミナルで、プロジェクトのディレクトリを作成する親ディレクトリに移動します。もし、ホームディレクトリの直下にプロジェクトを作成するのであれば、ターミナルで以下のコマンドを使って移動しておきます。 10 | 11 | ```sh 12 | cd ~ 13 | ``` 14 | 15 | ::: tip ヒント 16 | ホームディレクトリとは、ユーザー固有のファイルやフォルダを保存できる領域であり、通常ユーザー名でディレクトリが作成されています。 17 | ::: 18 | 19 | 3. `create-vue` でプロジェクトを新規作成します。ターミナルで以下のコマンドを実行します(コマンド実行後はそのまま待機しておいてください)。プロジェクトのディレクトリは `create-vue` によって自動的に作成されます。 20 | 21 | ```sh 22 | npm create vue@latest vue3-lab 23 | ``` 24 | 25 | 4. コマンドを実行すると、ターミナルにいくつかの質問が表示されます。このハンズオンでは以下のように選択します。 26 | 27 | 下記のメッセージが表示された場合は `y` と入力して `enter / return` キーを押します。 28 | ``` 29 | Need to install the following packages: 30 | create-vue@latest 31 | Ok to proceed? (y) -> y 32 | ``` 33 | 34 | 以降の質問には、基本的に `No` を選択して進めます。 35 | 36 | ::: tip ヒント 37 | 矢印キーでアンダースコアを移動させることで項目を選択します。 38 | enter / return キーで項目を確定できます。 39 | ::: 40 | 41 | ``` 42 | Vue.js - The Progressive JavaScript Framework 43 | ? Add TypeScript? › No / Yes -> No 44 | ? Add JSX Support? › No / Yes -> No 45 | ? Add Vue Router for Single Page Application development? › No / Yes -> No 46 | ? Add Pinia for state management? › No / Yes -> No 47 | ? Add Vitest for Unit Testing? › No / Yes -> No 48 | ? Add an End-to-End Testing Solution? › - Use arrow-keys. Return to submit. 49 | ❯ No 50 | Cypress 51 | Nightwatch 52 | Playwright 53 | -> No 54 | ? Add ESLint for code quality? › No / Yes -> No 55 | ``` 56 | 57 | ## プロジェクトの起動 58 | 59 | 作成したプロジェクトを起動してみましょう。プロジェクトの起動には外部パッケージをインストールしてから起動コマンドを実行します。 60 | 61 | 1. 作成したプロジェクトのディレクトリに移動し(この例では `vue3-lab`)、`npm install` で外部パッケージをインストールします。 62 | 63 | ```sh 64 | cd vue3-lab 65 | npm install 66 | ``` 67 | 68 | 2. `npm install` の処理が完了したら `npm run dev` でプロジェクトを起動します。 69 | 70 | ```sh 71 | npm run dev 72 | ``` 73 | 74 | 3. `npm run dev` の実行が完了したら、ブラウザで `http://localhost:5173/` にアクセスします。 75 | 76 | 4. ブラウザに「You did it!」等と表示されていれば、無事にプロジェクトの作成が成功しています。 77 | 78 | ## プロジェクトの確認 79 | 80 | プロジェクト新規作成後、以下のようなディレクトリ構造になります。 81 | 82 | ``` 83 | vue3-lab 84 | ├── README.md 85 | ├── index.html 86 | ├── node_modules 87 | ├── package-lock.json 88 | ├── package.json 89 | ├── public 90 | │   └── favicon.ico 91 | ├── src 92 | │   ├── App.vue 93 | │   ├── assets 94 | │   │   ├── base.css 95 | │   │   ├── logo.svg 96 | │   │   └── main.css 97 | │   ├── components 98 | │   │   ├── HelloWorld.vue 99 | │   │   ├── TheWelcome.vue 100 | │   │   ├── WelcomeItem.vue 101 | │   │   └── icons 102 | │   │   ├── IconCommunity.vue 103 | │   │   ├── IconDocumentation.vue 104 | │   │   ├── IconEcosystem.vue 105 | │   │   ├── IconSupport.vue 106 | │   │   └── IconTooling.vue 107 | │   └── main.js 108 | └── vite.config.js 109 | 110 | 6 directories, 19 files 111 | ``` 112 | 113 | これらのファイルが `create-vue` で作成されます。 114 | 115 | ![Vite App](./images/vite-app.png) 116 | -------------------------------------------------------------------------------- /examples/slot/src/App.vue: -------------------------------------------------------------------------------- 1 | // region script 2 | 50 | // endregion script 51 | 52 | // region template 53 | 82 | // endregion template 83 | 84 | // region style 85 | 143 | // endregion style 144 | -------------------------------------------------------------------------------- /docs/v-if.md: -------------------------------------------------------------------------------- 1 | # v-if で表示・非表示を切り替える 2 | 3 | ## 本章の概要とゴール 4 | 購入しようと思った商品が売り切れで購入できないと、せっかく購入しようとしたユーザーをがっかりさせてしまいます。 5 | 本章では、`v-if` ディレクティブを使って売り切れの商品は非表示にするようプログラムを改修していきます。 6 | 本章を実践すると、特定の条件の時だけ HTML を表示させることができるようになり、`v-if` の使い方が理解できます。 7 | 8 | ## v-if の書き方 9 | 10 | Vue.js では特定の条件の時だけ DOM を生成し表示できる、`v-if` というディレクティブが用意されています。以下のように、表示・非表示を制御したい DOM 要素に `v-if` を追加します。`v-if` の値が `true` の場合は表示され、 `false` の場合は表示されません。 11 | 12 | ```html 13 | 14 |
something
15 | 16 | 17 |
something
18 | ``` 19 | 20 | ## プロパティの追加 21 | 22 | それでは、`v-if` を使用して、売り切れの商品を非表示にしましょう。 23 | 24 | まず、"売り切れかどうか"という情報を、`items` の商品情報に `soldOut` というプロパティで持たせてみましょう。今回は `id` が `3` の商品を売り切れ状態にしてみます。`id` が `3` の商品に `soldOut` というプロパティを追加し、 `true` を設定します。 25 | 26 | <<< @/../examples/v-if/src/App.vue#script{30-30} 27 | 28 | ## DOM 要素に v-if を追加 29 | 30 | 次に、DOM 要素に `v-if` を追加して、非表示にします。1 つ 1 つの商品を表示している要素は以下でハイライトしている部分です。 31 | 32 | 変更前 33 | 34 | <<< @/../examples/v-for/src/App.vue#template{12-23} 35 | 36 | この `
` 要素に `v-if` を記述していきます。`item.soldOut` が `true` の場合は、売り切れであることを示しています。 37 | 38 | 売り切れではない時、つまり `item.soldOut` が `false` の時だけ表示をさせたいため、ひと工夫必要です。`v-if="item.soldOut"` としてしまうと、売り切れの場合のみ表示させることになってしまうため、`!` を使用して真偽値を逆転させて使用しましょう。 39 | 40 | 変更後 41 | 42 | <<< @/../examples/v-if/src/App.vue#template{12-25} 43 | 44 | これで `id` が `3` の商品は非表示になりました。 45 | 46 | ::: tip ヒント 47 | ここでは省略していますが、売り切れの状態を明示するため、`id` が `3` 以外の商品は `soldOut` プロパティを `false` にしておくとよいでしょう。 48 | ::: 49 | 50 | ## v-else や v-else-if の使い方 51 | 52 | JavaScript の条件分岐の構文に `else` があるように、Vue.js にも同様のディレクティブが用意されています。`else` と同様の働きをするのが `v-else` です。 53 | 54 | 例えば、売り切れの場合は非表示にするのではなく"売り切れです"というメッセージを表示させたい場合は以下のように使用できます。 55 | 56 | ```html 57 |
58 | 59 |
60 |
売り切れです
61 | ``` 62 | 63 | また、JavaScript の `else if` と同様の働きをする `v-else-if` も用意されています。`v-if` の評価が `false` の時に、さらに条件を指定したい時に使用できます。 64 | 65 | 66 | 67 | ## v-showとの違い 68 | `v-if` に似た `v-show` というディレクティブが用意されています。以下のように、表示・非表示を制御したい DOM 要素に `v-show` を追加します。`v-show` の値が `true` の場合は表示され、 `false` の場合は表示されません。 69 | 70 | ```html 71 | 72 |
something
73 | 74 | 75 |
something
76 | ``` 77 | 78 | 一見 `v-if` と同じように思えますが、`v-if` が DOM 要素ごと削除しているのに対して、`v-show` は style 属性の値に `display:none;` を付与して非表示にしています。 79 | 80 | ブラウザ上での描画 81 | ```html 82 | 83 |
something
84 | ``` 85 | 86 | ::: tip ヒント 87 | `v-if` は表示を切り替えるコストが高く、 `v-show` は初期描画のコストが高いです。そのため、頻繁に表示を切り替えるのであれば `v-show` を使い、それ以外では `v-if` を使うとよいでしょう。 88 | ::: 89 | 90 | ::: warning 注意 91 | `v-show` は `