- 投稿日:2020-09-26T20:24:02+09:00
【Vue】コンポーネント間のデータ(とメソッド)の受け渡し
はじめに
Vueの基礎的な部分、コンポーネント間のデータの受け渡しの備忘録。
ついでに、親コンポーネントのメソッドを子コンポーネントで利用する方法も載せた。なお、デザインテンプレートにvuetifyを使っている。
環境
- vue: 2.6.10
- vuetify: 2.1.0
サンプルコード
親コンポーネント
parentComponent.vue<template> <v-card> <child-component :users :teamId @showList="showUserList" /> </v-card> </template> <script> import childComponent from "@/components/molcules/childComponent" export default { components: { "child-component": childComponent, }, data() { return { users: [ "Alice", "Bob", ], teamId: 3, } }, methods: { showUserList(item) { console.log("showUserList: " + item) }, }, } </script>子コンポーネント
childComponent.vue<template> <v-card> {{ teamId }} <v-list v-for="(user, index) in users" :key="index" > {{ user }} </v-list> <v-btn @click="showList" > </v-btn> </v-card> </template> <script> export default { props: { users: { type: Array, required: false, default: () => [] }, teamId: { type: Number, required: true, default: () => 0 } }, methods: { showList(item) { this.$emit("showUserList", item) }, }, } </script>おわりに
取り急ぎコードのみ載せた。
後日、余力があれば解説のほうも追記する。
- 投稿日:2020-09-26T15:32:53+09:00
Vue3の環境にVuetifyがインストールできない
Vue3の環境にVuetifyがインストールできない
vue add vuetifyを実行した時、次のようなエラーがでて、インストールが完了しません。
Error: You cannot call "get" on a collection with no paths. Instead, check the "length" property first to verify at least 1 path exists. Error: You cannot call "get" on a collection with no paths. Instead, check the "length" property first to verify at least 1 path exists. at Collection.get (/home/masa/.n/lib/node_modules/@vue/cli/node_modules/jscodeshift/src/Collection.js:213:13) at injectOptions (/home/masa/.n/lib/node_modules/@vue/cli/lib/util/codemods/injectOptions.js:15:6) at runTransformation (/home/masa/.n/lib/node_modules/@vue/cli/node_modules/vue-codemod/dist/src/run-transformation.js:61:17) at /home/masa/.n/lib/node_modules/@vue/cli/lib/Generator.js:290:23 at Array.forEach (<anonymous>) at Generator.resolveFiles (/home/masa/.n/lib/node_modules/@vue/cli/lib/Generator.js:276:24) at processTicksAndRejections (internal/process/task_queues.js:93:5) at async Generator.generate (/home/masa/.n/lib/node_modules/@vue/cli/lib/Generator.js:175:5) at async runGenerator (/home/masa/.n/lib/node_modules/@vue/cli/lib/invoke.js:111:3) at async invoke (/home/masa/.n/lib/node_modules/@vue/cli/lib/invoke.js:92:3)解決策
vuetify3がリリースされるまで待つ
https://github.com/vuetifyjs/vuetify/issues/11162#issuecomment-616353160
以下の試したことを実行すると上のエラーは解消するが別のエラーがでて動きません。
試したこと
main.jsに次のコードを書いてから、vue add vuetifyを実行する。
new Vue({ render: h => h(App), }).$mount('#app');
- 投稿日:2020-09-26T14:20:11+09:00
Nuxt v2でStorybook 6.0.xを導入する
以前にこちらの記事でインストールからscssの利用設定、CSF記法を備忘録的にまとめました。
久しぶりにStorybookを新規立ち上げてみたところ、設定ファイル周りの仕様が変わっておりましたので、改めてインストールから基本設定の部分までをメモしておきます。
TypeScriptの利用設定等も同様に行えるはずです(未確認)。0. Nuxtプロジェクトの作成
Nuxtプロジェクトは
src
以下に移動し、scssの設定も完了しているものとする。
作成するファイルの通り、Storybookでのscssとエイリアスの稼働確認を行います。0.1.
/src/assets/
以下の構成とファイル内容assets ├── img │ └── hoge.png │ └── hoge_bg.png │ └── hoge_bg2.png └── scss ├── _mixins.scss // なくてもOK ├── _variables.scss ├── global.scss └── reset.scss // なくてもOK_variables.scss// 変数稼働チェック $font-color-green: Green;global.scss/* `layouts/default.vue`のスタイル設定を一部移動し、改変 */ @import './reset'; @import './_variables'; @import './_mixins'; html { font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 16px; word-spacing: 1px; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; box-sizing: border-box; // エイリアス稼働チェック background: url(~assets/img/hoge_bg.png); } a { // 変数稼働チェック color: $font-color-green; }0.2.
src/components/StorybookTest.vue
を作成。Storyで表示する確認用のコンポーネント。
あくまでscssとエイリアス設定が効くかの確認なので要素を並べただけですのであしからず。StorybookTest.vue<template> <div class="outer"> <div class="inner"> <a href="#">Storybook Test</a> <!-- エイリアスの確認 --> <img src="~/assets/img/hoge.png" alt="" /> </div> </div> </template> // scssの確認 <style lang="scss" scoped> .outer { width: 110px; height: 200px; margin: auto; .inner { text-align: center; /* エイリアスの確認 */ background: url('~assets/img/hoge_bg.png'); } } </style>1. Storybookインストール
ここは以前と変わりません。CLIでのインストール時に
sb
をつけておくと、フレームワーク等を自動で判別して必要なモジュールを追加してくれます。npx -p @storybook/cli sb init
インストールが完了すると、
.storybook
とstories
というディレクトリが生成されます。
stories
ディレクトリは以前から変わらず、storyファイルを格納します。
一方、.storybook
ディレクトリ内に生成されるファイルが以下のように変更されておりました。.storybook ├── main.js └── preview.js2. 設定ファイルの変更
以前は、Nuxtプロジェクトで使用しているscssファイルをStorybookでも利用するための設定やエイリアスの設定を、
.storybook/webpackconfig.js
というファイル内で定義しておりましたが、これらがインストール時に生成された.storybook/main.js
に記述を移します。2.1 scssの読み込み設定
storybook/main.js- const { resolve } = require('path') + const path = require('path') const rootPath = path.resolve(__dirname, '../src/') module.exports = { "stories": [ "../**/*.stories.mdx", "../**/*.stories.@(js|jsx|ts|tsx)" ], "addons": [ "@storybook/addon-links", "@storybook/addon-essentials" ], + webpackFinal: async(config, {configType}) => { + config.module.rules.push({ + test: /\.scss$/, + use: [ + 'style-loader', + 'css-loader', + 'sass-loader' + ], + include: rootPath, + }) + + config.resolve.modules = [ + ...(config.resolve.modules || []), + rootPath + ]; + + return config + } }2.2 Nuxtプロジェクトで使用しているscssをStorybookでも使用する
reset.scssやglobal.scssなど、Nuxtプロジェクトで使用しているassets以下にある共通のscssをStorybookにも適用する。
これは.storybook/preview.js
に必要なscssをimportしてあげるだけで良い。storybook/preview.js// 他のscssファイルもimportしているので、ここではglobal.scssの記述のみ + import '../src/assets/scss/global.scss' // 以下はStorybookインストール時に自動で定義されている export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, }3. 確認
Storyファイルの作成
stories/StorybookTest.stories.jsimport StorybookTest from '../src/components/StorybookTest.vue' /* コンポーネントの設定 */ export default { title: 'Storybook稼働確認', // ナビゲーションパネルでの表示名となる component: StorybookTest, // 対象となるコンポーネントを定義する } /* story記述 */ // default export const STTest = () => ({ // 変数名がナビゲーションパネルでの表示名となる components: { StorybookTest }, // 対象となるコンポーネントを指定する template: '<storybook-test />', // レンダリングするhtmlを記述する })以上までの設定でscssとエイリアスの設定は完了。最後にStorybookを起動して確認してみる。
npm run storybook
- 投稿日:2020-09-26T14:10:58+09:00
Vue CLI 3 よく使うであろうコマンド コピペ用
- 投稿日:2020-09-26T14:10:58+09:00
Vue CLI よく使うであろうコマンド コピペ用
- 投稿日:2020-09-26T10:12:35+09:00
Vue v3.0.0記念Code nameまとめ
Vue v3.0.0 One Pieceが2020/09/18にリリースされました。
https://github.com/vuejs/vue-next記念に過去からのCode nameをまとめてみました。
Version Code name 作品名 v3.0.0 One Piece ONE PIECE v2.6.0 Macross 超時空要塞マクロス v2.5.0 Level E レベルE v2.4.0 Kill la Kill キルラキル v2.3.0 JoJo's Bizarre Adventure ジョジョの奇妙な冒険 v2.2.0 Initial D 頭文字D v2.1.0 Hunter X Hunter HUNTER×HUNTER v2.0.0 Ghost in the Shell 攻殻機動隊 v1.0.0 Evangelion 新世紀エヴァンゲリオン v0.12.0 Dragon Ball ドラゴンボール v0.11.0 Cowboy Bebop カウボーイビバップ v0.10.0 Blade Runner ブレードランナー v0.9.0 Animatrix アニマトリックス 命名は見ればわかるようにアニメ好きですね
「F,N」を除いてアルファベット順になっています。
急ににわか認定されそうなものが出てきましたが、基本的に有名どころなので次はどんな作品がくるでしょうか
- 投稿日:2020-09-26T10:12:35+09:00
Vue v3.0.0リリース記念Code name振り返り
Vue v3.0.0 One Pieceが2020/09/18にリリースされました。
https://github.com/vuejs/vue-next記念に過去からのCode nameをまとめてみました。
Version Code name 作品名 v3.0.0 One Piece ONE PIECE v2.6.0 Macross 超時空要塞マクロス v2.5.0 Level E レベルE v2.4.0 Kill la Kill キルラキル v2.3.0 JoJo's Bizarre Adventure ジョジョの奇妙な冒険 v2.2.0 Initial D 頭文字D v2.1.0 Hunter X Hunter HUNTER×HUNTER v2.0.0 Ghost in the Shell 攻殻機動隊 v1.0.0 Evangelion 新世紀エヴァンゲリオン v0.12.0 Dragon Ball ドラゴンボール v0.11.0 Cowboy Bebop カウボーイビバップ v0.10.0 Blade Runner ブレードランナー v0.9.0 Animatrix アニマトリックス 命名は見ればわかるようにアニメ好きですね
「F,N」を除いてアルファベット順になっています。
急ににわか認定されそうなものが出てきましたが、基本的に有名どころなので次はどんな作品がくるでしょうか
- 投稿日:2020-09-26T08:43:02+09:00
Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #3 個別記事ページの作成
←Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #2 NuxtとRailsとの疎通テスト
個別記事ページの作成
$ mkdir pages/posts $ touch pages/posts/_id.vuepages/posts/_id.vue<template> <v-layout column justify-center align-center > <v-flex xs12 sm8 md6 > <v-card> <v-card-title class="headline"> {{ post.subject }} - {{ post.user.name }} </v-card-title> <v-card-text> {{ post.body }} </v-card-text> </v-card> </v-flex> </v-layout> </template> <script> export default { validate ({ params }) { return /^\d+$/.test(params.id) }, async asyncData ({ $axios, params }) { const response = await $axios.$get(`/v1/posts/${params.id}`) return { post: response.post } } } </script>Nuxtでは上記のように
pages/hoge/_id.vue
とすることで、hoge/{id}のような動的ページが作られます。バリデートは数値型のみ許容するように設定しています。以下、公式ドキュメント参照。
ルーティング - NuxtJSそして
asyncData
というSSR用のメソッドでv1/posts/${params.id}
とすることで、URLのid部分の数値から固定のpostを取得しているわけです。なお、今回は
post
の値をVuexのstoreに保存していません。
storeはなんでもかんでも保存を保存しておく場所ではなく、他のmoduleやサイト全体で使う必要があるか考え、そうでなければ不用意に突っ込まないほうがいいです。もしブラウザで以下の通り表示されたら、とりあえずOKです。
indexから個別ページにリンクを設置
indexから個別ページにリンクを貼ります。
pages/index.vue<v-card v-for="post in posts" :key="post.id"> <v-card-title class="headline"> - {{ post.subject }} - {{ post.user.name }} + <n-link :to="`/posts/${post.id}`"> + {{ post.subject }} - {{ post.user.name }} + </n-link> </v-card-title> <v-card-text>リンクになっていますね。
CORS対策
ではindexから個別ページに飛んでみましょう。
エラーになりましたか?
実はこれがエラーメッセージ読んでも原因が特定しづらく結構厄介なものです。
以前この問題の対応策を書き残していますので、詳細を知りたい方は以下の記事を。
Nuxt.jsでURL直叩きの時はページが表示されるのに、nuxt-linkやブラウザバックでAn error occurredになるさて上記記事にも書きましたが、原因はページ遷移した場合はSSR(サーバサイドレンダリング)ではなくCSR(クライアントサイドレンダリング)になるため、CORS(オリジン間リソース共有)の対策が必要です。
nuxt.config.js** Nuxt.js modules */ modules: [ - '@nuxtjs/axios' + '@nuxtjs/axios', + '@nuxtjs/proxy' ], - axios: {}, + axios: { + proxy: true + }, + proxy: { + '/v1/': { + target: 'https:/xxxxxxxxxxx.ap-northeast-1.amazonaws.com:8080/' + } + },targetはご自身のRails APIエンドポイントに置き換えてください。
この設定が済めば、indexも個別ページも、ブラウザバックやn-link(nuxt-link)による遷移時も正常に表示されるはずです。
続き
→Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #4 サインアップページの作成
【連載目次へ】
- 投稿日:2020-09-26T08:42:09+09:00
Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #2 NuxtとRailsとの疎通テスト
←Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #1 環境構築
axiosの導入
URLのリクエストを送る際はaxiosを使います。
create_nuxt_appの時にaxiosを入れているはずですが、もし入れるのをミスっていた場合は以下の手順で追加します。$ yarn add @nuxtjs/axiosnuxt.config.jsexport default { ** Nuxt.js modules */ modules: [ + '@nuxtjs/axios' ],APIとの疎通テスト
pages/index.vueWelcome to the Vuetify + Nuxt.js template </v-card-title> <v-card-text> + <ul> + <li v-for="post in posts" :key="post.id"> + {{ post.subject }} + {{ post.body }} + </li> + </ul> ... components: { Logo, VuetifyLogo + }, + async asyncData({ $axios }) { + const response = await $axios.$get('/v1/posts'); + return { + posts: response.posts + }; } } </script>雑ではありますが、Railsのseedで作ったデータが無事に取得できましたね。
とりあえずこれでフロントエンドとバックエンドの連携確認は取れました。
Vuexで書き換える
特にルール無く記述していくことも可能なのですが、Vuexを利用して書いていきます。
Vuex は Vue.js アプリケーションのための 状態管理パターン + ライブラリです。 これは予測可能な方法によってのみ状態の変異を行うというルールを保証し、アプリケーション内の全てのコンポーネントのための集中型のストアとして機能します。 また Vue 公式の開発ツール拡張と連携し、設定なしでタイムトラベルデバッグやステートのスナップショットのエクスポートやインポートのような高度な機能を提供します。
文章・画像引用:Vuex とは何か? | Vuex
文章を読んだり画像をパッと見ただけではなかなか理解しづらいかもしれません。
actionsやらmutationsやらdispatch, commit…なにこれ?と思うかもしれませんが、
- storeに
state
、mutations
、actions
の3つ(+getters
の4つ)を持ってそれぞれを呼び出すというパターンstate
は値を持つだけmutations
はstateの値をセットするだけactions
で処理して、stateを変更する時は直接stateを呼ばずmutationsを呼ぶgetters
はstateの値を取得するだけmutations
を呼ぶことをcommit
と言うactions
を呼ぶことをdispatch
と言うとなります。
とりあえず以下のようにファイルを編集します。
store/posts.jsexport const state = () => ({ posts: [] }) export const getters = { posts (state) { return state.posts } } export const mutations = { setPosts (state, data) { state.posts = data } } export const actions = { async fetchPosts () { return await this.$axios.$get('/v1/posts') } }pages/index.vue<template> <v-layout column justify-center align-center > <v-flex xs12 sm8 md6 > <v-card v-for="post in posts" :key="post.id"> <v-card-title class="headline"> {{ post.subject }} - {{ post.user.name }} </v-card-title> <v-card-text> {{ post.body }} </v-card-text> </v-card> </v-flex> </v-layout> </template> <script> export default { async fetch ({ store }) { const posts = await store.dispatch('posts/fetchPosts') store.commit('posts/setPosts', posts.posts) }, computed: { posts () { return this.$store.getters['posts/posts'] } } } </script>storeディレクトリ以下に置いたファイルは、{ファイル名}/{関数名}で名前空間が切られます。
どのように処理されているかの流れは、上記2ファイルに1〜8でコメント記載しています。まずは
const posts = await store.dispatch('posts/fetchList') // 1
によってposts/fetchList
のdispatch
。
前述の通りdispatchはactionsを呼び出すので、posts.js
のactions
にあるfetchList
が呼ばれるわけですね。一度見方が分かれば、そこまで読み解くのは難しくないはずです。
Vuexはルールを破って書くことができてその場合エラーを投げたりしないのですが、結局そうなるとコードの保守性は下がります。ですので上記ルールに従って、storeの直接呼び出しや書き換えをせずに、actionsやmutationsで制御していきましょう。
続き
- 投稿日:2020-09-26T01:14:45+09:00
Vueでv-forを使いfont awosomeを繰り返し表示させる方法
タイトル通りvueでfont awosomeのアイコンを繰り返し表示させようとしたら、一部困ったことになったので解決策を記しておきます。
vueでfont awosomeの導入するまではこの記事を参考にしました。目的
よくプロフィールサイトで見かけるこんな感じのレイアウトを構築したいとします。
結論
以下のように記述して表示させることができました。
<v-layout justify-space-around wrap class="mb-10"> <v-flex v-for="language in languages" :key="language.id" > <font-awesome-icon :icon="{ prefix: language.prefix, iconName: language.iconName }" /><br /> <span>{{ language.name }}</span> </v-flex> </v-layout><script> export default { data() { return { languages: [ { id: 1, prefix: "fas", iconName: "code", name: "HTML5/CSS3/Sass", }, { id: 2, prefix: "fab", iconName: "js-square", name: "JavaScript", }, { id: 3, prefix: "far", iconName: "gem", name: "Ruby", }, ], }; }, }; </script>注意点
何が問題だったかというと、vueでfont awosomeを表示させようとすると、prefixがデフォルトの状態でfarになっており、それ以外のfasやfabは指定しないと表示されないのです。(こちらの記事を参考にさせていただきました。)
したがって下のように記述してしまうと、デフォルトのfar以外は表示されなくなってしますのです。
<v-layout justify-space-around wrap class="mb-10"> <v-flex v-for="language in languages" :key="language.id" > <font-awesome-icon :iconName="language.iconName" //prefixの指定をしていない /><br /> <span>{{ language.name }}</span> </v-flex> </v-layout><script> //省略 { id: 2, iconName: "js-square", //farではないので表示されない name: "JavaScript", }, { id: 3, iconName: "gem", //farなので表示される name: "Ruby", }, ], }; }, }; </script>