Vue.js | POPWEB https://blog.popweb.dev Developer, Blogger, Illustrator in Tokyo. Fri, 09 Apr 2021 17:07:34 +0000 ja hourly 1 https://wordpress.org/?v=6.7.6 https://storage.googleapis.com/gcs.pop-web.net/2021/01/favicon.ico Vue.js | POPWEB https://blog.popweb.dev 32 32 Nuxt.jsで「TypeError: Cannot set property ‘render’ of undefined」のコソールエラー対処法 https://blog.popweb.dev/programming/vue-js/nuxt-js-typeerror-cannot-set-property-render-of-undefined/ https://blog.popweb.dev/programming/vue-js/nuxt-js-typeerror-cannot-set-property-render-of-undefined/#respond Wed, 28 Oct 2020 04:11:56 +0000 https://blog.popweb.dev/?p=1469 目次 エラー内容原因と対処法 エラー内容 Nuxt.jsで開発中、以下のコンソールエラーが出て画面が表示されなくなった。 原因と対処法 <script>タグの閉じタグがなかったり、空の<script&g […]

The post Nuxt.jsで「TypeError: Cannot set property ‘render’ of undefined」のコソールエラー対処法 first appeared on POPWEB.]]>

エラー内容

Nuxt.jsで開発中、以下のコンソールエラーが出て画面が表示されなくなった。

TypeError: Cannot set property 'render' of undefined

原因と対処法

<script>タグの閉じタグがなかったり、空の<script>タグが存在しているとエラーとなるため、ちゃんと閉じタグをしてあげるか、空タグを削除してあげるとよい。

The post Nuxt.jsで「TypeError: Cannot set property ‘render’ of undefined」のコソールエラー対処法 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/nuxt-js-typeerror-cannot-set-property-render-of-undefined/feed/ 0
【Nuxt + Firebase】core.js関連のエラーの原因と解決法 https://blog.popweb.dev/programming/vue-js/nuxt-firebase-core-js/ https://blog.popweb.dev/programming/vue-js/nuxt-firebase-core-js/#respond Wed, 29 Jul 2020 07:34:50 +0000 https://blog.popweb.dev/?p=1459 Nuxt + Firebaseで開発をしていて、Firebaseのテストモジュール入れ、開発サーバを起動したらcore.js関連のエラーがずらっと出た。 目次 原因解決方法 原因 NuxtとFirebase使われるcor […]

The post 【Nuxt + Firebase】core.js関連のエラーの原因と解決法 first appeared on POPWEB.]]>
Nuxt + Firebaseで開発をしていて、Firebaseのテストモジュール入れ、開発サーバを起動したらcore.js関連のエラーがずらっと出た。

ERROR  Failed to compile with 77 errors                                  friendly-errors 15:28:27

These dependencies were not found:                                        friendly-errors 15:28:27
                                                                          friendly-errors 15:28:27
