20190929のvue.jsに関する記事は9件です。

VSCodeでVue.jsのモダンな開発環境を整えよう

はじめに

みなさん、Visual Studio Code(以下VSCode)使ってますか?VSCodeはかなりの頻度で開発されており、色々と便利な機能が随時アップデートされているので、多くの現場で使われていることだと思います。今回は、VSCodeを使って、Vue.jsの開発環境の設定についてご紹介します。主にデバッグの部分に軸をおいて解説していますので、VSCodeでVue.jsの開発をされている方には有益な情報になるかと思います。

では、早速はじめましょう。
\(^o^)/

前提条件

検証している環境は下記になります。

環境 バージョン
OS Mac OS Mojave
vue cli 3.11.0
VSCode 1.38.1
Node.js 10.15.3

事前に下記のインストールが済んでいる前提となりますので、インストールがまだの場合は、インストールをお願いします。

  • Node.js
  • npm
  • yarn
  • Vue CLI
  • VSCode
  • Google Chrome

環境構築

VSCodeにプラグインを追加

VSCodeに必要なプラグインを追加します。
プラグインの追加方法は解説しておりませんので、別途別の資料を参照頂ければ幸いです。

Vue.js Extension Pack
リンク
Vue.jsでよく使うプラグインをまとめたもの。

Debugger for Chrome
リンク
Javascriptのデバッグをするためのプラグイン。
使い方は後ほど解説します。

Google Chromeに拡張機能を追加

Google Chromeに必要な拡張機能を追加します。
拡張機能の追加方法は解説しておりませんので、別途別の資料を参照頂ければ幸いです。

Vue.js devtools
リンク
Vue.jsのサイトのデバッグをするためのツール。
使い方は後ほど解説します。

Vueのテンプレートを作成

# Vue.jsのテンプレートを作成する
$ vue create my-app

# 下記選択肢が表示されるので、「Manually select features」を選択しEnter
Vue CLI v3.11.0
? Please pick a preset:
  default (babel, eslint)
❯ Manually select features

# 下記選択肢が表示されるので、「Babel」、「TypeScript」、「Router」、「Vuex」、「Linter / Formatter」を選択し、Enter
(選択はSPACEキーで可能です)
? Check the features needed for your project:
 ◉ Babel
 ◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◯ CSS Pre-processors
❯◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

# 下記の様に聞かれるので、「n」を入力し、Enter
? Use class-style component syntax? (Y/n) n

# 下記のように聞かれるので、「y」を入力し、Enter
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) y

# 下記のように聞かれるので、「y」を入力し、Enter
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) y

# 下記のように聞かれるので、「TSLint」を選択し、Enter
? Pick a linter / formatter config: (Use arrow keys)
❯ TSLint
  ESLint with error prevention only
  ESLint + Airbnb config
  ESLint + Standard config
  ESLint + Prettier

# 下記のように聞かれるので、「Lint additional lint features」を選択し、Enter
? Pick additional lint features:
❯◉ Lint on save
 ◯ Lint and fix on commit

# 下記のように聞かれるので、「In dedicated config files」を選択し、Enter
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files
  In package.json

# 下記のように聞かれるので、「n」を入力し、Enter
? Save this as a preset for future projects? (y/N) n

# 最終的には以下のようになっているはず
Vue CLI v3.11.0
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, Vuex, Linter
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a linter / formatter config: TSLint
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N) n

$ cd my-app
$ yarn serve

ブラウザに「http://localhost:8080/」を入力し、下記画像のようにVue.jsのページが表示されることを確認して下さい。

my-app_と_node.png

VSCodeでVue.jsのデバッグを行う

# my-app内にいることを必ず確認した後、コマンドを実行して下さい。
$ yarn add axios

まず、先程作成したmy-appをVSCodeで開いて下さい。
HelloWorld.vueを開いて、<script>タグ内を下記コードで上書きして下さい。
郵便番号から住所を取得する処理を追加しております。

HalloWorld.vue(抜粋)
import Vue from 'vue';
import axios from 'axios';

export default Vue.extend({
  name: 'HelloWorld',
  props: {
    msg: String,
  },
  created: async ()=>{
    const response = await axios.get('https://api.zipaddress.net/?zipcode=6048151')
    window.console.log(response);
  }
});

最終的には下記のようになるかと思います。

HelloWorld_vue_—_my-app.png

