20210325のvue.jsに関する記事は10件です。

【Vue.js Composition API】v-forの中で子コンポーネントの参照を使用する with TypeScript

Vue.js の Composition API でref属性を使用した子コンポーネントの参照をv-for内で使用する場合の備忘録です。
今回は TypeScript も使用しています。

<template>
  <div>
    <HelloWorld
      v-for="(item, i) in list"
      :key="item"
      :ref="el => { if (el) helloWorldComponents[i] = el }"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, reactive, onBeforeUpdate } from 'vue';
import HelloWorld from './components/HelloWorld.vue';

export default defineComponent({
  components: {
    HelloWorld,
  },
  setup() {
    const list = reactive([1, 2, 3]);

    const helloWorldComponents = ref<InstanceType<typeof HelloWorld>[]>([]);

    onBeforeUpdate(() => {
      // Updateの前に必ず参照をリセットする
      helloWorldComponents.value = [];
    });

    return { list, helloWorldComponents };
  },
});
</script>

参考文献

Usage inside v-for
Vue.js の Composition API における this.$refs の取得方法

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

Vue.jsのfilterを理解する!

対象

Vue.jsでfilterとmixinを理解したい

前提知識

Vue.jsの基礎的な理解

filterとは?

フィルターとはテキストにたいしてなにかフォーマットを変更したい時などに用いることが多いです。
やってみる方がわかると思います。
今回はVue CLIを使用していきます。

Home.vue
<template>
<div>
  <h2>{{title}}</h2>
</div>
</template>

<script>
export default {
  data() {
    return {
      title: "welcom to tokyo",
    }
  },
}
</script>

このように記述します。
{{title}}の部分は全て小文字で表示されていますが、こちらを大文字にしていきたいとします。
こういった場合はcomputedで動的に変える方法とfilterを使う方法があります。

しかしcomputedを使って変える場合だと仮に{{subTitle}}のように値が増えるとそれごとに大文字にする処理を書かなければいけません

以下例です

Home.vue
<template>
<div>
  <p v-border:dotted="{color: 'red', width: '300px'}">Home</p>
  <h2>{{titleUppterCase}}</h2>
  <h2>{{subTitleUpperCase}}</h2>
</div>
</template>

<script>
export default {
  data() {
    return {
      title: "welcom to tokyo",
      sibTitle: "sub title"
    }
  },
  computed: {
    titleUppterCase() {
     return this.title.toUpperCase();
    },
    subTitleUpperCase() {
     return this.subTitle.toUpperCase();
    }
  }
}
</script>

これでも大文字になるのですが

computed: {
    titleUppterCase() {
     return this.title.toUpperCase();
    },
    subTitleUpperCase() {
     return this.subTitle.toUpperCase();
    }
  }

この部分が非常に冗長ですね。
ここで使えるのがフィルターです。

使い方としてはvue cliのmain.jsに記述していきます。

main.js
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false
Vue.filter("upperCase", (value) => {
  return value.toUpperCase();
})

new Vue({
  render: h => h(App),
}).$mount('#app')

記述としてはこんな感じです。
まずfilterの第一引数に任意の名前をつけます。
第二引数は関数をとり、引数でvalueをとります。

これでフィルターの設定は完了です。
使いたい場合は

Home.vue
 <h2>{{ title | upperCase }}</h2>
 <h2>{{ subTitle | upperCase }}</h2>

たったこれだけ全てが大文字に適用されるようになります。
ちなみにmain.jsで記述すると全てのcomponentで扱えるグローバルフィルターになります。

ローカルフィルターを定義する

ローカルフィルターではそのcomponentないでだけ使用することができるようになります。

Home.vue
<script>
export default {
  data() {
    return {
      title: "welcom to tokyo",
      subTitle: "sub title"
    }
  },
  filters: {
    upperCase(value) {
      return value.toUpperCase();
    }
  }
}
</script>

scriptタグ内をこちらに変更するだけです!
filtersを定義してあとはその中に好きな関数を指定するだけになります。

注意点

computedとfilterを使う例を紹介してきましたが基本的にはcomputedの方が処理的には早いです。
なぜかと言うとcomputedはキャッシュを効かせられるのに大してfilterはキャッシュを効かせることができないからです。

なので何度も描画されてレンダリングが多いような場面ではfilterは使うものではないです。
そういった場面ではなく尚且つ同じような処理がふえそうな場面でつかって見ましょう!

お疲れさまでした!

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

Vue.jsの算出プロパティ(computed)と監視プロパティ(watch)を理解する

前提知識

Vue.jsの基礎

早速やってみる

今回はProperty.vueといったファイルを作っていきます(vue cliを使用しています)

Property.vue
<template>
  <div>
    <h1>そのままのメッセージ: {{message}}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "this is message!!"
    }
  }
}
</script>

こんな感じで作成。
ではこの下にこのメッセージの大文字の内容を出したいとします。

そこで登場するのがcomputedです。

computedとは

computedプロパティはデータに何かしらの処理を加えてから実行したい!!
といった時に役に立つプロパティです。
今回で言えばmessageのdataを大文字にしてから表示したい。が条件です。

