20190724のvue.jsに関する記事は11件です。

LaravelのControllerで生成・加工したデータをVue.jsのテンプレートファイルで利用する方法

はじめに

LaravelとVue.jsでちょっとしたアプリを作っていた時に、LaravelのControllerで生成・加工したデータをVue.jsのテンプレートファイルに渡して使用するには下記の手順でデータを渡す必要がありましたので今後必要になった時に直ぐに思い出せる様にまとめたいと思います。

Controller→View(Bladeファイル)→Vue(Vue.jsテンプレート)

前提とするデータ構成

とある店舗情報を格納するデータをDB等から取得して下記の多次元配列としてControllerで整形したと想定します。
*Controllerでの細かいデータの取得・加工処理については本記事では割愛します。

array(5){
  0 => array(5)
  1 => array(5)
  2 => array(5)
  3 => array(5)
  4 => array(5) 
}

valueである各配列の中身は下記の様な形式のデータとします。

array(5){
    'shopId' => "testId1",
    'shopName' => "testShop1",
    'price' => "1000",
    'shopTel' => "1234-5678-90",
    'shopMessage' => array('short' => "test shot message",
                        'long' => "test long message"
    ),
    'shopImage' => array('url1' => "https://example.com/sample1.jpg",
                        'url2' => "https://example.com/sample2.jpg"
    )
}

Controller

順を追って、まずはControllerから流れを見て行きます。

上記の店舗情報データを$sampleDataとします。

この$sampleDataをVueファイルで配列の様に扱うにはjsonエンコーディングを行いオブジェクト化する必要があります。

$shopData = json_encode($sampleData);

viewを指定する箇所を含めると下記の様な具合になります。

app/Http/Controllers/SampleController.php

public function index()
{

    /*** データの加工処理は省略 ***/

    // 配列のjsonエンコード化
    $shopData = json_encode($sampleData);

    // viewファイルに$shopDataを渡す
    return view('index')->with('shopData', $shopData);
}

View

次はViewファイルを見て行きます。

bodyタグ内を下記の通り記述して行きます。

resources/views/index.blade.php

<main id="app">
    <shop-page v-bind:shop-data="{{ $shopData }}"></shop-page>
</main>

shop-pageタグがVueテンプレートの内容を反映する箇所です。
このshop-pageタグにControllerから受け取ったデータをバインド(結びつける)します。
「v-bind」属性(ディレクティブ)でバインドを行います。
v-bindで指定した「shop-data」がVueテンプレート内にてControllerから来た$shopDataのデータを受け持つことになります。
Vueテンプレート内ではキャルメルケースのshopDataと言う名前でデータが利用されることになります。

Vueテンプレート

Vueテンプレートの中身は下記の通りです。

resources/components/ShopPage.vue

<template>
    <div class="card text-white bg-dark mb-3" v-for="shop in shopData">
        <div class="row no-gutters">
            <img class="card-img" :src="shop.shopImage.url1" alt="no image">
            <div class="card-body">
                <h3 class="card-title">{{ shop.shopName }}</h3>
                <p class="card-text">{{ shop.shopMessage.short }}</p>
            </div>
        </div>
    </div>
</template>


<script>
    export default {
        props: {
            shopData: {
                type: Object
            },
        },
       name:'shop-page'
   }
</script>

scriptタグ内のprops(プロパティ)に記載されているshopDataがbladeファイル内での$shopDataになります。
型にObject型を指定する必要があります。

データの利用例として、templateタグ内で店舗情報をBootstrapのcardで表示するコードを記載しています。

for文の要領で店舗情報ごとにcardを作成するには一番外側のcardクラスが指定されたdivタグ内でv-forディレクティブを設定する方法があります。
下記の通りに指定することでforeach文の様に各店舗情報のオブジェクトを抽出することが出来ます。

v-for="shop in shopData"

今回のデータ構成ではkeyの値を参照する必要の無い作りになっている為「v-for」ディレクティブでkeyの値を取得していませんが、もし必要な場合は下記の通りに記載する必要があります。

v-for="(shop, key) in shopData"

「shop」はControllerで生成したの店舗ごとの情報をまとめたデータです。
このshopの値は「v-for」ディレクティブが指定されたタグ内で記載されている全てのタグ内で各データに沿ったkeyを指定することで利用出来ます。

shop{
    'shopId' : "testId1",
    'shopName' : "testShop1",
    'price' : "1000",
    'shopTel' : "1234-5678-90",
    'shopMessage' : {
        'short' : "test shot message",
        'long' : "test long message"
    },
    'shopImage' : {
        'url1' : "https://example.com/sample1.jpg",
        'url2' : "https://example.com/sample2.jpg"
    }
}

h1タグやpタグにて文字列を出力する場合は下記の通り二重括弧を使って値を指定します。