* core-js/modules/es.array.concat in ./.nuxt/client.js                    friendly-errors 15:28:27
* core-js/modules/es.array.every in ./.nuxt/router.scrollBehavior.js      friendly-errors 15:28:27
* core-js/modules/es.array.filter in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js and 2 others
* core-js/modules/es.array.find in ./.nuxt/client.js                      friendly-errors 15:28:27
* core-js/modules/es.array.for-each in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js and 2 others
* core-js/modules/es.array.from in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.array.includes in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.array.index-of in ./.nuxt/utils.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js&
* core-js/modules/es.array.iterator in ./.nuxt/client.js                  friendly-errors 15:28:27
* core-js/modules/es.array.join in ./.nuxt/utils.js                       friendly-errors 15:28:27
* core-js/modules/es.array.map in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.array.reduce in ./.nuxt/utils.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./.nuxt/components/nuxt-build-indicator.vue?vue&type=script&lang=js&
* core-js/modules/es.array.slice in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.array.some in ./.nuxt/client.js                      friendly-errors 15:28:27
* core-js/modules/es.function.name in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.object.assign in ./.nuxt/client.js                   friendly-errors 15:28:27
* core-js/modules/es.object.get-own-property-descriptor in ./.nuxt/index.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js& and 1 other
* core-js/modules/es.object.get-own-property-descriptors in ./.nuxt/index.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js& and 1 other
* core-js/modules/es.object.keys in ./.nuxt/client.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js& and 1 other
* core-js/modules/es.object.to-string in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js and 2 others
* core-js/modules/es.promise in ./.nuxt/client.js                         friendly-errors 15:28:27
* core-js/modules/es.promise.finally in ./.nuxt/client.js                 friendly-errors 15:28:27
* core-js/modules/es.regexp.constructor in ./.nuxt/utils.js               friendly-errors 15:28:27
* core-js/modules/es.regexp.exec in ./.nuxt/client.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./.nuxt/components/nuxt-build-indicator.vue?vue&type=script&lang=js&
* core-js/modules/es.regexp.to-string in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.string.ends-with in ./.nuxt/utils.js                 friendly-errors 15:28:27
* core-js/modules/es.string.includes in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.string.iterator in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.string.match in ./.nuxt/client.js                    friendly-errors 15:28:27
* core-js/modules/es.string.repeat in ./.nuxt/utils.js                    friendly-errors 15:28:27
* core-js/modules/es.string.replace in ./.nuxt/client.js, ./.nuxt/components/nuxt.js
* core-js/modules/es.string.search in ./.nuxt/utils.js                    friendly-errors 15:28:27
* core-js/modules/es.string.split in ./.nuxt/utils.js, ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./.nuxt/components/nuxt-build-indicator.vue?vue&type=script&lang=js&
* core-js/modules/es.string.starts-with in ./.nuxt/utils.js               friendly-errors 15:28:27
* core-js/modules/es.string.trim in ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js&
* core-js/modules/es.symbol in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js and 2 others
* core-js/modules/es.symbol.description in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/es.symbol.iterator in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
* core-js/modules/web.dom-collections.for-each in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js and 2 others
* core-js/modules/web.dom-collections.iterator in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js

原因

NuxtとFirebase使われるcore.jsのバージョンが異なるため。

Nuxt側のcore.jsのバージョンを2から3へダウングレードすればいいらしい。

解決方法

しかし、package.jsonを見てみるとすでにバージョン2となっていた。

一応、以下コマンドでバージョン2を再度インストールしてみる。

$ npm install core-js@2.6.11

これでうまくいった。。。

package.jsonをみるとキャレットが付与しただけになっているが、これでエラーが出ないようになった。

The post 【Nuxt + Firebase】core.js関連のエラーの原因と解決法 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/nuxt-firebase-core-js/feed/ 0
【初心者向け】Vue.jsのスロットの使い方 https://blog.popweb.dev/programming/vue-js/v-slot/ https://blog.popweb.dev/programming/vue-js/v-slot/#respond Fri, 19 Jun 2020 16:05:04 +0000 https://blog.pop-web.net/?p=1363 Vue.jsのスロットの使い方をざっくり説明する。 開発にはVue CLIを使っている前提で話を進めていく。 目次 スロットコンテンツフォールバックコンテンツ名前付きスロット名前付きでないデフォルトのスロットについてスロ […]

The post 【初心者向け】Vue.jsのスロットの使い方 first appeared on POPWEB.]]>
Vue.jsのスロットの使い方をざっくり説明する。

開発にはVue CLIを使っている前提で話を進めていく。

スロットコンテンツ

スロットコンテンツでは、親コンポーネントから子コンポーネントへコンテンツを丸ごと渡しあげることができる。

まず、以下の親コンポーネントを用意する。

子コンポーネントであるtextLinkを読み込むように用意しておく。

子コンポーネントへの渡し方は簡単で、コンポーネントの間に何か要素を入れることで渡すことができる。

今回は「ここはリンクです!」とうただの文字列。

App.vue

<template>
  <div id="app">
    <textLink url="/#">
      ここはリンクです!
    </textLink>
  </div>
</template>

<script>
import textLink from "./components/textLink";

export default {
  components: {
    textLink,
  },
};
</script>

次に、子コンポーネントのtextLinkを作成する。

機能的にはテキストリンクを配置するだけのもの。

子コンポーネントには受け渡し口として<slot />を配置する。

textLink.vue

<template>
  <a :href="url" class="nav-link">
    <slot />
  </a>
</template>

<script>
export default {
  props: ["url"],
};
</script>

これで、<slot />の部分が「ここはリンクです!」に置換される。

ブラウザで確認すると以下のようにテキストリンクになっていることがわかる。

フォールバックコンテンツ