次に、下記画像のようにして、44行目にブレークポイントを設定して下さい。

HelloWorld_vue_—_my-app.png

では、デバッグを実行していきましょう。
左のアイコンの中からデバッグアイコン(虫の形)をクリックして下さい。

my-app.png

「構成がありません」の右側にある、歯車アイコンをクリックして下さい。
ポップアップが表示されますので、「Chrome」をクリックして下さい。

my-app.png

「デバッグ」の右にある緑三角をクリックして下さい。(下記画像参照)

launch_json_—_my-app.png

Google Chromeでページが開くので、上部にある「About」をクリック後、「Home」をクリックして下さい。
(下記画像参照)
もしページが開かない場合は、バックグラウンドでyarn serveコマンドが実行されている必要がありますので、実行されているかどうかを確認下さい。

my-app.png

すると、下記画像のようにデバッグ画面に遷移するかと思います。

HelloWorld_vue_—_my-app.png

左の「変数」の部分では、変数の中身を見ることが出来ます。
中央上部のツールパネルでは、処理を進めたりなどの操作が可能です。
中央の黄色い背景の部分(44行目)で、処理がストップしている事がわかります。

HelloWorld_vue_—_my-app.png

ツールパネルについて、少し説明します。
アイコンが6個あるかと思いますが、左から順番に下記意味となります。

  • 続行
  • ステップオーバー
  • ステップイン
  • ステップアウト
  • 再起動
  • 停止

では、ツールパネルの一番左にある「続行」をクリックして下さい。
(下記画像参照)

HelloWorld_vue_—_my-app.png

すると、変数responseの中身が表示されています。
京都の郵便番号を入れているので、京都の住所がAPIで取得できていることがわかります。
(下記画像参照)

HelloWorld_vue_—_my-app.png

メモ

本来であれば、createdの中の処理は、画面を初回に表示した際にブレークポイントで止まってほしいのですが、なぜかそうなりませんでした。また、一度目にブレークポイントで止まったときには、responseには値が入っていません。このあたりの挙動は、Vue.jsのバックグラウンドのロジックが関係しているのかもしれないのですが、詳細にはわかりませんでした。もし詳しい方がいらっしゃいましたら、コメントでご教授頂ければ幸いです。

Vue.js devtoolsでVue.jsでVue.jsのデバッグを行う

ブラウザに「http://localhost:8080/」を入力し、ページを開きます。
デベロッパーツールを開きます。(Macの場合は、Command+Option+i)
メニューの右側にある「Vue」をクリックします。(下記画像参照)

my-app.png

Vueのパネルを開くと、Vueの構造が表示されます。(下記画像参照)

DevTools_-_localhost_8080__と_my-app.png

試しに、HelloWorldコンポーネントを開いてみましょう。
propsで渡ってきた値やdata属性の中身などを見ることが出来ます。

DevTools_-_localhost_8080_.png

date属性、propsの値も変更することが可能です。
propsの値を変更するためには、設定の変更が必要になります。(下記画像参照)
これは非常に便利ですね。

DevTools_-_localhost_8080__と_my-app.png

DevTools_-_localhost_8080_.png

Vuexとして保存されているデータを確認することも出来ます。
今回は何も保存していませんので、値は表示されていませんが、Vuexを利用している場合は確認することが出来ます。

DevTools_-_localhost_8080__と_Releases_·_vuejs_vue.png

次にイベントの表示です。
emitで発行したイベントの履歴を見ることが出来ます。
今回はemitを使っていないので何も表示されていませんが、emitを使う場合は、自分の想定しているタイミングでイベントが実行されているかを確認することが出来ます。

DevTools_-_localhost_8080__と_「VSCodeでVue_jsのモダンな開発環境を整えよう」を編集_-_Qiita.png

次にルーターの表示です。
ルーターの遷移履歴、ルーターのパス一覧を見ることが出来ます。

DevTools_-_localhost_8080__と_「VSCodeでVue_jsのモダンな開発環境を整えよう」を編集_-_Qiita.png

DevTools_-_localhost_8080_.png

終わりに

今回の記事で、Vue.jsの開発環境、デバッグ手法についての基礎は解説できたのかなと思っています。デバッグは非常に難しいので、ツールに頼れる部分はどんどんツールに頼っていくのが効率の良い開発に繋がるのではないでしょうか。この記事が少しでも皆さんの開発、デバッグの助けになれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsをTypeScriptと使うメモ -設定-(@vue/cliは使わずに)