Property.vue
<template>
  <div>
    <h1>そのままのメッセージ: {{message}}</h1>
    <h1>大文字のメッセージ: {{upperMessage}}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "this is message"
    }
  },
  computed: {
    upperMessage() {
      return this.message.toUpperCase();
    }
  }
}
</script>

このようにcomputedプロパティでupperMessage関数を定義する事でmessageを大文字にしたものを表示する事ができます。
thisでvueインスタンスにアクセスできます。

methodsとの違い

methodsじゃダメなの??
といった疑問が浮かぶかと思います。

Property.vue
<template>
  <div>
    <h1>そのままのメッセージ: {{message}}</h1>
    <h1>大文字のメッセージ: {{upperMessage()}}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "this is message"
    }
  },
  methods: {
    upperMessage() {
      return this.message.toUpperCase();
    }
  }
}
</script>

げんにメソッドに書き換えても同じような処理ができます。

computedとmethodsの違い

どちらを使っても同じような結果が返ってくるのですが、決定的な違いは算出プロパティ(computed)を使用すると、
"リアクティブな依存関係にもとづきキャッシュされる" といった特徴があります。

つまり値が更新された時のみに実行される事になります。
つまりどういったことかと言うとmessageの値が変わらない限りはuppperMassageに何度アクセスしても関数を再び実行する事はなく即時に事前のデータを返せるということです!!!

これがmethodsとcomputedの大きな違いです!!

監視プロパティ(watch)って??

watchに関しては特定のデータが変わった時に実行したい。そんな時に使用します。
このwatchに関しては非常にcomputedに似ている部分があります。

基本的にはcomputedを使用するものだと思っていただいて大丈夫です。
ただ、computedだけではかばいきれない部分と言うものがあります。
その部分を補ってくれるのがwatchなのです!

今回はカウントアップの例で見ていきましょう

Property.vue
<template>
  <div>
    <h1>ここからカウントアップします</h1>
    <p>{{counter}}</p>
    <button @click="countUp">カウントアップ</button>
    <p>{{lessThanThree}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: 0,
    }
  },
  methods: {
    countUp() {
      return this.counter += 1;
    }
  },
  computed: {
    lessThanThree() {
      return this.counter > 3 ? "3より上" : "3以下";
    }
  }
}
</script>

こんな感じに書き換えていきます。
どいった処理かと言うとデフォルトでcounterのdataを0で設定しておきます
カウントアップボタンをクリックすると+1され3より下と3以上を判定しています。

これであればcomputedで問題ないのですが。

<p>{{lessThanThree}}</p>

conputedはこの部分が消えてしまうと処理が描画される事がありません。

watchと言うのは基本的に非同期処理の場合に使います。
computedはreturn を使うのですが、非同期処理では戻り値であるreturnを使う事はできません。

Property.vue
<template>
  <div>
    <h1>ここからカウントアップします</h1>
    <p>{{counter}}</p>
    <button @click="countUp">カウントアップ</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: 0,
    }
  },
  methods: {
    countUp() {
      return this.counter += 1;
    }
  },
  watch: {
    counter: function() {
      const vm = this;
      setTimeout(function() {
        vm.conter = 0
      }, 3000)
    }
  }
}
</script>

こんな感じに記述するとwatchはcounterを監視するようになります。
この処理で言うと3病後にカウンターを0にしてくれええええといった処理になります。

ちなみにwatchないではthisをそのまま使うことができないため一度定数に代入してから使用しています。

ただ基本はcomputedを使うのがVue.jsのベストプラクティスになります「!

お疲れさまでした!!

参考記事

Vue.js公式ドキュメント
Udemy, 超Vue.js 2 完全パック (Vue Router, Vuex含む)

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

Vue.js~ToDoリスト④~

今秋は、前回つけた削除機能に完了したときに横線が入るように実装していきたいと思います。

HTMLでの実装は以下のようになります。

index.html
<ul>
      <li v-for="(todo,index) in todos">
        <input type="checkbox" v-model="todo.isDone"> 
        <span v-bind:class="{done: todo.isDone}">{{index}}:{{ todo.title }}</span>
        <span class="delete-button" v-on:click="deleteItem(index)"></span>
      </li>
    </ul>

今回は完了チェックを付けやすいように、チェックボックスを付けたいと思います。
また、v-modelとtodo.isDoneを紐付けておきます。
今回はv-vindというディレクティブを使っていきます。
v-bind:classにオブジェクトを渡すことで、動きを付けてくれます。
今回は、データに応じて動きを変えたいので、spanタグを使いDoneのときの動きを付けていきます。

ここで、js側の実装をみていきます。