親コンポーネント側から何か要素を送るときに、その要素が何もない場合に表示させるコンテンツを決めることができる。

それがフォールバックコンテンツ。

どうするかというと、子コンポーネント側の<slot>タグの中身に何か要素を入れてあげるだけで良い。

textLink.vue

<template>
  <div>
    <a :href="url" class="nav-link">
      <slot>デフォルトのリンクだよ!</slot>
    </a>
  </div>
</template>

<script>
export default {
  props: ["url"],
};
</script>

名前付きスロット

名前付きスロットはその名の通り名前をつけて区別するスロットのこと。

つまり、区別できるので複数のスロットを使うことができる。

まずは、親コンポーネントを編集する。

以下のよう。

App.vue

<template>
  <div id="app">
    <textLink url="/#">
      <template v-slot:link> // ※templateタグでv-slot:<スロット名>とする。
        ここはリンクです!
      </template>
      <template v-slot:string> // ※templateタグでv-slot:<スロット名>とする。
        ただの文字列です!
      </template>
    </textLink>
  </div>
</template>

<script>
import textLink from "./components/textLink";

export default {
  components: {
    textLink,
  },
};
</script>

以上のように、親コンポーネントではtemplateタグごとにv-slotで名前をつけて設定する。

ちなみに、v-slot:#として省略記号で置き換えることができる

次に子コンポーネント。

textLink.vue

<template>
  <div>
    <a :href="url" class="nav-link">
      <slot name="link" /> // 親コンポーネントで付けた名前でname=<スロット名>とする
    </a>
    <hr />
    <p>
      <slot name="string" /> // 親コンポーネントで付けた名前でname=<スロット名>とする
    </p>
  </div>
</template>

<script>
export default {
  props: ["url"],
};
</script>

<slot />タグにさっき親コンポーネントで設定した名前をnameプロパティとして設定する。

ブラウザで確認してみる。

これで複数のスロットを区別して設定することができた。

名前付きでないデフォルトのスロットについて

先ほどの子コンポーネントのコードに名前付きでないslotタグを設置してみる。

textLink.vue

<template>
  <div>
    <a :href="url" class="nav-link">
      <slot name="link" />
    </a>
    <hr />
    <slot /> // 追加
    <hr />
    <p>
      <slot name="string" />
    </p>
  </div>
</template>

親コンポーネントに<h1>と、<footer>タグを追加。

App.vue

<template>
  <div id="app">
    <textLink url="/#">
      <h1>タイトルです</h1> // 追加
      <template v-slot:link>
        ここはリンクです!
      </template>
      <template v-slot:string>
        ただの文字列です!
      </template>
      <footer>フッターです。</footer> // 追加
    </textLink>
  </div>
</template>

これはどうなるかというと、<h1><footer>は合体でして子コンポーネントの名前なしslotに置換される。

ブラウザで確認する。

また、親コンポーネントでv-slotがつかない要素は一旦、v-slot:defaultという名前でtemplateタグに集約されて子コンポーネントに置換されるという動作をする。

なので、さっきの親コンポーネントのコードを以下のようにv-slot:defaultで書いても同じ結果が得られる。

App.vue

<template>
  <div id="app">
    <textLink url="/#">
      <template v-slot:default> // v-slot:defaultとすることもできる
        <h1>タイトルです</h1>
        <footer>フッターです。</footer>
      </template>
      <template v-slot:link>
        ここはリンクです!
      </template>
      <template v-slot:string>
        ただの文字列です!
      </template>
    </textLink>
  </div>
</template>

スロットプロパティで子から親へ

子コンポーネントのデータを親コンポーネントで使いたい時は、スロットプロパティを使用する。

まず、子コンポーネントの<slot>を以下ように編集する。

textLink.vue

<template>
  <div>
    <a :href="url" class="nav-link">
      <slot name="link" title="タイトルリンクです!" /> // title="タイトルリンクです!" を追加した
    </a>
  </div>
</template>

<script>
export default {
  props: ["url"],
};
</script>

追加した「title=”タイトルリンクです!”」を親側で表示させるための、以下のように親コンポーネントを編集する。

App.vue

<template>
  <div id="app">
    <textLink url="/#">
      <template v-slot:link="slotProps"> // ="slotProps" を追加
        <h2>{{ slotProps.title }}</h2> // slotPropsの中身を表示
        ここはリンクです!
      </template>
    </textLink>
  </div>