設定

必要なpackageを取得

npm install vue-property-decorator
npm install --save-dev typescript webpack webpack-merge

tsconfig(基本的に推奨構成より)

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "strict": true,
    "moduleResolution": "node",
    "noImplicitAny": true,  // 暗黙のany
    "strictNullChecks": true,  //nullやundefinedを明示するように
    "noImplicitThis": true,
    "moduleResolution": "node",
    // importのpathを./src/...から@src/...に
    "paths": {
      "@src/*": ["src/*"]
    }, 
    "include": [
      "./src/**/*.ts"
    ]
  }
}

includeなどは自分の設定に合わせて…

webpack設定

webpack.common.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const webpack = require('webpack')

module.exports = {
  entry: {
    app: ["./src/index.ts"]
  },
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "public/js")
  },
  resolve: {
    extensions: [".js", ".ts", ".vue", ".json", ".css"],
    alias: {
      vue$: "vue/dist/vue.esm.js",
      // importのpathを./src/...から@src/...に
      '@src': path.resolve(__dirname, './src')
    },
    modules: ["node_modules"]
  },
  plugins: [
    new VueLoaderPlugin(),
  ]
}

開発用のビルドと本番用のビルドで分けたりする。(sourcemap出力したり)

webpack.dev.js
// 開発ビルド用
const merge = require('webpack-merge')
const common = require('./webpack.common.js')

module.exports = merge(common, {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        loader: 'vue-loader',
        options: {
          cssModules: {
            camelCase: true
          }
        }
      },
      {
        test: /\.ts$/,
        exclude: '/node_modules/',
        use: [
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/]
            }
          }
        ]
      },
    ]
  }
})


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxtから利用したChart.jsでイベントを発行する

はじめに

以前書いたNuxtでChart.jsを利用するで実装したdoughnut-chartにて、hover時とレンダリング完了時にそれぞれイベントが発行されるよう改修しました。

hoverイベントを発行

doughnut-chartはChart.jsのDoughnut Chartを利用しており、hover時に処理を実行するためにはoptions.onHoverにコールバック関数を渡すことで可能となります。
https://www.chartjs.org/docs/latest/general/interactions/events.html

そのため、doughnut-chartではコールバック関数をコンポーネントのメソッドとして実装し、renderChart時にonHoverプロパティの値として定義することとしました。

plugins/vue-chartjs.js
  // ・・・省略
  mounted() {
    this.renderChart(this.chartData, { onHover: this.hover, ...this.options });
  },
  methods: {
    hover: function(point, event) {
      const element = event[0] || null;
      if (element === null) {
        return;
      }
      this.$emit('hover', element._index);
    },
  },
});

実装したhoverメソッドでは2つの引数pointeventを受け取り、これらにはそれぞれMouseEventChartElementが渡されます。
ChartElementにはlabelやvalueをはじめとするChart情報が含まれており、今回はその中のindex情報を利用することとしました。
this.$emitにてカスタムイベントを発行することが可能なため、hoverイベントを発行しindexを返却しております。

plugins/vue-chartjs.js
<template>
  <v-container fluid>
    <doughnut-chart :chart-data="chartData" :options="chartOptions" @hover="hover"/>
    // ・・・省略
  </v-container>
</template>

<script>
  // ・・・省略
  methods: {
    // ・・・省略
    hover: function(index) {
      console.log(index);
    },
  },
};
</script>

doughnut-chartにてhoverイベントを発行するよう実装したため、呼び出し側からは上記のようにevent handlerをメソッドにて実装し、@hover="event handler名"にてイベントを受け取ることが可能となります。

renderedイベントを発行

次にレンダリングが完了した際にイベントを発行するようdoughnut-chartを改修します。
Chart.jsのDoughnut Chartでは、options.animation.onCompleteにコールバック関数を渡すことでレンダリング完了時に処理を実行することが可能です。
https://www.chartjs.org/docs/latest/configuration/animations.html

そこでhoverイベントの発行時と同様にoptionsプロパティにコールバック関数をdefault値として渡すことで実装しようと試みたのですが、onCompleteanimationオブジェクトのプロパティであり一つネストした階層に定義する必要があるため、新たに算出プロパティoptionsMergedDefaultEventsを実装し、そこでdefaultのイベントをpropsで渡されたoptionsにmergeするようにしました。