<h1 class="card-title">{{ shop.shopName }}</h1>
<p class="card-text">{{ shop.shopMessage.short }}</p>

画像を表示させる場合は少し書き方が異なります。
src属性に画像データのパスやURLを指定しますが、「src」の直前に「:」(コロン)を指定する必要がある。

<img class="card-img" :src="shop.shopImage.url1" alt="no image">

店舗情報をボタンクリックイベント後の関数で利用したい場合は下記の様に「v-on:click」ディレクティブに関数名を指定してパラメータとして店舗情報を指定すると良いです。
関数定義内の各詳細のデータの指定の仕方は同様です。

<a v-on:click="testFunc(shop)" href="javascript::void(0)" class="btn btn-primary">detail</a>

ちなみに

bladeファイル上で配列のkey指定をして数値や文字列など単体のデータを渡す場合はControllerでjsonエンコードを行う必要はありません。
配列のままbladeファイルでkey指定することによって単体のデータを渡すことが出来ます。

app/Http/Controllers/SampleController.php

$singleValue = array('key1' => 1, 'key2' => 2, 'key3' => 3);

resources/views/index.blade.php

<shop-page v-bind:shop-data="{{ $shopData }}" v-bind:single-value="{{ $singleValue['key1'] }}" ></shop-page>

この場合はVueファイル内ではpropsでNumber型やString型を指定する必要があります。

以上です。
LaravelをやるとVue.jsに触れる機会が出てくる為この辺りの理解も深める必要があるなと感じました!

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

Quasar Frameworkの素振りをしてみた

本記事で書いている事

  • Quasar Frameworkについて
  • 作ってみたアプリの概要/実装(Vue + Firebaseで簡易チャット)
  • 素振りしてみた所感

Quasar Frameworkについて

公式の内容を抜粋すると

  • VueベースのFramework
  • 便利な備え付けコンポーネントがいっぱい
    • StyleやLayoutも簡単にできる
    • レスポンシブデザインも簡単に実装できる
  • 簡単なbuild process(quasar CLIを使えば脳死でビルドできる)
  • SPA/PWA/SSR/Mobile App/Desktop appなどを高速で始められる
    • MobileはCordova
    • DesktopはElectron

いわゆるマルチプラットフォームなアプリケーションをVueと備え付けのコンポーネントで爆速で作れるフレームワークというわけです。(しかも全て同じコードで)
お隣さんはIonic FrameworkFramework7などです。

作ってみたアプリの概要

VueとFirebaseで認証付きの簡単なチャットを作成しました。

作成結果

  • ウェブ版
    quasar-chat-web2.png

  • モバイル版(エミュレータ)
    quasar-chat-mobile2.png

UIの実装について

UIパーツは自分で作成せず、下記の通りQuasar備え付けのコンポーネント群を活用しました。

index.vueの一部
<div>
 <transition-group name="chat-list">
  <q-chat-message v-for="item in chats"
    :key="item.key"
    :name="item.user.name"
    :avatar="item.user.avatar"
    :text="[item.text]"
    :sent="item.user.uid === currentUser.uid"
  />
 </transition-group>
</div>
<q-input bottom-slots v-model="inputText" label="チャットを入力ください" counter maxlength="100" :disable="isDisabled">
 <template v-slot:append>
   <q-icon v-if="inputText !== ''" name="close" @click="inputText = ''" class="cursor-pointer" />
 </template>
 <template v-slot:after>
  <q-btn round flat icon="send" @click="sendMessage"/>
 </template>
</q-input>

<q-chat-message>でチャットメッセージがすぐ作れ、sent propertyで送り側か受け手側かも簡単に設定できたり、avatarやnameもproperyに入れるだけで良い感じに表示してくれてます。Quasarにはこういう便利なコンポーネントが無数にあるのも魅力の一つ。

JavaScriptの実装について

基本有名なFirebase + Vueで作る簡易チャットの実装1を真似しました。ただし、Firebaseの実装の部分をWebとMobile(Cordova)で変えないといけないので、その部分だけ独自に実装しました。2 下記はその一例です。

App.vueの一部
import { Platform } from 'quasar'

if ( Platform.is.mobile ) {
  document.addEventListener('deviceReady', () => {
    firebase.initializeApp(config)
  })
} else {
  firebase.initializeApp(config)
}

Platform.is.mobileはmobileはどうかを判定するBooleanで、他Platform.is.desktopなどもあります。 Vue Component内だとthis.$qでPlatformにアクセスできます。3
他は特段変わった実装はしてないです。

ちょっと詰まった所