</template>

<script>
import textLink from "./components/textLink";

export default {
  components: {
    textLink,
  },
};
</script>

受け取る変数のslotPropsは、なんでも好きな名前を付けれる。

これをブラウザで確認する以下のような感じになる。

また、名前付きスロットを使わずに、デフォルトスロットしかない場合は以下のようにも書ける。

App.vue

<template>
  <div id="app">
    <textLink url="/#" v-slot:default="slotProps"> // templateタグを削除してコンポネートタグにv-slotが書ける
      <h2>{{ slotProps.title }}</h2>
      ここはリンクです!
    </textLink>
  </div>
</template>

textLink.vue

<template>
  <div>
    <a :href="url" class="nav-link">
      <slot title="タイトルリンクです!" /> // name="link"を消去
    </a>
  </div>
</template>

さらに、v-slot:default:defaultもなくして省略ができる。

<template>
  <div id="app">
    <textLink url="/#" v-slot="slotProps">
      <h2>{{ slotProps.title }}</h2>
      ここはリンクです!
    </textLink>
  </div>
</template>

以上、スロットの説明終わり。

The post 【初心者向け】Vue.jsのスロットの使い方 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/v-slot/feed/ 0
$nextTickでタイミングを遅延させて子コンポーネントにアクセスする https://blog.popweb.dev/programming/vue-js/nexttick/ https://blog.popweb.dev/programming/vue-js/nexttick/#respond Mon, 15 Jun 2020 07:35:00 +0000 https://blog.pop-web.net/?p=1337 mountedやupdatedを使用してもでは子コンポーネントを全てをマウントしたことは保証しないため、子コンポーネントへアクセスがうまくいかない時がある。 そこ解決するために、$nextTickを使用してDOMの更新サ […]

The post $nextTickでタイミングを遅延させて子コンポーネントにアクセスする first appeared on POPWEB.]]>
mountedやupdatedを使用してもでは子コンポーネントを全てをマウントしたことは保証しないため、子コンポーネントへアクセスがうまくいかない時がある。

そこ解決するために、$nextTickを使用してDOMの更新サイクル後に処理実行させるようにする。

  this.$nextTick(function () {
    // DOMの更新サイクル後に実行する処理
  })
The post $nextTickでタイミングを遅延させて子コンポーネントにアクセスする first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/nexttick/feed/ 0
Vue.jsエラー。gyp: No Xcode or CLT version detected! https://blog.popweb.dev/programming/vue-js/gyp-no-xcode-or-clt-version-detected/ https://blog.popweb.dev/programming/vue-js/gyp-no-xcode-or-clt-version-detected/#respond Wed, 10 Jun 2020 15:15:00 +0000 https://blog.pop-web.net/?p=1299 vue create <プロジェクト名>コマンドを入力すると以下のようなエラーがでた。 XcodeあるいはCLTのバージョンがおかしいらしい。 解決方法について GitHubのnode-gypにあったものを参 […]

The post Vue.jsエラー。gyp: No Xcode or CLT version detected! first appeared on POPWEB.]]>
vue create <プロジェクト名>コマンドを入力すると以下のようなエラーがでた。

gyp: No Xcode or CLT version detected!

XcodeあるいはCLTのバージョンがおかしいらしい。

解決方法について

GitHubのnode-gypにあったものを参考にした。

sudo rm -rf $(xcode-select -print-path)
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install

これで再度、vue create <プロジェクト名>コマンドを入力するとエラーも出ずにプロジェクトが作成された。

The post Vue.jsエラー。gyp: No Xcode or CLT version detected! first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/gyp-no-xcode-or-clt-version-detected/feed/ 0
Vue.jsの開発環境Vue CLIのインストールと初期設定 https://blog.popweb.dev/programming/vue-js/vue-cli-install/ https://blog.popweb.dev/programming/vue-js/vue-cli-install/#respond Mon, 08 Jun 2020 11:44:00 +0000 https://blog.pop-web.net/?p=1295 いつもはVue.jsのフレームワークであるNuxt.jsで開発を行なっているが、Vue CLIでの開発環境の構築をしてみる。 事前にNode.jsをインストールしておく。 目次 Vue CLIのインストールプロジェクトの […]