plugins/vue-chartjs.js
  // ・・・省略
  computed: {
    optionsMergedDefaultEvents: function() {
      let options = this.options;
      const animation = this.options.animation || {};
      options.animation = {
        onComplete: this.rendered,
        ...animation,
      };

      options = {
        onHover: this.hover,
        ...options,
      };

      return options;
    },
  },
  mounted() {
    this.renderChart(this.chartData, this.optionsMergedDefaultEvents);
  },
  methods: {
    // ・・・省略
    rendered: function() {
      this.$emit('rendered');
    },
  },
  // ・・・省略

上記により、レンダリング完了時もhoverイベントと同様に呼び出し側から@rendered="event handler名"にてイベントを受け取ることが可能となりました。

plugins/vue-chartjs.js
<template>
  <v-container fluid>
    <doughnut-chart :chart-data="chartData" :options="chartOptions" @hover="hover" @rendered="rendered"/>
    // ・・・省略
  </v-container>
</template>

<script>
  // ・・・省略
  methods: {
    // ・・・省略
    rendered: function() {
      console.log('rendered');
    },
  },
};
</script>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

250行のVue.jsで陣取りゲームを作った

こんにちは、猫チーズです。

jintori.gif

黒色:ユーザー
灰色:自陣
赤色:敵
白色:敵陣
茶色:縄(自陣を広げるためのもの)

前回書いた記事『200行のVue.jsでスネークゲームを作った』が中々反響良さそうでしたので、Vue.js勉強用ゲーム 第2弾として陣取りゲームを作ってみました。

十数年前に何かのゲーム機で遊んだこのゲームを、うろ覚えで再現しています。
もし本家を知っている方いましたら教えてください!

デモページ

https://miyauchiakira.github.io/vue-game-jintori/

GitHub ソースコード

https://github.com/miyauchiakira/vue-game-jintori

ゲームルール

  1. 自陣の中では矢印キーで自由に動き回れる
  2. 敵陣に入ると、縄を張りながらまっすぐ進む
  3. 縄を張ったまま自陣に戻ると、自陣が増える
  4. 敵が縄にぶつかるとゲームオーバー
  5. 自陣を増やすとスコアUP

これらのルールをVue.jsで作りました。

250行のプログラム

以下の250行のhtmlファイルに全ての機能が纏まっています。
jintori.htmlなどの名前で保存して、ブラウザでそのファイルを開くと遊べます。
機能の改造などをして遊んでみてください。

jintori.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>陣取りゲーム</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

    <style>
        /* グリッドレイアウト */
        #grid {
            display: grid;
            grid-template-columns: repeat(20, 20px);    /* 横20マス 幅20px */
            grid-template-rows: repeat(20, 20px);   /* 縦20マス 高さ20px */
        }

        /* セルの色 */
        .cell {
            border: 1px solid white;
            background: whitesmoke;
        }

        /* ユーザーの陣地の色 */
        .cell.area {
            background: darkgray;
        }

        /* ロープの色 */
        .cell.lope {
            background: burlywood;
        }

        /* ユーザーの色 */
        .cell.user {
            background: black;
        }

        /* 敵の色 */
        .cell.enemy {
            background: orangered;
        }
    </style>