index.js
newItem: '',
    todos:  [{
      title: 'title1',
      isDone:false},{
        title:'title2',
        isDone:false},{
          title:'title3',
          isDone:true
        }]
  },
  methods: {
    UPItem: function() {
      const item = {
        title:this.newItem,
        isDone:false
      };
      this.todos.push(item);
      this.newItem = '';
    },

既存のデータを作っていきます。
false▶正しくない true▶正しい という値になります。
今回の記述内容は、タスク1,2は完了していない、タスク3は完了しているよって感じです。
ブラウザ上ではこのような感じになります。

スクリーンショット 2021-03-25 20.05.03.png

メソッドの方をみていきましょう!!これは追加の場合の処理になります。
変数を宣言し、追加されても完了の状態では無いようにisDone:falseを追加します!!
これで、追加から完了までの機能実装することができました!!?

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

Vue.js~ToDoリスト③~

今回はToDoリストの削除機能を作っていきます。

では、実装していきましょう!!

削除機能

index.html
<ul>
      <li v-for="(todo,index) in todos">
        No.{{index}}:{{ todo }}
        <span class="delete-button" v-on:click="deleteItem(index)"></span>
      </li>
</ul>

spanタグを追加して、✗を付けます。また、このspanタグをボタン化したいので、v-on:clickを使います。またここで、CSSを書くためのクラスも付与しておきます。
deleteItemと追加して、何番目のindexを削除するのかを指定します。

index.js
methods: {
    UPItem: function(event) {
      this.todos.push(this.newItem)
    },
    deleteItem: function(index) {
      if (confirm('No.' + String(index) +'削除しますか?')) {
        this.todos.splice(index, 1);
      }
    }
  }

実行機能にdeleteItemを追加します。
今回、関数fanctionに引数としてindexが上がってきます。
そして、this.todos~...のspliceという新しいメゾットが出てきました。
これは、配列の要素を操作するメゾットになります。
①要素を取り除く
②置き換える
③追加する
ことができます。

splice 使い方

これを使うときは、第1引数は必須となります。第2引数はオプションとなっています。
今回の場合はindexを引数として指定し、第2因数は1となります。これは、1個削除してねって指示になっています。

また削除する前に、削除しますか??っというダイアログを追加したいと思います。
confirmというメゾットを使うことで、作成することができます。

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

Vue CLIで作成されるSPAフォルダの中身を解説

Vue-CLIとは?


Vue-CLIとは、コマンドラインを使ってVue.jsでアプリ開発を支援してくれるツールのことです。

Vue CLI 公式サイトでも紹介されているので、一通り目を通しておくことをオススメします。
https://cli.vuejs.org/

Vue CLIのダウンロード方法については、以前記事を書きました。
ダウンロード後、下記画面が表示されていれば、正常に動作していることが確認できます。

javascript-vuejs-cli-howto.png

Vue.jsのフォルダ構成を理解する


では、早速中身を確認していきたいと思います。

プロジェクトを生成した直後は、node_modules、public、srcの3つのディレクトリが生成されており、各フォルダが密接につながっています。

node_mudulesはnpmでインストールされるパッケージの保管ディレクトリです。

src内にはasserts、routers、veiwsのディレクトリに分かれており
App.vue、main.jsが格納されてます。この中で、最も重要なフォルダがsrcになります。

├──public
│   ├── index.html 
│   ├── favicon.ico
│
└── src
    ├── App.vue
    ├── assets
    │   └── logo.png
    ├── components
    │   └── HelloWorld.vue
    ├── main.js
    ├── routers
    │   └── index.js
    └── views
        ├── About.vue
        └── Home.vue

public/index.html


まず始めに、publicの中にあるindex.htmlを見てみましょう。

このファイルがブラウザが表示するファイルです。
ブラウザで表示されている内容が、そのままindex.htmlに記述されているわけではなく、

でid属性にappを指定して、Vueインスタンスを別のファイルで生成しています。
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>vue-application</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but vue-application doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

main.js


main.jsの中身を見てみましょう。
main.jsはその名前が示す通り、プロジェクトフォルダの中で最も重要なJavaScriptファイルです。

まず、routerフォルダ内のindex.jsとApp.vueで記述されている内容をインポートしています。
さらに、render: h =>h(app)のrender関数を使ってApp.vueの中身をindex.html内の

に追加しています。
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

src/App.vue


main.jsでimportされているApp.vueは、template,script,styleの3つで構成されています(単一コンポーネント)。
templateタグではブラウザ上に表示したい内容をHTMLで記述することが可能です。
App.vueではさらに、HelloWorld.vueをscript内でインポートして、 をtemplate内で記述し、その中身を表示しています。

src/App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</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>

src/router/index.js


router内のindex.jsに記述されている内容は、Vue-routerでブラウザ上で表示するページのパスを示しており
それを選択すると指定されたコンテンツを表示してくれます。
ダウンロードした当初はhomeページとaboutページのパスがあらかじめ設定されています。

src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
//import コンポーネント名 from 'Vueのファイルパス'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',       //path:'宛先のパス' 
    name: 'home',    //name: コンポーネント名
    component: Home  //component コンポーネント名
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
export default router

App.vue


パスを指定後、App.vueにパスを記述すると、指定したコンテンツを表示(画面移行)させることができます。
はaタグとしてレンダリングすることができます。

App.vue
<template>  
  <div id="app">

    <!-- 追加ここから -->
    <div class="header">
      <router-link to="/">
        home
      </router-link>
      <router-link to="about">
        about
      </router-link>
    <div>
    <!-- 追加ここまで -->

    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>

store/index.js



store/index.jsはVueアプリケーションの状態を一括管理するための場所になります。
状態を一括で管理することで、どういった種類の状態の変化が起こるのかが分かりやすくなります。

store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})