The post Vue.jsの開発環境Vue CLIのインストールと初期設定 first appeared on POPWEB.]]>
いつもはVue.jsのフレームワークであるNuxt.jsで開発を行なっているが、Vue CLIでの開発環境の構築をしてみる。

事前にNode.jsをインストールしておく。

Vue CLIのインストール

コマンドラインを起動して、Vue CLIをインストールする。

Vue CLIは基本どこでも使えるようにしたいので、グローバルインストールする。

よって、-gオプションをつけてインストールする。

npm install -g @vue/cli

終わったらバージョンの確認

vue --version
@vue/cli 4.4.1

プロジェクトの作成

以下のコマンドでプロジェクトを作成

vue create <プロジェクト名>

presetの選択肢がでるので、defaultを選択。

Vue CLI v4.4.1
? Please pick a preset: (Use arrow keys)
❯ default (babel, eslint)
  Manually select features

インストールが始まるので終わるまで待つ。

開発用サーバーの起動

以下の手順のコマンドで開発用サーバーを起動する。

cd <プロジェクト名>
npm run serve

http://localhost:8080/にアクセスし、ブラウザでVue CLIのデフォルト画面が表示されればOK。

The post Vue.jsの開発環境Vue CLIのインストールと初期設定 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/vue-cli-install/feed/ 0
【Nuxt.js コンポーネント間の循環参照】Unknown custom elementとなる原因と解決方法 https://blog.popweb.dev/programming/vue-js/nuxt-js-unknown-custom-element/ https://blog.popweb.dev/programming/vue-js/nuxt-js-unknown-custom-element/#respond Wed, 03 Jun 2020 13:41:51 +0000 https://blog.pop-web.net/?p=1288 Nuxt.jsで開発中に以下のエラーが出てハマった。 エラーメッセージにあるように、nameオプションで指定してもダメだった。 今回の場合、原因はコンポーネント間の循環参照の記述方法だった。 Vue.jsのドキュメントの […]

The post 【Nuxt.js コンポーネント間の循環参照】Unknown custom elementとなる原因と解決方法 first appeared on POPWEB.]]>
Nuxt.jsで開発中に以下のエラーが出てハマった。

[Vue warn]: Unknown custom element: <コンポーネント名> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

エラーメッセージにあるように、nameオプションで指定してもダメだった。

今回の場合、原因はコンポーネント間の循環参照の記述方法だった。

Vue.jsのドキュメントのコンポーネント間の循環参照に書いてあるように、記述方法には2通りある。

beforeCreaterequireを使ってコンポーネント登録するか、componentsフィールド内で importを使ってコンポーネント登録するかだ。

Nuxt.jsの場合では、requireの方でやると前述のエラーが出るが、importの方でやるとエラーは出ないようだ。

Nuxt.jsでエラーが出る記述

<script>
export default {
  // Nuxt.jsではエラー
  beforeCreate() {
    this.$options.components.Component = require("~/components/modal/Component.vue").default;
  }
};
</script>

Nuxt.jsでエラーが出ない記述

<script>
export default {
  // Nuxt.jsでもOK
  Component: () => import("~/components/modal/Component.vue")
};
</script>
The post 【Nuxt.js コンポーネント間の循環参照】Unknown custom elementとなる原因と解決方法 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/nuxt-js-unknown-custom-element/feed/ 0
Vue.jsの動的なコンポーネントの使い方 https://blog.popweb.dev/programming/vue-js/dynamic-component/ https://blog.popweb.dev/programming/vue-js/dynamic-component/#respond Mon, 01 Jun 2020 11:42:00 +0000 https://blog.pop-web.net/?p=1388 動的なコンポーネントについて説明する。 開発環境ははVue CLIを使っている前提で話を進めていく。 目次 動的なコンポーネントの記述方法kees-aliveでキャッシュする 動的なコンポーネントの記述方法 動的にコンポ […]

The post Vue.jsの動的なコンポーネントの使い方 first appeared on POPWEB.]]>
動的なコンポーネントについて説明する。

開発環境ははVue CLIを使っている前提で話を進めていく。

動的なコンポーネントの記述方法

動的にコンポーネントを切り替えるために、複数コンポーネントを用意しておく。

そして記述方法としては、<component>要素とisプロパティを以下のように設定する。

<component :is="currentComponent"></component>