</head>
<body>
    <div id='app'>
        <p>SCORE: {{ score }}</p>

        <div id='grid'>
            <!-- セルを400個生成して、必要に応じてuser, area, lope, enemyクラスを付ける -->
            <!-- (注意:Vueは v-for="i in 数値" としたとき、iが1から始まる) -->
            <div v-for="i in grid.width * grid.height"
                 :class="{
                     cell: true,
                     area: user.area_indexes.includes(i - 1),
                     lope: user.lope_indexes.includes(i - 1),
                     user: user_index === i - 1,
                     enemy: enemy_index === i - 1,
                 }"
            ><!--{{ i - 1 }}--></div>
        </div>

        <p v-if='is_gameover'>
            GAME OVER<br>
            <button onclick="location.reload()">RETRY</button>
        </p>
    </div>

    <script>
        new Vue({
            el: '#app',

            data: {
                speed: 200, // 1マス進むのにかかる時間[ms]

                // グリッドのデータ
                grid: {
                    width: 20,  // 横20マス
                    height: 20, // 縦20マス
                },

                // ユーザーのデータ
                user: {
                    pos: { x: 0, y: 0 },    // 位置座標
                    direction: { dx: 1, dy: 0 },    // 進行方向(初期値は右)
                    area_indexes: [],   // ユーザーの陣地(インデックスの配列)
                    lope_indexes: [],   // ロープ(インデックスの配列)
                },

                // 敵のデータ
                enemy: {
                    pos: { x: 10, y: 10 },          // 位置座標
                    direction: { dx: -1, dy: 1 },   // 進行方向(初期値は左下)
                },
            },

            // 初期化
            created() {

                // 上下左右端をユーザーのエリアにする
                for(let x = 0; x < this.grid.width; x++) {
                    for(let y = 0; y < this.grid.height; y++) {
                        const is_side = x === 0 || x === this.grid.width - 1 || y === 0 || y === this.grid.height - 1

                        if(is_side) {
                            this.user.area_indexes.push(this.pos2index({x, y}))
                        }
                    }
                }

                // キーボード入力のイベントをon_keydownメソッドに投げる
                document.onkeydown = () => {
                    this.on_keydown(event.keyCode)
                }

                // 時間を動かし始める
                this.time_goes()
            },

            computed: {

                // スコア = ユーザーのエリアの量(初期の領域を除く)
                score() {
                    return this.user.area_indexes.length - this.grid.width * 2 - this.grid.height * 2 + 4
                },

                // ユーザーの座標をインデックスに変換
                user_index() {
                    return this.pos2index(this.user.pos)
                },

                // 敵の座標をインデックスに変換
                enemy_index() {
                    return this.pos2index(this.enemy.pos)
                },

                // ゲームオーバーの条件
                is_gameover() {
                    return this.user.lope_indexes.includes(this.enemy_index)
                },
            },

            methods: {
                // 時間を進める
                time_goes() {
                    if(this.is_gameover) return
                    this.forward_user()
                    this.forward_enemy()

                    setTimeout(this.time_goes.bind(this), this.speed)   // speedミリ秒後に自分自身を呼び出す
                },

                // 受け取った座標をインデックスに変換する
                pos2index({x, y}) {
                    return this.grid.width * y + x
                },

                // ユーザーを進める
                forward_user() {
                    const old_pos = { ...this.user.pos }

                    // directionの分だけ移動させる
                    this.user.pos.x += this.user.direction.dx
                    this.user.pos.y += this.user.direction.dy

                    const pos_owner = this.get_cell_owner(this.user.pos)    // 現在地の所有者

                    // 現在地が場外なら、位置座標を巻き戻す
                    if(pos_owner === 'frameout') {
                        this.user.pos = old_pos
                        return
                    }

                    // 現在地が敵陣の中なら、ここにロープを追加
                    if(pos_owner === 'enemy') {
                        this.user.lope_indexes.push(this.user_index)
                    }

                    // ロープを伸ばしたままユーザーの陣地まで辿り着いた場合
                    if(pos_owner === 'user' && this.user.lope_indexes.length) {

                        const enemy_area = this.get_enemy_area()

                        // 敵エリア以外のエリアをユーザーのエリアにする
                        this.user.area_indexes = []
                        this.user.lope_indexes = []
                        for(let x = 0; x < this.grid.width; x++) {
                            for(let y = 0; y < this.grid.height; y++) {

                                // このセル(x, y)が敵の陣地か否か
                                const is_enemy_area = enemy_area.left <= x && x <= enemy_area.right && enemy_area.top <= y && y <= enemy_area.bottom

                                if(is_enemy_area) continue
                                this.user.area_indexes.push(this.pos2index({x, y}))
                            }
                        }
                    }
                },

                // 敵を進める
                forward_enemy() {
                    const { pos, direction } = this.enemy

                    // ユーザーのエリアにぶつかるなら跳ね返す
                    const is_collided_x = this.get_cell_owner({ x: pos.x + direction.dx, y: pos.y }) === 'user'
                    const is_collided_y = this.get_cell_owner({ x: pos.x, y: pos.y + direction.dy }) === 'user'
                    if(is_collided_x) direction.dx *= -1    // 進行方向を左右反転
                    if(is_collided_y) direction.dy *= -1    // 進行方向を上下反転

                    // directionの分だけ移動させる
                    pos.x += direction.dx
                    pos.y += direction.dy
                },

                // 指定したセルの所有者を取得する
                get_cell_owner({x, y}) {
                    if(x < 0 || this.grid.width <= x || y < 0 || this.grid.height <= y) return 'frameout'
                    if(this.user.area_indexes.includes(this.pos2index({x, y}))) return 'user'
                    if(this.user.lope_indexes.includes(this.pos2index({x, y}))) return 'lope'
                    return 'enemy'
                },

                // 敵陣地の範囲(left, top, right, bottom)を取得する
                get_enemy_area() {
                    const { x, y } = this.enemy.pos
                    const area = { left: x, top: y, right: x, bottom: y }   // 初期値 = 敵自身の座標

                    // 上下左右それぞれの方向で敵陣地の範囲を調べる
                    while(this.get_cell_owner({x: area.left - 1, y}) === 'enemy') area.left--
                    while(this.get_cell_owner({x: area.right + 1, y}) === 'enemy') area.right++
                    while(this.get_cell_owner({x, y: area.top - 1}) === 'enemy') area.top--
                    while(this.get_cell_owner({x, y: area.bottom + 1}) === 'enemy') area.bottom++

                    return area
                },

                // キー入力を受け取ってユーザーの進行方向を変える
                on_keydown(keyCode) {
                    if(this.get_cell_owner(this.user.pos) !== 'user') return    // ユーザーのエリア外では方向転換できない

                    switch(keyCode) {
                        case 37: this.user.direction = {dx: -1, dy: 0}; break   // 「←」キーが押された
                        case 38: this.user.direction = {dx: 0, dy: -1}; break   // 「↑」キーが押された
                        case 39: this.user.direction = {dx: 1, dy: 0}; break    // 「→」キーが押された
                        case 40: this.user.direction = {dx: 0, dy: 1}; break    // 「↓」キーが押された
                    }
                },
            },
        })
    </script>