quasar dev -m cordova -T iosでCordova側のbuild結果をEmulatorもしくは検証モバイル端末で確認できるのですが、webpack-dev-serverを立ち上げ、それを外部IP経由ででアクセスし表示するという方式4を取っている。この外部IPがFirebaseで承認されていないドメインのためFirebase Authが弾かれる自体が発生しました。
原因はすぐ特定できましたが、CLIが都合よくやってくれた結果の副作用は他もありそうな感じがしました。
ちなみにquasar build -m cordova -T ios側はbundle結果がアセットとしてアプリに内包される事になります。(つまり外側だけアプリ、中身外部ウェブみたいな方式ではない)

所感

Vue Wayな感じが好きなら比較的便利かなというのが率直な感想。Mobile側も基本Cordovaのプロジェクトを内部で作っているだけなので、Cordovaにできる事はほぼ全てできます。(当たり前か...)。
何よりコンポーネントが無茶苦茶豊富なのでUI作るのには困る事はなさそう。
何か一つ書くとすれば、JSのentry pointが自動作成だったり、Cordovaのconfig.ymlもQuasar CLI実行時に勝手に修正されたりするので、細かいカスタマイズしたい時には何かと問題が起きそうな予感がしました。

今後

他のFrameworkとの比較もしつつ、もう少し深掘りしていきたい。

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

Vue.jsの開発環境でServiceWorkerを起動させ画面を確認する方法まとめ

Chromeのアドオンを使用する

Link:

https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb

使用方法:

  1. 上記のリンクからアドオンをインストールする
  2. CHOOSE FOLDERをクリックする
  3. 公開したいディレクトリを選択する(ここでは dist
  4. http://127.0.0.1:8887にアクセスする

Node.jsを使用する

使用方法:

Expressのインストール

npm install express

Expressの設定ファイル作成

touch server.js

Expressの設定を記述

vi server.js

以下をコピペ

const express = require('express');
const port = process.env.PORT || 8080;
const app = express();
app.use(express.static(__dirname + "/dist/"));
app.listen(port);

ディレクトリを公開する

node server.js

参考文献

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

layoutsで取得したデータはページ遷移で更新されない

layouts の中で this.$route.name を取得し、フッターやヘッダーに渡したりしていました。

ページ間移動のときに当然 layouts の this.$route.name も同時に再取得されると思い込んでいましたが、どうやら更新されないようです。

【Nuxt.js】layoutsに設定をまとめつつ、タイトルはpagesから設定したい

こちらの記事を参考にし、 pages で this.$route.name を取得し、それを layouts に渡してからフッターに落とすように変更しました。

これでページ遷移のたびに this.$route.name が取得され、期待通りに動いてくれました。

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

Vagrant + VirtualBox + CentOS 7 に Nuxt.js を入れてみる

自主学習のメモ。ページが表示されるところまでは確認しました。

Vagrantfile の修正

Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.box = "bento/centos-7.6"
  config.vm.box_url = "https://app.vagrantup.com/bento/boxes/centos-7.6"

  #config.vm.network :forwarded_port, guest: 80, host: 8888
  config.vm.network :forwarded_port, guest: 3000, host: 3000
  config.vm.network :private_network, ip: "192.168.33.34"

  #config.vm.synced_folder "./mnt/project/", "/mnt/project/",
  #:owner => "vagrant", :group => "vagrant",
  #:mount_options => ["dmode=777,fmode=777"]
end

後でnuxt.jsでプロジェクトを作る際に、いろいろライブラリをインストールするんですが、
その際にシンボリックリンクを作ろうとします。
しかし、Vagrantでマウントしているディレクトリ内にシンボリックリンクは作成できず、エラーになるので、
マウントしないように設定します。

また、ローカル環境のURL「 http://localhost:3000 」にアクセスできるようにポートフォワーディングの設定をしています。

Node.js のインストール

公式ドキュメントに従い、 Nuxt.js をインストールするために create-nuxt-app を使用します。
create-nuxt-app を使うためには、 npx がインストールされている必要があり、
npx をインストールするには、 npm が必要です。

npm は、 node.js をインストールすれば一緒にインストールされます。
ゆえに、 node.js をインストールします。

執筆時点での最新版であるVer12系をインストールします。

インストール

curl -sL https://rpm.nodesource.com/setup_12.x | bash -
yum install nodejs

バージョン確認

node -v
npm -v

nodejs v12.7.0npm v6.10.0 がインストールされました。

npx のインストール

インストール

npm install -g npx

Nuxt.js のインストール

これで create-nuxt-app が使用できるようになり、 Nuxt.js をインストールする準備が整いました。
次のコマンドで、いよいよ Nuxt.js を稼働させます。

cd /path/to/project
npx create-nuxt-app myproject

CUI上でどういうモジュールを入れるか色々と質問されます。
jQueryとPHPで生きてきた人間なので、
ぶっちゃけ質問内容がほとんどよくわかってないですが、フィーリングで乗り越えます。

npx create-nuxt-app myproject

npx: installed 379 in 18.122s
create-nuxt-app v2.8.0
✨  Generating Nuxt.js project in /path/to/project/myproject
? Project name test
? Project description My mind-blowing Nuxt.js project
? Author name
? Choose the package manager Npm
? Choose UI framework Bootstrap Vue
? Choose custom server framework Express
? Choose Nuxt.js modules Axios, Progressive Web App (PWA) Support
? Choose linting tools ESLint
? Choose test framework Jest
? Choose rendering mode Universal (SSR)

cd test
rpm run dev

おわり

できました。すごい。
image.jpg

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

Vuetify 2.0の注目機能とNuxt.jsでの試し方

本日 Vuetify v2.0.0 Arcadia がリリースされました!
居ても立っても居られず、早速試してみました!

個人的注目機能

VColorPicker

リファレンス:VColorPicker
vue-colorの使用を検討していた身としては、Vuetifyのコンポーネントとして提供されるのはありがたいです。

color1
color2

VFileInput

リファレンス:VFileInput
こちらも地味にVuetifyに今までなかったやつです。
「ファイルを選択」ボタンのカスタマイズは地味に面倒なので、大変ありがたいです。

input1
input2

VOverlay

リファレンス:VOverlay
こちらもたまにcssで自力でやっていたので、楽になりますね。

overlay1
overlay2

Nuxt.jsでVuetify 2.0を使う

素のvueの場合はvuecliでできるようですが、Nuxt.jsの場合は@nuxt/vuetifyモジュールがまだv2.0.0に未対応なため、自力で導入する必要があります。
対応してました!→ nuxt-community/vuetify-module

下記の2種類の方法で利用可能です。

  • ①nuxtのvuetify-moduleを利用する方法
  • ②自分でpluginsに登録する方法

基本的には①で導入することをおすすめします。

①nuxtのvuetify-moduleを利用する方法

プロジェクト作成

この例ではcreate nuxt-appで新規に作成したプロジェクトを想定しています。

# ディレクトリ作成
mkdir vuetify2-example
# 移動
cd vuetify2-example

# プロジェクトの作成
yarn create nuxt-app
# Choose UI framework では、自力でVuetifyを導入するので、Noneを指定します
# 他の項目は任意です

# @nuxtjs/vuetifyを依存に追加
yarn add @nuxtjs/vuetify

nuxt.config.jsでの設定

下記設定を追加します。

nuxt.config.js
// 略
  devModules: ['@nuxtjs/vuetify'],
  vuetify: {
    theme: {
      dark: false
    }
  },
// 略

vuetifyの中にいろいろ設定できます。

VColorPickerを表示してみる

適当に新コンポーネントを試してみましょう。

pages/index.vue
<template>
  <v-app>
    <v-color-picker></v-color-picker>
  </v-app>
</template>

以下のコマンドで起動して確認します。

yarn dev

image.png
無事に起動できました!

②自分でpluginsに登録する方法

プロジェクト作成

この例でもcreate nuxt-appで新規に作成したプロジェクトを想定しています。

# ディレクトリ作成
mkdir vuetify2-example
# 移動
cd vuetify2-example

# プロジェクトの作成
yarn create nuxt-app
# Choose UI framework では、自力でVuetifyを導入するので、Noneを指定します
# 他の項目は任意です

# vuetifyを依存に追加
yarn add vuetify
# アイコンを追加
yarn add @mdi/font -D

Vuetify plugin

あとは以下の実装を追加するだけです。

plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import '@mdi/font/css/materialdesignicons.css'

Vue.use(Vuetify)

export default ctx => {
  const vuetify = new Vuetify({
    theme: {
      dark: false // dark or lightはここで指定するようになった
    },
    icons: {
      iconfont: 'mdi' // iconを指定しないとチェックボックス等が正常に表示されない
    }
  })

  ctx.app.vuetify = vuetify
  ctx.$vuetify = vuetify.framework
}

nuxt.config.jsに下記設定を追加します。

nuxt.config.js
  plugins: [
    '@plugins/vuetify'
  ],
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

plunkerでvue その6

概要

plunkerでvueやってみた。
じゃんけん、やってみた。

参考にしたページ

https://qiita.com/Mitsuzara/items/039cb367c4de7683d2d0

成果物

https://embed.plnkr.co/BPxmnQbWVQfD0zOs5rQU/

以上。

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

Vue.jsで作ったアプリをHerokuにデプロイ

Vueで作成したアプリをHerokuを使ってサッとデプロイした話です!(初心者さん向け)
公式を見ながら行なったものの少し苦戦したので、ここにまとめます。
参考にした海外のサイトのほぼ和訳になってしまうかも・・・

実行環境

Mac OS 10.14.2

下記をインストールされている前提で行います。


$git --version
git version 2.17.2 (Apple Git-113)
$ vue --version
3.9.3
$ node --version
v11.12.0
$ npm --version
6.10.1

※ 参考サイトではyarnの使用を推薦していましたが、ここではnpmを使います。
yarnで行う場合は適宜読み替えてください。

手順

1. Vueのプロジェクトを作成しよう
2. Herokuアプリケーションを作成しよう
3. HerokuでVueアプリを立ち上げる設定をしよう
4. デプロイしよう!

1. Vueのプロジェクトを作成しよう

・Vue CLIをインストール
$ npm install --global vue-cli

・Vueのプロジェクトを新規作成
$ vue init webpack <プロジェクト名>

・Vueのプロジェクトのルートディレクトリへ移動
$ cd <プロジェクト名>

・package.jsonに記載されたパッケージをインストール
$ npm install

・ローカルサーバーを立ち上げる
$ npm run dev

Vueのプロジェクトはこれで完成です!

2. Herokuアプリケーションを作成しよう

Herokuはお手軽に自身の作成したアプリをデプロイして、皆に公開することができるプラットフォームです。

・まずはHerokuをインストール(Mac)※Windowsはこちら参照
$ brew tap heroku/brew && brew install heroku
続いてHerokuのアカウントを作成しましょう。(説明省略)

・Herokuへアカウント情報(メール、パスワード)を使ってログイン
$ heroku login
何かキーを押してと言われるので、適当なキーをタッチします。
すると、ブラウザにログイン画面が表示されるので、Loginボタンを押下します。

・Herokuにプロジェクトを作成
$ heroku create <プロジェクト名>

ここで、新しいアプリのURLが生成されます!
https://<プロジェクト名>.herokuapp.com/

アクセスしてみるとこんな画面が表示されます。
Image from Gyazo
Herokuでデプロイする際に環境依存を防ぐためにNODE_ENVproductionを設定しておきます。
$ heroku config:set NODE_ENV=production --app <プロジェクト名>

3. HerokuでVueアプリを立ち上げる設定をしよう

フロントエンドのVue.jsを簡単にサーバーにアップするにはExpressというNode.jsのフレームワークが便利です。
Expressをインストール
$ npm install express --save

プロジェクトのルートディレクトリ直下にserver.jsを作成します。

// server.js
var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');
app = express();
app.use(serveStatic(__dirname + "/dist"));
var port = process.env.PORT || 5000;
app.listen(port);
console.log('server started '+ port);

ここでのポイントは5行目のdistディレクトリです。

distディレクトリにはVue.jsの圧縮されたファイルが定義されています。
ここでは、Herokuへ渡せるようにdistディレクトリを定義しています。

・ビルドします
$ npm run build

・下記コマンドでserver.jsを実行します。
$ node server.js

http://localhost:5000にアクセスすると、Herokuで実際に立ち上がるサイトをローカルで確認できます。

次にpackage.jsonも編集します。
HerokuはNode.jsのアプリを実行する際に自動的にpackage.jsonを見に行きます。

// package.json
{
  "name": "<プロジェクト名>",
  "version": "1.0.0",
  "description": "A Vue.js project",
  "author": "",
  "private": true,
  "scripts": {
    "dev": "node build/dev-server.js",
    "build": "node build/build.js",
    "start": "node server.js",   <--- ここを編集します
...

4. デプロイしよう!

・Gitリポジトリの初期化
$ git init

Herokuリモートリポジトリを設定します。
$ heroku git:remote --app <プロジェクト名>

Herokuへデプロイしたdistディレクトリを保持しておくために.gitignoreから外します。

// .gitignore
.DS_Store
node_modules/
dist/  <--- 削除します
npm-debug.log*
yarn-debug.log*
yarn-error.log*
test/unit/coverage
test/e2e/reports
selenium-debug.log
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln

・Gitにステージング&コミット
$ git add . && git commit -a -m "Herokuセットアップ"

・Herokuのリモートリポジトリにpush
$ git push heroku master

これでpackage.jsonstartで定義したコマンドが走り、最新のdistディレクトリがサーバーへアップされます!

https://<プロジェクト名>.herokuapp.com/
へアクセスして確認できます!!

※上手くいかないときheroku logsでログを出力することで解決の手がかりになります。。。

参考

こちらのサイトを大いに参考にさせていただきました!
Netscape

海外のサイトの方が実はわかりやすいことが多い気がします:grinning:(英語ともっと仲良くしたい・・・)
ありがとうございます!

最後に

間違っているなどあれば、ご指摘いただけるとありがたいです!!!
次はDocker環境で作成したアプリをデプロイしたいです:whale:

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

Vue.jsで作ったアプリをお気軽にデプロイ

Vueで作成したアプリをHerokuを使ってサッとデプロイした話です!(初心者さん向け)
公式を見ながら行なったものの少し苦戦したので、ここにまとめます。
参考にした海外のサイトのほぼ和訳になってしまうかも・・・

実行環境

Mac OS 10.14.2

下記をインストールされている前提で行います。


$git --version
git version 2.17.2 (Apple Git-113)
$ vue --version
3.9.3
$ node --version
v11.12.0
$ npm --version
6.10.1

※ 参考サイトではyarnの使用を推薦していましたが、ここではnpmを使います。
yarnで行う場合は適宜読み替えてください。

手順

1. Vueのプロジェクトを作成しよう
2. Herokuアプリケーションを作成しよう
3. HerokuでVueアプリを立ち上げる設定をしよう
4. デプロイしよう!

1. Vueのプロジェクトを作成しよう

・Vue CLIをインストール
$ npm install --global vue-cli

・Vueのプロジェクトを新規作成
$ vue init webpack <プロジェクト名>

・Vueのプロジェクトのルートディレクトリへ移動
$ cd <プロジェクト名>

・package.jsonに記載されたパッケージをインストール
$ npm install

・ローカルサーバーを立ち上げる
$ npm run dev

Vueのプロジェクトはこれで完成です!

2. Herokuアプリケーションを作成しよう

Herokuはお手軽に自身の作成したアプリをデプロイして、皆に公開することができるプラットフォームです。

・まずはHerokuをインストール(Mac)※Windowsはこちら参照
$ brew tap heroku/brew && brew install heroku
続いてHerokuのアカウントを作成しましょう。(説明省略)

・Herokuへアカウント情報(メール、パスワード)を使ってログイン
$ heroku login
何かキーを押してと言われるので、適当なキーをタッチします。
すると、ブラウザにログイン画面が表示されるので、Loginボタンを押下します。

・Herokuにプロジェクトを作成
$ heroku create <プロジェクト名>

ここで、新しいアプリのURLが生成されます!
https://<プロジェクト名>.herokuapp.com/

アクセスしてみるとこんな画面が表示されます。
Image from Gyazo
Herokuでデプロイする際に環境依存を防ぐためにNODE_ENVproductionを設定しておきます。
$ heroku config:set NODE_ENV=production --app <プロジェクト名>

3. HerokuでVueアプリを立ち上げる設定をしよう

フロントエンドのVue.jsを簡単にサーバーにアップするにはExpressというNode.jsのフレームワークが便利です。
Expressをインストール
$ npm install express --save

プロジェクトのルートディレクトリ直下にserver.jsを作成します。

// server.js
var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');
app = express();
app.use(serveStatic(__dirname + "/dist"));
var port = process.env.PORT || 5000;
app.listen(port);
console.log('server started '+ port);

ここでのポイントは5行目のdistディレクトリです。

distディレクトリにはVue.jsの圧縮されたファイルが定義されています。
ここでは、Herokuへ渡せるようにdistディレクトリを定義しています。

・ビルドします
$ npm run build

・下記コマンドでserver.jsを実行します。
$ node server.js

http://localhost:5000にアクセスすると、Herokuで実際に立ち上がるサイトをローカルで確認できます。

次にpackage.jsonも編集します。
HerokuはNode.jsのアプリを実行する際に自動的にpackage.jsonを見に行きます。

// package.json
{
  "name": "<プロジェクト名>",
  "version": "1.0.0",
  "description": "A Vue.js project",
  "author": "",
  "private": true,
  "scripts": {
    "dev": "node build/dev-server.js",
    "build": "node build/build.js",
    "start": "node server.js",   <--- ここを編集します
...

4. デプロイしよう!

・Gitリポジトリの初期化
$ git init

Herokuリモートリポジトリを設定します。
$ heroku git:remote --app <プロジェクト名>

Herokuへデプロイしたdistディレクトリを保持しておくために.gitignoreから外します。

// .gitignore
.DS_Store
node_modules/
dist/  <--- 削除します
npm-debug.log*
yarn-debug.log*
yarn-error.log*
test/unit/coverage
test/e2e/reports
selenium-debug.log
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln

・Gitにステージング&コミット
$ git add . && git commit -a -m "Herokuセットアップ"

・Herokuのリモートリポジトリにpush
$ git push heroku master

これでpackage.jsonstartで定義したコマンドが走り、最新のdistディレクトリがサーバーへアップされます!

https://<プロジェクト名>.herokuapp.com/
へアクセスして確認できます!!

※上手くいかないときheroku logsでログを出力することで解決の手がかりになります。。。

参考

こちらのサイトを大いに参考にさせていただきました!
Netscape

海外のサイトの方が実はわかりやすいことが多い気がします:grinning:(英語ともっと仲良くしたい・・・)
ありがとうございます!

最後に

間違っているなどあれば、ご指摘いただけるとありがたいです!!!
次はDocker環境で作成したアプリをデプロイしたいです:whale:

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

Vue.js+Vue.Draggable+CypressでDrag&Dropするテストを書く

前置き

Vue.js + Vue.Draggableでドラッグ&ドロップ機能を実装しているWebページに対してCypressでテストコードを書いていたところ、ドラッグ&ドロップがなかなか動作せずハマったので解決方法を記録しておきます。

環境

  • OS: Mac OS X 10.14.5 Mojave
  • Node.js: v12.6.0
  • npm: 6.10.0
  • yarn: 1.16.0
  • Vue CLI: v3.9.3
  • Vue: 2.6.10
  • Vue.Draggable: 2.23.0
  • Cypress: 3.4.0
  • Chrome: 75
  • Electron: 61
  • cypress-drag-drop: 1.1.1 ※期待通りに動作せず

ドラッグ&ドロップが動作するテストコード

test.js
describe('Drag and Drop test', () => {
  it('Swap ITEM-1 and ITEM-2', () => {
    cy.visit('/')

    cy.get('.items').first().as('sourceItem')
    cy.get('.items').last().as('targetItem')
    cy.get('@sourceItem')
      .trigger('pointerdown', { which: 1, button: 0 })
      .trigger('dragstart')
    cy.get('@targetItem')
      .trigger('dragover')
      .trigger('drop')

    cy.get('.items').first().should('contain', 'ITEM-2')
    cy.get('.items').last().should('contain', 'ITEM-1')
  })
})

テスト対象のvueコード

※draggableタグの部分は、class属性を追加した以外は公式サイトのサンプルコードをそのまま流用しています。

App.vue
<template>
  <div id="app">
    <draggable v-model="myArray" group="people" @start="drag=true" @end="drag=false">
       <div v-for="element in myArray" :key="element.id" class="items">{{element.name}}</div>
    </draggable>
  </div>
</template>

<script>
import draggable from 'vuedraggable'

export default {
  name: 'app',
  components: {
    draggable
  },
  data () {
    return {
      myArray: [
        { id: '1', name: 'ITEM-1' },
        { id: '2', name: 'ITEM-2' }
      ]
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.item {
  width: 6rem;
  margin: 1rem auto;
  border: solid 3px lightblue;
  cursor: move;
}
</style>

テスト実行結果

Succeed_drag-and-drop.gif
※確認しやすさのためTRIGGER前後のアニメーションの再生速度が遅くなるように編集しています。実際にはCypressの実行はもっと速いです。

ITEM-1とITEM-2の上下が入れ替わり、ASSERTにも成功します。
Chrome 75、Electron 61のどちらでも上記のテストコードでドラッグ&ドロップを実行できました。

ドラッグ&ドロップが動作しないテストコード

最初に書いていたテストコードです。
Cypress公式サイトの Plugins で紹介されている cypress-drag-drop を使いましたが、ドラッグ&ドロップが動作しませんでした。

test.js
describe('Drag and Drop test', () => {
  it('Swap ITEM-1 and ITEM-2', () => {
    cy.visit('/')

    cy.get('.items').first().as('sourceItem')
    cy.get('.items').last().as('targetItem')
    cy.get('@sourceItem').drag('@targetItem', 'center')

    cy.get('.items').first().should('contain', 'ITEM-2')
    cy.get('.items').last().should('contain', 'ITEM-1')
  })
})
commands.js
import 'cypress-drag-drop'

テスト実行結果

Failed_drag-and-drop.gif
※動作成功例と同様に、確認しやすさのためTRIGGER前後のアニメーションの再生速度が遅くなるように編集しています。

mousedown、dragstartイベント後、dragoverイベントがループしてしまいドラッグ&ドロップの処理が完了しません。

要因

デバッグしてみたところ、Vue.Draggableの対象となっているHTML要素に対して pointerdown イベントが発生すると該当要素に draggable="true" の属性が付与され、そのあとでないとドラッグ&ドロップが動作しないようでした。
最初に利用しようとしていた cypress-drag-drop のプラグインでは pointerdown イベントが発生せず、それが期待通りに動作しなかった原因と考えられます。
事前に該当のHTML要素に対して draggable="true" を書いても動作しませんでした。

2019/3/1に登録された cypress-drag-drop の issue では vuedraggable に対しても動作しているとのコメントがありましたので、いずれかのパッケージまたはブラウザのバージョンアップなどにより動作しなくなったのかもしれません。


参考サイト

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

Vue.js + Vue.Draggable + CypressでDrag & Dropするテストを書く

前置き

Vue.js + Vue.Draggableでドラッグ&ドロップ機能を実装しているWebページに対してCypressでテストコードを書いていたところ、ドラッグ&ドロップがなかなか動作せずハマったので解決方法を記録しておきます。

環境

  • OS: Mac OS X 10.14.5 Mojave
  • Node.js: v12.6.0
  • npm: 6.10.0
  • yarn: 1.16.0
  • Vue CLI: v3.9.3
  • Vue: 2.6.10
  • Vue.Draggable: 2.23.0
  • Cypress: 3.4.0
  • Chrome: 75
  • Electron: 61
  • cypress-drag-drop: 1.1.1

ドラッグ&ドロップが動作するテストコード

test.js
describe('Drag and Drop test', () => {
  it('Swap ITEM-1 and ITEM-2', () => {
    cy.visit('/')

    cy.get('.items').first().as('sourceItem')
    cy.get('.items').last().as('targetItem')
    cy.get('@sourceItem')
      .trigger('pointerdown', { which: 1, button: 0 })
      .trigger('dragstart')
    cy.get('@targetItem')
      .trigger('dragover')
      .trigger('drop')

    cy.get('.items').first().should('contain', 'ITEM-2')
    cy.get('.items').last().should('contain', 'ITEM-1')
  })
})

テスト対象のvueコード

※draggableタグの部分は、class属性を追加した以外は公式のサンプルコードをそのまま流用しています。

App.vue
<template>
  <div id="app">
    <draggable v-model="myArray" group="people" @start="drag=true" @end="drag=false">
       <div v-for="element in myArray" :key="element.id" class="items">{{element.name}}</div>
    </draggable>
  </div>
</template>

<script>
import draggable from 'vuedraggable'

export default {
  name: 'app',
  components: {
    draggable
  },
  data () {
    return {
      myArray: [
        { id: '1', name: 'ITEM-1' },
        { id: '2', name: 'ITEM-2' }
      ]
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

テスト実行結果

Succeed_drag-and-drop.gif
※確認しやすさのためTRIGGER前後のアニメーションの再生速度が遅くなるように編集しています。実際にはCypressの実行はもっと速いです。

ドラッグ&ドロップによりITEM-1とITEM-2の上下が入れ替わり、ASSERTに成功します。
Chrome 75、Electron 61のどちらでも上記のテストコードでドラッグ&ドロップを実行できました。

ドラッグ&ドロップが動作しないテストコード

最初に書いていたテストコードです。
Cypress公式サイトの Plugins で紹介されている cypress-drag-dropdrag() を使いましたが、ドラッグ&ドロップは動作しませんでした。

test.js
describe('Drag and Drop test', () => {
  it('Swap ITEM-1 and ITEM-2', () => {
    cy.visit('/')

    cy.get('.items').first().as('sourceItem')
    cy.get('.items').last().as('targetItem')
    cy.get('@sourceItem').drag('@targetItem', 'center')

    cy.get('.items').first().should('contain', 'ITEM-2')
    cy.get('.items').last().should('contain', 'ITEM-1')
  })
})
commands.js
import 'cypress-drag-drop'

テスト実行結果

Failed_drag-and-drop.gif
※動作成功例と同様に、確認しやすさのためTRIGGER前後のアニメーションの再生速度が遅くなるように編集しています。

mousedown、dragstartイベント後、dragoverイベントがループしてしまいドラッグ&ドロップの処理が完了しません。

要因

デバッグしてみたところ、Vue.Draggableの対象となっているHTML要素に対して pointerdown イベントが発生すると該当要素に draggable="true" の属性が付与され、そのあとでないとドラッグ&ドロップが実行できないようでした。
最初に利用しようとしていた cypress-drag-drop のプラグインでは pointerdown イベントが発生せず、それが期待通りに動作しなかった原因と考えられます。
事前に該当のHTML要素に対して draggable="true" を書いても動作しませんでした。

2019/3/1に登録された cypress-drag-drop の issue では vuedraggable に対しても動作しているとのコメントがありましたので、いずれかのパッケージやブラウザのバージョンアップなどにより動かなくなってしまったのかもしれません。

なお、以下のように pointerdown イベントと組み合わせれば、cypress-drag-drop プラグインの drag() も期待通りに動作します。

test.js
describe('Drag and Drop test', () => {
  it('Swap ITEM-1 and ITEM-2', () => {
    cy.visit('/')

    cy.get('.items').first().as('sourceItem')
    cy.get('.items').last().as('targetItem')
    cy.get('@sourceItem')
      .trigger('pointerdown', { which: 1, button: 0 })
      .drag('@targetItem', 'center')

    cy.get('.items').first().should('contain', 'ITEM-2')
    cy.get('.items').last().should('contain', 'ITEM-1')
  })
})

参考サイト

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