今日はここまでです。
学習が進んだら、追記訂正をしていきたいと思います。
最後まで読んでいただきありがとうございました。

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

個人的な Nuxt.js のコンポーネントを Github Pages で公開した

先日、以下のような記事を書いた。

実際、このようなコンポーネントを開発して、動かせる場所があるといいと思ったので、Github Pages でページを作成した。 なお、公開には gh-pages を利用した。

以下、記事執筆時点で記載している2コンポーネントについて簡単に説明

OneClickButton.vue

以下の記事の内容から名前を変えただけ。

EventMessageBoard.vue

メッセージを追加してから、一定時間後にメッセージが消えてくれるようなコンポーネント。
イベント(遅延処理やエラーなど)の完了後、これを一時的にユーザーに通達したいようなケースで利用することを想定している。

以下のような仕組みで実装した。

  • 利用時に ref を使って、コンポーネント利用者が特定のオブジェクトを参照可能にする (あまり ref は使いたくなかったが...もっと良い方法があれば...)
  • イベント発火時に this.$refs.__参照名__.add(message); のようにして通達すると、コンポーネント側で値を自動追加し、同時にTimeoutで一定時間後にメッセージを削除するイベントを追加する
  • transition によってある程度アニメーション付きで消えるようにする

苦労した点としては単体テストで setTimeout をどう扱うかだったが、これは jestsetTimeout をテストするための仕組みを持っていたので、これをうまく使うことで解決できた。

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

【独学 / 開発実務未経験】アプリ共有サービス" Ability ”の開発記録(Laravel / Vue / AWS / Docker / CircleCI)

挨拶

はじめまして!kamajiと申します?
開発実務未経験者が、人気の高まっている技術を筆頭にWebサービスを開発いたしましたので
紹介させていただきます。

自己紹介

経歴:4年生大学卒業後、メーカ系Sierに所属しており現在3年目(上流工程担当)
年齢:25歳
趣味:最新のアプリを触るのが好きで最近のお気に入りはNotionです。

? 開発したサービスについて

タイトル名:Ability

URL:https://ability-applications.com/home (PC推奨)
Github:https://github.com/tomoya-kamaji/ability

サービス概要

アプリに特化した情報共有サービス。
個人間でアプリをレビュー、共有することで自分にあったアプリを見つけることができます。

なぜ作成したのか?

ユーザに多くのアプリを知ってもらって、生活、業務に取り込んでいただくきっかけを作りたいという想いから作成しました。

■私の原体験
新卒でSierに入社した当初は、自分の業務のやり方がアナログで非効率でした。
頼まれたことを紙のメモや付箋を使って管理しますが、すぐになくしてしまう、字が汚くて読めない。結局役に立たない。
そんなとき、職場の周りの方が様々なアプリを使用して業務の改善を図っていました。(TrelloやOneNote、VSCODEなど)
見たことのないツール、サービスを匠に使いこなされていて感動したことを覚えています。
それを見てすぐにインストールして自分の業務に取り込んでいき、少しずつ業務を改善していくことができました。
使っていて自分の能力が高まった感覚になり、それからは最新のツールやサービスを見るのが大好きになりました?
そのときにもっと早くそういったサービスを知るきっかけを作りたいという思いから、個人でカジュアルにアプリを共有できるサービスを作成しました。

画面イメージ

Home画面

image-20210325173550373.png

アプリ検索画面

image-20210325173618877.png

レビュー投稿画面

image-20210325173741544.png

アプリ詳細画面

image-20210325173920674.png

image-20210325173949310.png

マイページ

image-20210325173843937.png

開発期間,時間

期間:年末年始~3月末の3ヶ月弱
時間:概算ですが学習時間と合わせて約300時間ほど費やしたと思います。
平日2時間。休日7~10時間。

週:約25時間
月:約100時間
合計:約300時間

仕事をやりながらだったので、コントロール性が高い朝に活動してました。(5~6時起き。リモート勤務に感謝)

学習方法

基本は独学で、途中からMENTAというサービスでメンターを雇い進捗管理をしていただきました。

学習教材

Udemy / Techpit / 書籍をメインに学習を行いました。詳細は最後に記載いたします。

? 機能一覧

アプリ検索機能

  • iThunsAPIを用いた検索

アプリ関連

  • ブックマーク機能

レビュー機能

  • レビュー登録
  • レビュー編集
  • レビュー削除

アプリ詳細画面

  • レビュー一覧
    • フィルタリング
  • iThunsAPIの情報から下記の情報を
    • アプリ名
    • アプリの詳細情報
    • アプリの新着情報
    • アプリの起業情報
    • アプリのスクリーンショット

ユーザ関連

  • マイページ編集機能
  • フォロー、フォロワー機能
  • ブックマーク一覧閲覧

⏱️ 技術・環境

フロントエンド

  • HTML / CSS / Sass / Boostrap
  • JavaScript / Vue.js

バッグエンド

  • PHP
  • Laravel
  • PHPinit

データベース

  • MySQL

インフラ

  • AWS(VPC、EC2、RDS、ACM、EBS、S3)