</body>
</html>

以下の機能は私が今思いついたものですが、よければ機能追加してみてください。難易度順です。
・スピードを速くする
・配色を変える
・マップのサイズを変える
・経過時間を表示
・敵の出現位置をランダムにする
・敵を増やす

猫チーズ

高校一年の頃からアプリ作りに没頭していて、今はアプリクリエイターとして生きるために奮闘中です。
今年の4月からサイバーブレイン株式会社でデザイナーを始めました。

Hello 猫チーズ | 猫チーズと擬似会話ができるブログ
https://blog.miyauchi-akira.app/post/20190927/

Twitter | 猫チーズ
https://twitter.com/miyauchoi

ポートフォリオ | ミヤウチアキラ
https://miyauchi-akira.app

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vuetify】<v-app-bar>を<v-content>にかぶらないようにする

はじめに

<v-app-bar>において特に属性を指定せずに<v-content>を用いると以下のようにページをロードした初期画面において<v-content>領域が<v-app-bar>領域を隠してしまうので、解決方法を紹介する。
スクリーンショット 2019-09-29 17.04.36.png

解決方法

app属性を指定する。

<template>
  <v-app>
    <v-app-bar app>
      ...
    </v-app-bar>
...
</template>

おわりに

こちら(公式)を参考。
最近Vuetifyを触り始めたのだが、公式サイトの情報のわかりやすさに感心した。ただ各コンポーネントの属性値などの日本語紹介は公式サイトではまだ一部しか書かれておらず本題の方法が未記入だったため、こちらに投稿する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue.js methodsやcomputedを共通化(mixin)する

methodsやcomputedを共通化(mixin)する

参考にしました。
https://qiita.com/_katomasa/items/7d0732306590e2831c0e

手順

1
共通化したいmethodsやcomputed等を記述したファイルを作成する。

例として utils.js を作成します。

パスは javascript/packs/mixins/utils.js とします。

以下は、moment.jsで日時をparseする関数です。

utils.js
import moment from 'moment'

export default {
  methods: {
    startParse: function(start) {
      return moment(start).format('YYYY-MM-DD')
    },
    endParse: function(end) {
      return moment(end).format('YYYY-MM-DD')
    }
  }
}

2
1のmethodsを使用するコンポーネントに以下を記述

some_component.vue
export default {
  import utilsMixin from utils.jsへのパス
  mixins: [utilsMixin] // 上記mixinを使用する宣言
}

3
こうすると、2のコンポーネント内で、1で定義したmethodsを使用することが出来る。