currentComponentの変数名はなんでもいい、これにコンポーネント名を入れることで動的にコンポーネントを切り替えることができる。

例として、以下は3つのコンポーネントに切り替えるコード。

App.vue

<template>
  <div id="app">
    <button @click="currentComponent = 'Home'">Home</button>
    <button @click="currentComponent = 'Posts'">About</button>
    <button @click="currentComponent = 'Archive'">Archive</button>
    <component :is="currentComponent" />
  </div>
</template>

<script>
import Home from "./components/Home";
import Posts from "./components/Posts";
import Archive from "./components/Archive";

export default {
  components: {
    Home,
    Posts,
    Archive,
  },
  data() {
    return {
      currentComponent: "",
    };
  },
};
</script>

ブラウザで確認。

kees-aliveでキャッシュする

動的コンポーネントを使用した場合、コンポーネントを切り替えるとコンポーネントは一度破棄される。

破棄せずにキャッシュしたい場合は、<keep-alive>でラップすれば良い。

<keep-alive>
  <component :is="currentComponent" />
</keep-alive>

また、<keep-alive>を使用した場合、ライフサイクルフックとしてactivateddeactivatedが使える。

activatedは、<keep-alive>内部のコンポーネントが表示された時に呼びだれて、deactivatedは非表示になったときに呼び出される。

The post Vue.jsの動的なコンポーネントの使い方 first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/dynamic-component/feed/ 0
【初心者向け】Nuxt.jsでのVuexのクラシックモードとモジュールモードについて https://blog.popweb.dev/programming/vue-js/nuxt-js-vuex/ https://blog.popweb.dev/programming/vue-js/nuxt-js-vuex/#respond Thu, 07 May 2020 15:40:48 +0000 https://blog.pop-web.net/?p=1197 Nuxt.jsで状態管理を行うライブラリであるVuexのクラシックモードとモジュールモードについて説明。 目次 まず、新規Nuxtプロジェクトを作成VuexのデータフローについてState(ステート)Mutation(ミ […]

The post 【初心者向け】Nuxt.jsでのVuexのクラシックモードとモジュールモードについて first appeared on POPWEB.]]>
Nuxt.jsで状態管理を行うライブラリであるVuexのクラシックモードとモジュールモードについて説明。

まず、新規Nuxtプロジェクトを作成

以下、コマンドでテスト用にNuxtプロジェクトを作成しておく。

npx create-nuxt-app vuex-test

初期設定をどうするか聞かれるが、すべてEnterキーを押下して進めてOK。

Vuexのデータフローについて

VuexにはState、Mutation、Actionといったデータフローがある。

State(ステート)

ストアの状態を保持しているところ。

Vueコンポーネントから直接操作をすることはできない。

Mutation(ミューテーション)

Vuexストアの状態を唯一操作ができる。

Action(アクション)

Mutationを呼び出す役割をする。

外部とのAPI通信したい場合はここに書く。

また、非同期処理を書く時もここに書く。

Vuexの2つのモード