その他ツール

  • VSCODE
  • Git / Github
  • Docker:開発環境のみ
  • CircleCi

インフラ構成図

Ability インフラ構成.png

開発環境、本番環境

開発環境にDocker / docker-composeを使用しており、以下の3つの用途のコンテナを使用しています。

  1. Webサーバーのコンテナ: Nginx
  2. アプリケーションのコンテナ: PHP / Laravel / Vue.js
  3. DBのコンテナ: MySQL

本番環境もECSを使ってコンテナ化したかったのですが、謎のエラーがでて断念しました。
EC2でのデプロイ経験にも慣れるため、今回はEC2上で環境構築していく形で進めていきました。

?️ 技術選定理由

技術を選定する上で、主に以下2点の観点を重視して選択しました。

  • 独学でも学びやすく実装できるまでたどり着けるか(途中で挫折しないか)
  • 現状、主流のWebアプリ開発で使用されているか

バックエンド:PHP/Laravel

役割:サーバサイドとしての機能。認証、クエリ発行など

採用理由

  • 初学者から学ぶ方が多いので、記事が多数
  • Rubyと迷ったが、関西での求人数が多いという理由からPHPを選択

フロントエンド:Vue.js

役割実際にブラウザで表示される部分、SPAで運用

採用理由

  • Vueテンプレートで簡潔に記述でき、生のJSにくらべて可読性高い
  • Reactと迷ったが、Vueよりも記述量が多く実装に時間がかかるという観点で不採用

CSSフレームワーク:Bootstrap

役割:UIを整える

採用理由

  • グリットシステム採用で直感的に画面の配置ができる。(よくある画面になりがちなので、配色を変更するなどして工夫しました。)

開発環境:Docker/Docker-compose

役割仮想開発環境の構築

採用理由

  • 1度Dockefileを記述してしまえば、環境構築が簡単
  • 短時間で行える・コンテナ型の為、軽量

インフラ:AWS

役割本番環境の運用

採用理由

  • クラウドサービスの中でシェア率No.1。記事が豊富
  • Herokuだと起動するまで遅く、GCPは初学者の実装例が少ない

CI/CDツール:CircleCI

役割自動でテスト・デプロイを行う

採用理由

  • オンプレのJenkinsと比べて設定が簡単
  • 手動でテスト・デプロイをする必要性が少なくなる
  • GitActionsとかなり迷いました

? 工夫した点

iThunsAPIの使用

レビュー投稿機能を作成するにあたって、下記2点が課題としてはありました。

  • レビュー時にユーザからアプリ名や画像を登録してもらうのが大変
  • マスターテーブルを作成するのは開発者の管理工数がかかってしまうこと

iThunsAPIを利用してレビュー投稿することでユーザの投稿へのハードル下げました。
iThunsAPI仕様

UI/UX

  • サイトのデザインに一貫性をもたせて、見やすく
  • 既存のWebアプリのデザインを参考に。(食べログなど)

環境・技術

  • チーム開発を意識して、Gitにpushする際は必ずプルリクを出してGithub上でマージするように心掛けました。

最後に

今回、人生で始めてオリジナルアプリを制作しました。
挫折せずに完成までこぎつけたのは以下2点の要因が大きいかと思います。

  1. やらなければいけない状況に自分をおいたこと

    3月迄にWebアプリを作成すると周りの友人などに宣言し、完成しなければいけない状況に追い込み自分を奮い立たせていました。
    また、メンターを雇い学習の進捗管理を行っていただいたのも効果的でした。(メンターの方ありがとうございました!)

  2. インプットはそこそこでアウトプットをメインに

    完全に理解するのはかなり時間がかかるので、そこそこのインプットで終わり、アウトプットメインで学習を行いました。
    PHPとLaravelの学習は合わせて3週間くらいで終わらせたと思います。

今後も上記2点のことを意識して学習を勧めて行きたいと思っております!
最後まで読んでいただきありがとうございました?

? 学習教材一覧

Udemy

PHP+MySQL(MariaDB) Webサーバーサイドプログラミング入門
PHPからLaravelまで サーバーサイドをとことんやってみよう【初心者から脱初心者へ】【わかりやすさ最重視】
Vue.js入門決定版!jQuery を使わない Web 開発 - 導入からアプリケーション開発まで体系的に動画で学ぶ
Vue.js + Firebaseで作るシングルページアプリケーション

Techpit

Vue.js/Vuexを使ってTrello風アプリを作成しよう!
Laravel(+Vue.js)でSNS風Webサービスを作ろう!
Laravel × CircleCI × AWSで学ぶCI/CD

書籍

たった1日で基本が身に付く! Docker/Kubernetes超入門
ゼロからわかるAmazon Web Services超入門 はじめてのクラウド (かんたんIT基礎講座)

参考リンク

絶対に失敗しないDockerでLaravel+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜後編〜

etx....

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

【独学 / 開発実務未経験】アプリ共有サービス「Ability」の開発記録(Laravel / Vue / AWS / Docker / CircleCI)

挨拶

はじめまして!kamajiと申します?
開発実務未経験者が、人気の高まっている技術を筆頭にWebサービスを開発いたしましたので
紹介させていただきます。

自己紹介