some_component.vue
<td>{{ startParse(task.start) }}</td>
<td>{{ endParse(task.end) }}</td>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nuxt.js + axiosで非同期データ通信ハンズオン風

ここで言う非同期データ通信とは

  • apiサーバからデータを取得してページ上に表示することとします。

前提

  • npm v5.2.0以上がローカルまたは開発環境に入っていること

プロジェクト作成

create-nuxt-app [プロジェクト名]
  • こんな感じで選択(Axiosを選択)
    スクリーンショット 2019-09-29 9.49.23.jpg

  • package.jsonaxiosが入っていることを確認

package.json
{
  "name": "async-test",
  "version": "1.0.0",
  "description": "My supreme Nuxt.js project",
  "author": "yosuke0517",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
  },
  "dependencies": {
    "nuxt": "^2.0.0",
    "@nuxtjs/axios": "^5.3.6"
  },
  "devDependencies": {
    "@nuxtjs/eslint-config": "^1.0.1",
    "@nuxtjs/eslint-module": "^1.0.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^6.1.0",
    "eslint-plugin-nuxt": ">=0.4.2"
  }
}

動作確認(とりあえずデフォでOK)

スクリーンショット 2019-09-29 9.54.52.jpg

学習で使うデータを作る

JSONPlaceholderというWebサービスを使用。実際の実務でもデータを用意するコストを省くことができる。

  • 今回はusers/のデータで実施する
    スクリーンショット 2019-09-29 9.59.03.jpg

  • 以下のURLでアクセスすると擬似的なusersのデータを取得できる

https://jsonplaceholder.typicode.com/users

スクリーンショット 2019-09-29 10.01.18.jpg

データを取得して表示する

  • index.vueの余計な箇所を削除し先ほどのurlから単純にデータを取得し表示(以下のようになっていればOKでstyleタグは削除)
index.vue
<template>
  <div class="container">
    <div>
      {{ users }}
    </div>
  </div>
</template>

<script>
const axios = require('axios')
const url = 'https://jsonplaceholder.typicode.com/users'

export default {
  asyncData ({ params }) {  //コンポーネントを初期化する前に非同期処理を行えるようにするメソッド
    return axios.get(url) //apiからのデータ取得をリクエスト
      .then((res) => {  //thenはレスポンスを受け取った段階で呼ばれるメソッド(res)にはレスポンスデータが入っている
        return { users: res.data } //res.dataにはjsonオブジェクトが入っている
      })
  }
}
</script>

  • 結果 スクリーンショット 2019-09-29 10.21.26.jpg

1人分のデータを取り出して表示する

  • 考え方
    • 配列となっているためインデックスを指定したりキーを指定したりするだけ
index.vue
{{ users[0] }}

とか

index.vue
{{ users[0].id }},{{ users[0].name }}

とか

  • 結果 スクリーンショット 2019-09-29 10.39.39.jpg

v-forで複数のデータをリストで表示する。

  • 考え方
    • v-forを使う
index.vue
<!--{{ users[0].id }},{{ users[0].name }}-->
      <ul>
        <li v-for="user in users" :key="user.id">
          {{ user.id }},{{ user.name }}
        </li>
      </ul>
  • 結果 スクリーンショット 2019-09-29 10.45.17.jpg

エラーハンドリング

  • 状況

    • 404エラーが発生したとする
  • index.vue内のurlを存在しないurlへ変更

    • 例)const url = 'https://jsonplaceholder.typicode.com/usersxxx'
  • 考え方

    • 引数にerrorを入れてcatchメソッドで処理する
index.vue
export default {
  asyncData({ params, error }) {
    return axios.get(url) 
      .then((res) => {
        return { users: res.data }
      })
      .catch((e => {
        //errorメソッドにはステータスコードと表示するメッセージを指定する
        error({ users: e.response.status, message: '404Error!!!!!' })
      }))
  }
}

とりあえず以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

plunkerでvue その37

概要

plunkerでvueやってみた。
練習問題やってみた。

練習問題

XMLを読んで

成果物

http://embed.plnkr.co/OZBXg3xksMECcPIdsbwD/

以上。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

plunkerでvue その36

概要

plunkerでvueやってみた。
練習問題やってみた。

練習問題

スネークゲームを設置して

参考したページ

https://qiita.com/miyauchoi/items/f753e5fa0209ab2034dd

成果物

http://embed.plnkr.co/fcOo3VltiOqsexYdrBFF/

以上。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む