Vuexにはクラシックモードとモジュールモードの2つのモードがある。

  • クラシックモードは内容を1つのファイルで管理する。(store/index.js)
  • モジュールモードは内容を複数のファイルで管理する。(store/*.js)

大規模開発になるとモジュールモードで分けた方が管理しやすい。

また、クラシックモードは次のメジャーアップデートで廃止予定…

クラシックモードで利用

まずはStateを作成する。

State(ステート)を使う

storeディレクトリ配下にindex.jsを作成して以下のように編集。

import Vuex from 'vuex'

const helloWorld = () => {
  return new Vuex.Store({
    state: function () {
      return {
        message: 'Hello, World'
      }
    }
  })
}
export default helloWorld

state部分が状態を管理する値を設定するところ。

stateの値はfunctionにするのがルールで、その中に状態管理したいデータをオブジェクト形式で設定する。

pagesディレクトリのindex.vueを以下のように編集する。

<template>
  <div style="padding:20px;">
    <p>{{ $store.state.message }}</p>
  </div>
</template>

npm run devで開発モードで実行する。

ブラウザで確認し、「Hello, World」の表示ができればOK。

Mutation(ミューテーション)を使う

Mutationを使ってStateの値を変更する。

store/index.jsを編集する。

mutationsを追加する。

import Vuex from 'vuex'

const helloWorld = () => {
  return new Vuex.Store({
    state: function () {
      return {
        message: 'Hello, World'
      }
    },
    mutations: {
      updateData: function (state, payload) {
        state.message = payload
      }
    }
  })
}
export default helloWorld

functionに第二引数(payload)を設定するとは、Vueコンポーネントから値と受け取ることができる。

次に、index.vueにmutationsに処理をさせるボタンを設置する。

<template>
  <div style="padding:20px;">
    <p>{{ $store.state.message }}</p>
    <br />
    <button @click="$store.commit('updateData', 'send mutations')">
      mutations!
    </button>
  </div>
</template>

$store.commitの第二引数に渡したい値を入れる。

ブラウザで確認して、ボタンをクリックすると「send mutations」と表示が切り替わればOK。

Action(アクション)を使う

store/index.jsを編集する。

actionsを追加する。

import Vuex from 'vuex'

const helloWorld = () => {
  return new Vuex.Store({
    state: function () {
      return {
        message: 'Hello, World'
      }
    },
    mutations: {
      updateData: function (state, payload) {
        state.message = payload
      }
    },
    actions: {
      updateDataAction(context) {
        context.commit('updateData', 'send actions')
      }
    }
  })
}
export default helloWorld

次にindex.vueを編集してactionsを実行できるようにする。

$store.commit$store.dispatchに変更。

<template>
  <div style="padding:20px;">
    <p>{{ $store.state.message }}</p>
    <br />
    <button @click="$store.dispatch('updateDataAction')">
      actions!
    </button>
  </div>
</template>

ブラウザで確認して、ボタンをクリックすると「send actions」と表示が切り替わればOK。

さらに、$store.dispatchの第二引数に値を渡すこともできる。

index.vueを以下のように変更

<template>
  <div style="padding:20px;">
    <p>{{ $store.state.message }}</p>
    <br />
    <button @click="$store.dispatch('updateDataAction','add value')">
      actions!
    </button>
  </div>
</template>

store/index.jsでも値を受け取れるように設定。

import Vuex from 'vuex'

const helloWorld = () => {
  return new Vuex.Store({
    state: function () {
      return {
        message: 'Hello, World'
      }
    },
    mutations: {
      updateData: function (state, payload) {
        state.message = payload
      }
    },
    actions: {
      updateDataAction(context, payload) {
        context.commit('updateData', payload)
      }
    }
  })
}
export default helloWorld

ブラウザで確認して、ボタンをクリックすると「add value」と表示が切り替わればOK。

モジュールモードで利用

今まで記述してきたクラシックモードをモジュールモードに変換していく。

モジュールモードを有効になる条件として、store/index.jsをexportしないこと、又はstore/index.js自体が存在しないことがあげられる。

storeディレクトリ配下に、jsファイルをおくことモジュールとして自動登録される。

モジュール名も作成したファイル名となる。

モジュールモードのファイルを作成

storeディレクトリ配下にhelloworld.jsを作成し、クラシックモードからモジュールモードに書き換えるよう、以下のように編集する。

export const state = () => ({
  message: 'Hello, World'
})

export const mutations = {
  updateData: function (state, payload) {
    state.message = payload
  }
}

export const actions = {
  updateDataAction(context, payload) {
    context.commit('updateData', payload)
  }
}

次に、index.vueの編集もする。

<template>
  <div style="padding:20px;">
    <p>{{ $store.state.helloworld.message }}</p> //$store.stateの後に『helloworld.』を追加
    <br />
    <button
      @click="$store.dispatch('helloworld/updateDataAction', 'add value')" // 『helloworld/』を追加
    >
      actions!
    </button>
  </div>
</template>

最後にいらなくなった、store/index.jsを削除。

最後に、ブラウザで確認して、ボタンをクリックすると「Hello, World」が「add value」へと表示が切り替わればOK。

The post 【初心者向け】Nuxt.jsでのVuexのクラシックモードとモジュールモードについて first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/nuxt-js-vuex/feed/ 0
カスタムコンポーネントでのv-modelの動作について。中身の:valueと@inputを理解する https://blog.popweb.dev/programming/vue-js/custom-components-v-model/ https://blog.popweb.dev/programming/vue-js/custom-components-v-model/#respond Sun, 12 Apr 2020 04:29:00 +0000 https://blog.pop-web.net/?p=1157 v-modelは双方向データバインディングを行うディレクティブであるが、カスタムコンポーネントでv-modelを使う場合、少しややこしい。 目次 v-modelの中身の動作についてカスタムコンポーネントでv-modelを […]

The post カスタムコンポーネントでのv-modelの動作について。中身の:valueと@inputを理解する first appeared on POPWEB.]]>
v-modelは双方向データバインディングを行うディレクティブであるが、カスタムコンポーネントでv-modelを使う場合、少しややこしい。

v-modelの中身の動作について

まず、v-modelには、別の書き方がある。

以下の2つのinputタグのプロパティは同じ意味である。

<template>
  <div>
    <!-- 以下の2つは同じ動作をする -->
    <input v-model="exampleText" />
    <input :value="exampleText" @input="exampleText = $event.target.value" />

    <p>{{ exampleText }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      exampleText: ""
    };
  }
};
</script>

valueプロパティ(:value)とinputイベント(@input)の記述を一つにまとめたものがv-modelである。

ちなみに、こんな感じに複雑な構文をシンプルに分かりやすくまとめた構文を糖衣構文やシンタックスシュガーと呼ばれる。

カスタムコンポーネントでv-modelを使う場合

カスタムコンポーネントでv-modelを使う場合でも、v-modelの中身はvalueプロパティとinputイベントである。

以下の2つはコンポーネントは同じ動作になる。

<template>
  <div style="padding:10px;">
    <!-- 以下の2つは同じ動作をする -->
    <someComponent v-model="exampleText" />
    <someComponent
      :value="exampleText"
      @input="exampleText = $event"
    />
  </div>
</template>

実際に親コンポーネントと子コンポーネントを作成して動作確認をする。

親コンポーネント(index.vue)

<template>
  <div style="padding:10px;">
    <someComponent
      :value="exampleText"
      @input="exampleText = $event"
    />
  </div>
</template>

<script>
import someComponent from "../components/someComponent";

export default {
  components: {
    someComponent
  },
  data() {
    return {
      exampleText: ""
    };
  }
};
</script>

子コンポーネント(someComponent.vue)

<template>
  <div>
    <input
      :value="value"
      @input="$emit('input', $event.target.value)"
      type="text"
    />
    <p>{{ value }}</p>
  </div>
</template>

<script>
export default {
  props: ["value"]
};
</script>

子コンポーネントは、親のコンポーネントの:valueからpropsでデータを受け取る。そして{{ value }}で表示。

$emitの第一引数の「input」はで親コンポーネントにあるカスタムイベント@inputを指していて、これを発火させて「exampleText」に「$event」を代入している。

$eventの中身は、子コンポーネントの第二引数の値が入っている。

これで、子コンポーネントで入力されたデータを親コンポーネントに渡すことができる。

プロパティ名やカスタムイベント名を変更したい時

カスタムコンポーネントでv-modeを使用した場合、デフォルトでプロパティ名はvalueとなり、カスタムイベント名はinputとなる。

これらを変更したい時は、子コンポーネントの方でmodelオプションを使う。

さっきのソースコードではテキストボックスだったが、チェックボックスに変更する。

ここでは、プロパティ名をcheckedとし、カスタムイベント名をchangeとした。

親コンポーネント(index.vue)

<template>
  <div style="padding:10px;">
    <someComponent v-model="checkBox" />
  </div>
</template>

<script>
import someComponent from "../components/someComponent";

export default {
  components: {
    someComponent
  },
  data() {
    return {
      checkBox: false
    };
  }
};
</script>

子コンポーネント(someComponent.vue)

<template>
  <div>
    <input
      :checked="checked"
      @input="$emit('change', $event.target.checked)"
      type="checkbox"
    />
    <p>{{ checked }}</p>
  </div>
</template>

<script>
export default {
  model: {
    prop: "checked",
    event: "change"
  },
  props: ["checked"]
};
</script>

まとめると、カスタムコンポーネントでv-modelを使う場合、親コンポーネントと子コンポーネントとの間で具体的にどういったデータのやり取りをしているかを意識する必要があるということ。

The post カスタムコンポーネントでのv-modelの動作について。中身の:valueと@inputを理解する first appeared on POPWEB.]]>
https://blog.popweb.dev/programming/vue-js/custom-components-v-model/feed/ 0