経歴:4年生大学卒業後、メーカ系Sierに所属しており現在3年目(上流工程担当)
年齢:25歳
趣味:最新のアプリを触るのが好きで最近のお気に入りはNotionです。

? 開発したサービスについて

タイトル名:Ability

URL:https://ability-applications.com/home (PC推奨)
Github:https://github.com/tomoya-kamaji/ability

サービス概要

アプリに特化した情報共有サービス。
個人間でアプリをレビュー、共有することで自分にあったアプリを見つけることができます。

なぜ作成したのか?

ユーザに多くのアプリを知ってもらって、生活、業務に取り込んでいただくきっかけを作りたいという想いから作成しました。

■私の原体験
新卒でSierに入社した当初は、自分の業務のやり方がアナログで非効率でした。
頼まれたことを紙のメモや付箋を使って管理しますが、すぐになくしてしまう、字が汚くて読めない。結局役に立たない。
そんなとき、職場の周りの方が様々なアプリを使用して業務の改善を図っていました。(TrelloやOneNote、VSCODEなど)
見たことのないツール、サービスを匠に使いこなされていて感動したことを覚えています。
それを見てすぐにインストールして自分の業務に取り込んでいき、少しずつ業務を改善していくことができました。
使っていて自分の能力が高まった感覚になり、それからは最新のツールやサービスを見るのが大好きになりました?
そのときにもっと早くそういったサービスを知るきっかけを作りたいという思いから、個人でカジュアルにアプリを共有できるサービスを作成しました。

画面イメージ

Home画面

image-20210325173550373.png

アプリ検索画面

image-20210325173618877.png

レビュー投稿画面

image-20210325173741544.png

アプリ詳細画面

image-20210325173920674.png

image-20210325173949310.png

マイページ

image-20210325173843937.png

開発期間,時間

期間:年末年始~3月末の3ヶ月弱
時間:概算ですが学習時間と合わせて約300時間ほど費やしたと思います。
平日2時間。休日7~10時間。

週:約25時間
月:約100時間
合計:約300時間

仕事をやりながらだったので、コントロール性が高い朝に活動してました。(5~6時起き。リモート勤務に感謝)

学習方法

基本は独学で、途中からMENTAというサービスでメンターを雇い進捗管理をしていただきました。

学習教材

Udemy / Techpit / 書籍をメインに学習を行いました。詳細は最後に記載いたします。

? 機能一覧

アプリ検索機能

  • iThunsAPIを用いた検索

アプリ関連

  • ブックマーク機能

レビュー機能

  • レビュー登録
  • レビュー編集
  • レビュー削除

アプリ詳細画面

  • レビュー一覧
    • フィルタリング
  • iThunsAPIの情報から下記の情報を
    • アプリ名
    • アプリの詳細情報
    • アプリの新着情報
    • アプリの起業情報
    • アプリのスクリーンショット

ユーザ関連

  • マイページ編集機能
  • フォロー、フォロワー機能
  • ブックマーク一覧閲覧

⏱️ 技術・環境

フロントエンド

  • HTML / CSS / Sass / Boostrap
  • JavaScript / Vue.js

バッグエンド

  • PHP
  • Laravel
  • PHPinit

データベース

  • MySQL

インフラ

  • AWS(VPC、EC2、RDS、ACM、EBS、S3)

その他ツール

  • VSCODE
  • Git / Github
  • Docker:開発環境のみ
  • CircleCi

インフラ構成図

Ability インフラ構成.png

開発環境、本番環境

開発環境にDocker / docker-composeを使用しており、以下の3つの用途のコンテナを使用しています。

  1. Webサーバーのコンテナ: Nginx
  2. アプリケーションのコンテナ: PHP / Laravel / Vue.js
  3. DBのコンテナ: MySQL

本番環境もECSを使ってコンテナ化したかったのですが、謎のエラーがでて断念しました。
EC2でのデプロイ経験にも慣れるため、今回はEC2上で環境構築していく形で進めていきました。

?️ 技術選定理由

技術を選定する上で、主に以下2点の観点を重視して選択しました。

  • 独学でも学びやすく実装できるまでたどり着けるか(途中で挫折しないか)
  • 現状、主流のWebアプリ開発で使用されているか

バックエンド:PHP/Laravel

役割:サーバサイドとしての機能。認証、クエリ発行など

採用理由

  • 初学者から学ぶ方が多いので、記事が多数
  • Rubyと迷ったが、関西での求人数が多いという理由からPHPを選択

フロントエンド:Vue.js

役割実際にブラウザで表示される部分、SPAで運用

採用理由

  • Vueテンプレートで簡潔に記述でき、生のJSにくらべて可読性高い
  • Reactと迷ったが、Vueよりも記述量が多く実装に時間がかかるという観点で不採用

CSSフレームワーク:Bootstrap

役割:UIを整える

採用理由

  • グリットシステム採用で直感的に画面の配置ができる。(よくある画面になりがちなので、配色を変更するなどして工夫しました。)

開発環境:Docker/Docker-compose

役割仮想開発環境の構築

採用理由

  • 1度Dockefileを記述してしまえば、環境構築が簡単
  • 短時間で行える・コンテナ型の為、軽量

インフラ:AWS

役割本番環境の運用

採用理由

  • クラウドサービスの中でシェア率No.1。記事が豊富
  • Herokuだと起動するまで遅く、GCPは初学者の実装例が少ない

CI/CDツール:CircleCI

役割自動でテスト・デプロイを行う

採用理由

  • オンプレのJenkinsと比べて設定が簡単
  • 手動でテスト・デプロイをする必要性が少なくなる
  • GitActionsとかなり迷いました

? 工夫した点

iThunsAPIの使用

レビュー投稿機能を作成するにあたって、下記2点が課題としてはありました。

  • レビュー時にユーザからアプリ名や画像を登録してもらうのが大変
  • マスターテーブルを作成するのは開発者の管理工数がかかってしまうこと

iThunsAPIを利用してレビュー投稿することでユーザの投稿へのハードル下げました。
iThunsAPI仕様

UI/UX

  • サイトのデザインに一貫性をもたせて、見やすく
  • 既存のWebアプリのデザインを参考に。(食べログなど)

環境・技術

  • チーム開発を意識して、Gitにpushする際は必ずプルリクを出してGithub上でマージするように心掛けました。

最後に

今回、人生で始めてオリジナルアプリを制作しました。
挫折せずに完成までこぎつけたのは以下2点の要因が大きいかと思います。

  1. やらなければいけない状況に自分をおいたこと

    3月迄にWebアプリを作成すると周りの友人などに宣言し、完成しなければいけない状況に追い込み自分を奮い立たせていました。
    また、メンターを雇い学習の進捗管理を行っていただいたのも効果的でした。(メンターの方ありがとうございました!)

  2. インプットはそこそこでアウトプットをメインに

    完全に理解するのはかなり時間がかかるので、そこそこのインプットで終わり、アウトプットメインで学習を行いました。
    PHPとLaravelの学習は合わせて3週間くらいで終わらせたと思います。

今後も上記2点のことを意識して学習を勧めて行きたいと思っております!
最後まで読んでいただきありがとうございました?

? 学習教材一覧

Udemy

PHP+MySQL(MariaDB) Webサーバーサイドプログラミング入門
PHPからLaravelまで サーバーサイドをとことんやってみよう【初心者から脱初心者へ】【わかりやすさ最重視】
Vue.js入門決定版!jQuery を使わない Web 開発 - 導入からアプリケーション開発まで体系的に動画で学ぶ
Vue.js + Firebaseで作るシングルページアプリケーション

Techpit

Vue.js/Vuexを使ってTrello風アプリを作成しよう!
Laravel(+Vue.js)でSNS風Webサービスを作ろう!
Laravel × CircleCI × AWSで学ぶCI/CD

書籍

たった1日で基本が身に付く! Docker/Kubernetes超入門
ゼロからわかるAmazon Web Services超入門 はじめてのクラウド (かんたんIT基礎講座)

参考リンク

絶対に失敗しないDockerでLaravel+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜後編〜

etx....

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

Vue.js + TypeScript で チャートコントロールを配置しよう - Ignite UI for Web Components

こんにちは!

Web Components は、Web プラットフォームであれば、汎用的に利用できるのが魅力ですね。

Vue.js で Ignite UI for Web Components のチャートを利用する手順について紹介します。

本記事は以下の記事の続きとなります。Vue.js の概要解説、インストール方法についても解説していますのでご参照ください。

Ignite UI for WebComponents のチャートの利用方法

チャートのパッケージをインストール

まずは、Ignite UI for Web Components のチャートのページを参考に、必要なパッケージをインストールします。

アプリケーションフォルダの直下でチャートのパッケージをインストールするため、下記のコマンドを実行します。

C:\vue\vue_igc> npm install --save igniteui-webcomponents-charts

main.ts ファイルの編集

インストールしたパッケージを利用できるようにするために main.ts に必要な設定を行います。

import Vue from 'vue'
import App from './App.vue'
import { ModuleManager } from 'igniteui-webcomponents-core';
import { IgcDataGridModule } from 'igniteui-webcomponents-grids';
import { IgcCategoryChartModule } from 'igniteui-webcomponents-charts';

Vue.config.productionTip = false

ModuleManager.register(
  IgcDataGridModule,
  IgcCategoryChartModule
);

Vue.config.ignoredElements = [
  'igc-data-grid',
  'igc-category-chart'
]

new Vue({
  render: h => h(App),
}).$mount('#app')

チャートを利用可能にするために変更した内容は下記になります。

ModuleManager.register

IgcCategoryChartModule をインポートし、ModuleManager に登録します。

import { IgcCategoryChartModule } from 'igniteui-webcomponents-charts';

ModuleManager.register(
  ...
  IgcCategoryChartModule
);

ignoredElements

WebComponents のコンポーネントは、Vue.js のネイティブなコンポーネントではないため、そのまま html にコンポーネントを配置するとエラーが発生します。その回避策として、ignoredElements に登録します。ignoredElements に登録された要素は、無視されエラーとならずにビルドされます。

Vue.config.ignoredElements = [
    ...
  'igc-category-chart'
]

HelloWold.vue ファイルの変更

<template>
  <div>
        <igc-category-chart 
                      id="chart"
                      width="100%"
                      height="500px"
                      ref="chart">
      </igc-category-chart>

      <igc-data-grid 
            height="500px"
            width="100%"
            auto-generate-columns="true"
            ref="grid">
      </igc-data-grid>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { IgcDataGridComponent } from 'igniteui-webcomponents-grids';
import { IgcCategoryChartComponent } from 'igniteui-webcomponents-charts';


@Component
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;


  private dataSource!: Array<object>;

  constructor(){
    super();
    // 表示用のデータソース
    this.dataSource = [{
        Discontinued: false,
        OrderDate: new Date("2012-02-12"),
        ProductID: 1,
        ProductName: "Chai",
        QuantityPerUnit: "10 boxes x 20 bags",
        ReorderLevel: 10,
        UnitPrice: 18.0000,
        UnitsInStock: 39
    }, {
        Discontinued: false,
        OrderDate: new Date("2003-03-17"),
        ProductID: 2,
        ProductName: "Chang",
        QuantityPerUnit: "24 - 12 oz bottles",
        ReorderLevel: 25,
        UnitPrice: 19.0000,
        UnitsInStock: 17
    }, {
        Discontinued: false,
        OrderDate: new Date("2006-03-17"),
        ProductID: 3,
        ProductName: "Aniseed Syrup",
        QuantityPerUnit: "12 - 550 ml bottles",
        ReorderLevel: 25,
        UnitPrice: 10.0000,
        UnitsInStock: 13
    }, {
        Discontinued: false,
        OrderDate: new Date("2016-03-17"),
        ProductID: 4,
        ProductName: "Chef Antony Cajun Seasoning",
        QuantityPerUnit: "48 - 6 oz jars",
        ReorderLevel: 0,
        UnitPrice: 22.0000,
        UnitsInStock: 53
    }, {
        Discontinued: true,
        OrderDate: new Date("2011-11-11"),
        ProductID: 5,
        ProductName: "Chef Antony Gumbo Mix",
        QuantityPerUnit: "36 boxes",
        ReorderLevel: 0,
        UnitPrice: 21.3500,
        UnitsInStock: 0
    }];


  }

  mounted() {
    // グリッドにデータソースを設定
    const igcGrid = this.$refs.grid as IgcDataGridComponent;
    console.log(igcGrid);
    igcGrid.dataSource = this.dataSource;

    // チャートにデータソースを設定
    const igcChart = this.$refs.chart as IgcCategoryChartComponent;
    igcChart.dataSource = this.dataSource;

  }


}
</script>

mounted

mounted は、インスタンスがマウントされた後に呼び出されます。Web Components のコンポーネントを利用する場合は、インスタンスがマウントされた後にデータを設定する必要があるため、mounted 内でデータを設定しています。

  mounted() {
    // チャートにデータソースを設定
    const igcChart = this.$refs.chart as IgcCategoryChartComponent;
    igcChart.dataSource = this.dataSource;
  }

チャートの表示確認

それでは、Vue.js を起動してチャートが表示できることを確認しましょう。

image.png

まとめ

本記事では、Web Components のチャートの使用方法について解説しました。

Web Components は、Web プラットフォームであれば、どんなフロントエンドフレームワークを採用していても利用できる汎用性が大変魅力的なテクノロジーですね。

以下の Youtube でも、チャートの利用方法についても解説していますので、よければこちらもご参照ください。

本シリーズのバックナンバー

本シリーズのバックナンバーはこちらから

サンプルソースのダウンロード

本記事で紹介したサンプルソースはこちらからダウンロードできます。

Ignite UI for Web Components トライアル版を利用するには

インフラジスティックスでは充実した UI コンポーネントライブラリーを収録し、データリッチでレスポンシブなWebアプリケーションをより迅速に構築することを可能にする Ignite UI を開発しており、Web Components対応の Ignite UI for Web Components もリリースしています。

Ignite UI for Web Components はトライアル版での試用が可能です。

製品に関する技術的な問い合わせは こちらのページ よりアカウントの作成を行ってください。登録より30日間、弊社のテクニカルサポートをご利用いただくことが出来ますのでお気軽にお問い合わせください。

また、製品をご購入をご検討のお客様は こちらのページ よりお気軽にお問い合わせください。

開発全般に関するご相談はお任せください!

インフラジスティックス・ジャパンでは、各開発プラットフォームの技術トレーニング、コンサルテーションの提供、開発全般のご支援を行っています。

「古い技術やサポート終了のプラットフォームから脱却する必要があるが、その移行先のプラットフォームやフレームワークの検討が進まない、知見がない。」

「新しい開発テクノロジーを採用したいが、自社内にエキスパートがいない。日本語リソースも少ないし、開発を進められるか不安。」

「自社のメンバーで開発を進めたいが、これまで開発フェーズを外部ベンダーに頼ってきたため、ツールや技術に対する理解が乏しい。」

「UIを刷新したい。UIデザインやUI/UXに関する検討の進め方が分からない。外部のデザイン会社に頼むと、開発が難しくなるのではないか、危惧している。」

といったご相談を承っています。

お問い合せはこちらからお気軽にご相談ください。

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