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

【Vue】テーブル操作エキスパートへの道。ボタンクリック列でを削除する方法

ボタンクリックで表から列を削除する方法について。

これまで、

v-forを使ったテーブルの作成
表で複数選択を可能にする方法
ボタンクリックで行を追加する方法
ボタンクリックで列を追加する方法
ボタンクリックで列を追加する方法

について確認したので、次のステップとして列を削除する方法を確認する。

実装イメージ

image.png

↓ 選択中のセルを削除する

image.png

考え方

  1. 現在選択中のセルの有無を判断
  2. 現在選択中のセルの列番号を取得する
  3. 表から選択中のセル以外を残す
  4. 選択を解除

実装

    removeColumn(){
      //選択中のセルがある場合のみ処理を実行
      if(this.currentCells.length != 0){

        //削除したいセル番号を抽出(重複削除)
        const cellIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxcellIndex )
        )

        //削除したい列を除外
        this.rows.map((row)=> 
          row.table_cells = (row.table_cells.filter((x, cellIndex)=>
            !cellIndicesToRemove.has(cellIndex)
          ))
        )

        //選択中のセルを解除
        this.currentCells = []
      }
    }


1. 現在選択中のセルの有無を判断

if(this.currentCells.length != 0)

現在選択中のセルの行列番号を格納する配列の要素の長さで判断する。


2. 現在選択中のセルの列番号を取得する

const cellIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxcellIndex )
        )

mapメソッドを使って、現在選択中の列番号を抽出する。
重複削除するため、Setオブジェクトに変換する。


3.表から選択中のセル以外を残す

        //削除したい列を除外
        this.rows.map((row)=> 
          row.table_cells = (row.table_cells.filter((x, cellIndex)=>
            !cellIndicesToRemove.has(cellIndex)
          ))
        )

filterとSetオブジェクトのhasメソッドを使って、現在選択中以外のセル番号のみを残す。

mapメソッドで行要素を一つづつ抜き出す。
filterメソッドで各行の列要素を一つづつ抜き出し、!とhasメソッドで番号が一致したセルを除外していく。

filterは非破壊のため、不要なセルを排除した行を元の行に代入する。


4. 選択を解除

      this.currentCells = []

現在選択中のセルを空にする。


フルコード

<template>
  <div>
    <p>〜TmpRemoveColumn.vue〜</p>
    <p>currentCells : {{currentCells}}</p>


    <p>
      <button
        @click="removeColumn"
      >列を削除
      </button>
    </p>

    <table>
      <template v-for="(tr, rowIndex) in rows">
        <tr :key="rowIndex">
          <template v-for="(cell, cellIndex) in tr.table_cells">
            <th :key="cellIndex" 
                v-if="cell.cell_type == 'TH'"
                :class="{'is-active': isActive(rowIndex, cellIndex)}"
                @click="clickCell($event)">
              ( {{rowIndex}} , {{cellIndex}} )
            </th>

            <td :key="cellIndex" 
                v-else-if="cell.cell_type == 'TD'"
                :class="{'is-active': isActive(rowIndex, cellIndex)}"
                @click="clickCell($event)">
              ( {{rowIndex}} , {{cellIndex}} )
            </td>
          </template>
        </tr>
      </template>
    </table>

  </div>
</template>

<script>
export default {
  data(){
    return{
      currentCells:[],
      rows: [
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
                {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
      ]
    }
  },
  methods:{
    //isActiveの判定
    //currentCellsの中にあればtrueにする
    //指定した行列番号の要素がある=数値が-1以外ならtrueにする。
    isActive(rowIndex, cellIndex){
      return this.currentCells.findIndex((elem) =>
        elem.xxxrowIndex == rowIndex && elem.xxxcellIndex == cellIndex
        ) > -1
    },

    clickCell(event){
      //クリックされたセルの情報
      const cell = event.target
      const tr = event.target.parentNode

      //クリックされたセルが既に選択されている場合は、配列から削除する
      if(this.isActive(tr.rowIndex, cell.cellIndex)){

        //選択中の配列の何番目の要素かを求める
        const rmIndex = this.currentCells.findIndex((elem)=>
          elem.xxxrowIndex == tr.rowIndex && elem.xxxcellIndex == cell.cellIndex 
        )

        //選択した要素を選択中の配列から削除する
        this.currentCells = [
          ...this.currentCells.slice(0, rmIndex),
          ...this.currentCells.slice(rmIndex + 1)
        ]

      } else{
        this.currentCells = [
          ...this.currentCells,
          {
            xxxrowIndex: tr.rowIndex,
            xxxcellIndex: cell.cellIndex
          }
        ]
      }
    },
    removeColumn(){
      //選択中のセルがある場合のみ処理を実行
      if(this.currentCells.length != 0){

        //削除したいセル番号を抽出(重複削除)
        const cellIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxcellIndex )
        )

        //削除したい列を除外
        this.rows.map((row)=> 
          row.table_cells = (row.table_cells.filter((x, cellIndex)=>
            !cellIndicesToRemove.has(cellIndex)
          ))
        )

        //選択中のセルを解除
        this.currentCells = []
      }
    }
  }
}
</script>

<style lang="scss" scoped>
table{
  width: 80%;

  th,td{
    border: thin solid rgba(0, 0, 0, 0.12);
    text-align: center;
    color: gray;
  }
  th{
    background: #ccc;
  }
  th, td{
    //選択状態
    &.is-active{
      border: 1px double #0098f7;
    }
  }
}
button{ 
   background: gray;
   padding: 5px 20px;
   color: white;
   border-radius: 50px;
}
input{
  margin: 7px;
  box-sizing: border-box;
}
</style>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsの開発支援ツール【Vue CLI】を導入してみた

概要

最近人気であるJavaScriptフレームワーク「Vue.js」を試してみようと思い、Vue.jsアプリケーションの開発支援ツールである「Vue CLI」の開発環境の構築を行いましたのでその手順を記載しました。

  • 開発環境「Vue CLI」の導入手順
    • Node.jsのインストール
    • Vue CLIのインストール
    • Vue CLIの基本的な使い方
    • ホットリロード機能の確認
  • 導入環境
    • Windows10 Home 64bit バージョン1903

開発環境「Vue CLI」の導入手順

Vue CLIのインストールはWindowsのコマンドプロンプトやMacのターミナルなどのようなコマンドラインツールを使用して、npmコマンドを入力実行して行っていきます。
npmは、JavaScript用のパッケージ管理ツールですが、npmがインストールされていなくとも、JavaScriptの実行環境であるNode.jsをインストールすると、一緒にnpmもインストールされるので、「Node.js」をインストール後、「Vue CLI」をインストールする順番で導入していきます。

Node.jsのインストール

公式サイトから該当するプラットフォームのインストーラをダウンロードします。
https://nodejs.org/ja/download/

ここでは導入先環境がWindowsの64bitマシンなので、msiインストーラをダウンロードしますが、自分の環境に合ったインストーラをダウンロードします。

Windowsの場合は簡単で、ダウンロードしたインストーラを実行後、画面の指示に従ってインストールを進めていきます。

「Next」をクリックします

ライセンス同意のチェックをつけて「Next」をクリックします

インストール先を指定します。(ここではデフォルトのままにしています。)

インストール内容を選択します。(ここではデフォルトのままにしています。)

ツールをインストールするか選択します(ここではインストールしません。)

インストール開始画面で「install」をクリックすると、Node.jsのインストールが開始されます。

インストールが終了すると完了画面が表示されるので、「Finish」をクリックしてインストーラを閉じます。

Node.jsをインストールするとnpmも一緒にインストールされるので、正常にインストールできたかどうか確認します。コマンドラインから次のnpmコマンドを実行します。正常にインストールされていれば「6.14.8」(2020年11月時点)のようにnpmのバージョンが表示されます。

npm --version

Node.jsのバージョンも確認しておきます。コマンドラインから次のnodeコマンドを実行します。正常にインストールされていれば「v14.15.0」(2020年11月時点)のようにnpmのバージョンが表示されます。

node --version

Vue CLIのインストール

Vue CLIのインストールは、コマンドラインから次のnpmコマンドを実行します。
少し時間がかかるので、インストール状況の表示が更新されるのを待ちます。

npm install -g @vue/cli

進行状況
vuecliインストール.PNG

正常にインストールできたか確認するために、コマンドラインから次のvueコマンドを実行します。正常にインストールされていれば「4.5.8」(2020年11月時点)のようにVue CLIのバージョンが表示されます。これで、Vue CLIのインストールは完了です。

vue --version

Vue CLIの基本的な使い方

Vue CLIにはGUIのプロジェクト管理ツールが用意されていて、ツールの画面からプロジェクトの作成やソースコードのビルドを実行できます。VueCLIではアプリケーションの管理単位をプロジェクトと呼んでいます。プロジェクト管理ツールを起動するには、コマンドラインから次のvueコマンドを実行します。

vue ui

起動に成功すると次のような初期画面がブラウザで表示されます。
Vue初期画面.PNG

新しいプロジェクトを作成する

「ここに新しいプロジェクトを作成する」をクリックして、プロジェクトの作成場所を指定します。保存場所を指定したら「次へ」でプリセットの設定画面に進みます。
Vueプロジェクト作成1.PNG
Vueプロジェクト作成2.PNG
ここでは、最初のデフォルトのプリセット「babel, eslint」を選択します。
Vueプロジェクト作成3.PNG
「プロジェクトを作成する」をクリックすると、選択したプリセットに応じたプラグインのインストールが始まるので、プロジェクトの作成が完了するまで待ちます。
Vueプロジェクト作成4.PNG
プロジェクトの作成が完了すると、プロジェクトの管理画面が表示されます。プロジェクトフォルダを確認してみると、プロジェクトのサンプルソースコードが自動的に配置されています。
Vueプロジェクト管理画面.PNG

開発環境(ローカル環境)向けのビルド

プロジェクト管理画面の左メニューにある「タスク」を選択します。タスクの一覧から「serve」を選択して「タスクの実行」をクリックします。
開発ビルド.PNG
この操作によって、ローカルサーバー上でアプリケーションが実行できるようにコンパイルを行います。出力タブに切り替えて見るとコマンドラインから実行できるコマンドを実行しているだけでした。

コンソールに出力されている最後のメッセージを確認すると今の状況を教えてくれていました。
1. [http://localhost:8080/] でアプリケーションが起動してます。
2. 開発環境向けビルドは最適化されていないことに注意してください。
3. 本番環境向けのビルドは、npm runbuildコマンドを実行します。

開発環境向けのビルドでは、実際に参照されていないプラグインやライブラリが含まれているようで、本番環境にデプロイするには向いてないみたいです。本番環境向けのビルドは「build」タスクの実行ボタンをクリックするだけで実行できるようです。

ブラウザで[http://localhost:8080/] にアクセスしてみると、Vue CLIのローカルサーバー上で起動しているアプリケーションの初期画面が表示できました。
アプリ起動.PNG

ホットリロード機能の確認

アプリケーションの初期画面を開いた状態で、ソースコードを更新すると、自動的にブラウザで反映されるか試してみます。プロジェクトフォルダ内の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>

#変更後
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="はじめてVue CLIを導入してみた!"/>
  </div>
</template>

ホットリロード.PNG

ブラウザをリロードしなくても画面の内容が変更されることが確認できました。ブラウザをリロードしなくてもリアルタイムに反映されるこのホットリロード機能すばらしいですね。

今回はここまで!

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

【Vue】テーブル操作エキスパートへの道。ボタンクリックで行を削除する方法

ボタンクリックで表から行を削除する方法について。

これまで、

v-forを使ったテーブルの作成
表で複数選択を可能にする方法
ボタンクリックで行を追加する方法
ボタンクリックで列を追加する方法

について確認したので、次のステップとして行を削除する方法を確認する。

アウトプットイメージ

image.png

↓ 選択している行のみを削除

image.png

行削除の考え方

複数選択時は、選択した行をすべて削除する。
考え方は比較的シンプル

  • 選択中の行番号を抽出する(重複削除)
    • Set, mapメソッド
  • 抽出した行番号以外の表を作る
    • filter, hasメソッド

行削除実例

行削除のメソッド
removeRow(){
      //選択中のセルがある場合のみ処理を実行
      if(this.currentCells.length != 0){

        //削除したいセル番号を抽出(重複削除)
        const rowIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxrowIndex )
        )

        //削除したい列を除外(該当した行番号はスルー)
        this.rows = this.rows.filter((row, rowIndex)=>
          !rowIndicesToRemove.has(rowIndex)
        )

        //選択中のセルを解除
        this.currentCells = []
      }
    }


・選択中のセルがある場合のみ処理を実行

if(this.currentCells.length != 0)
現在選択中のセルがない場合は何もしない。

・選択中のセルの行番号を抜き出す

Setオブジェクトを使う。

Setオブジェクトとは、重複がない特別なオブジェクト。配列のように並び順もない。袋の中に個々の値が入っているイメージ。

const rowIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxrowIndex )
        )

new Set()でSetオブジェクトを生み出す。

this.currentCells.map(cell => cell.xxxrowIndex)
選択中のセルの行番号を一つづつ取得し配列にする。

この処理を実行することで下記のようなイメージになる。

Setオブジェクトの詳しい使い方はこちら

・指定した要素以外を抜き出す

        this.rows = this.rows.filter((row, rowIndex)=>
          !rowIndicesToRemove.has(rowIndex)
        )

filterメソッドはtrueになった場合のみ要素を残す。第二引数はインデックス番号になる。

rowIndicesToRemove.has(rowIndex)
現在選択中の行番号が入ったSetオブジェクトrowIndeicesToRemoveに対し、hasメソッドで一致する値があった場合にtrueを返す。

hasメソッドはSet専用のメソッド。指定した値があるとtrue,該当しない場合はfalseを返す。

ArrayオブジェクトのindexOfincludeメソッドと似た役割。

!をつけることで、一致しない場合のみtrueとすることで、残したい列のみを残す。


フルコード

<template>
  <div>
    <p>〜TmpRemoveRow.vue〜</p>
    <p>currentCells : {{currentCells}}</p>


    <p>
      <button
        @click="removeRow"
      >行を削除
      </button>
    </p>

    <table>
      <template v-for="(tr, rowIndex) in rows">
        <tr :key="rowIndex">
          <template v-for="(cell, cellIndex) in tr.table_cells">
            <th :key="cellIndex" 
                v-if="cell.cell_type == 'TH'"
                :class="{'is-active': isActive(rowIndex, cellIndex)}"
                @click="clickCell($event)">
              ( {{rowIndex}} , {{cellIndex}} )
            </th>

            <td :key="cellIndex" 
                v-else-if="cell.cell_type == 'TD'"
                :class="{'is-active': isActive(rowIndex, cellIndex)}"
                @click="clickCell($event)">
              ( {{rowIndex}} , {{cellIndex}} )
            </td>
          </template>
        </tr>
      </template>
    </table>

  </div>
</template>

<script>
export default {
  data(){
    return{
      currentCells:[],
      rows: [
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
                {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
        {
          "table_cells": [
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
            {"cell_type": "TD"},
          ]
        },
      ]
    }
  },
  methods:{
    //isActiveの判定
    //currentCellsの中にあればtrueにする
    //指定した行列番号の要素がある=数値が-1以外ならtrueにする。
    isActive(rowIndex, cellIndex){
      return this.currentCells.findIndex((elem) =>
        elem.xxxrowIndex == rowIndex && elem.xxxcellIndex == cellIndex
        ) > -1
    },

    clickCell(event){
      //クリックされたセルの情報
      const cell = event.target
      const tr = event.target.parentNode

      //クリックされたセルが既に選択されている場合は、配列から削除する
      if(this.isActive(tr.rowIndex, cell.cellIndex)){

        //選択中の配列の何番目の要素かを求める
        const rmIndex = this.currentCells.findIndex((elem)=>
          elem.xxxrowIndex == tr.rowIndex && elem.xxxcellIndex == cell.cellIndex 
        )

        //選択した要素を選択中の配列から削除する
        this.currentCells = [
          ...this.currentCells.slice(0, rmIndex),
          ...this.currentCells.slice(rmIndex + 1)
        ]

      } else{
        this.currentCells = [
          ...this.currentCells,
          {
            xxxrowIndex: tr.rowIndex,
            xxxcellIndex: cell.cellIndex
          }
        ]
      }
    },
    removeRow(){
      //選択中のセルがある場合のみ処理を実行
      if(this.currentCells.length != 0){

        //削除したいセル番号を抽出(重複削除)
        const rowIndicesToRemove = new Set(
          this.currentCells.map(cell => cell.xxxrowIndex )
        )

        //削除したい列を除外(該当した行番号はスルー)
        this.rows = this.rows.filter((row, rowIndex)=>
          !rowIndicesToRemove.has(rowIndex)
        )

        //選択中のセルを解除
        this.currentCells = []
      }
    }
  }
}
</script>

<style lang="scss" scoped>
table{
  width: 80%;

  th,td{
    border: thin solid rgba(0, 0, 0, 0.12);
    text-align: center;
    color: gray;
  }
  th{
    background: #ccc;
  }
  th, td{
    //選択状態
    &.is-active{
      border: 1px double #0098f7;
    }
  }
}
button{ 
   background: gray;
   padding: 5px 20px;
   color: white;
   border-radius: 50px;
}
input{
  margin: 7px;
  box-sizing: border-box;
}
</style>

コード自体はすごく簡単。Set, has, map, filterを使えるかが鍵となる。

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

Nuxt.jsでAnimate.cssをcdn経由で使う方法

はじめに

Nuxt.js に Animate.css を導入するための方法です。
すでに Nuxt.js の環境構築などを終えられている方が対象です。

他にも、cdn を使って何かを読み込ませたい人のプラスになるかもしれません。

早速本題

  • head タグの中にいろいろ書き込みたいので、head メソッドを使います。
import Loading from "@/components/Loading"; //追加

  export default {
// 省略
    head() {
      return {
        link: [{
          rel: "stylesheet",
          href: "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
        }]
      }
    }

これだけです。
default.vueファイルなどに以上の記述をしていただければ、class 名のところに Animate.css の記述を書くだけでいろんな動きをしてくれます。
例)class = "animate__animated animate__slideInDown"

Animate.css に限らず、他の外部リソースを使う時にも応用できるかと思います。
自分がやろうとした時に、以下の参考記事にたどり着くまでに時間がかかったので、まとめてみました。

参考

NUXT JS 外部リソースを使うには?

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

【メモ】Vue.jsのThree.jsでObjectのTextureを切り替える

はじめに

HTML+JavaScript版:【メモ】Three.jsでObjectのTextureを切り替える

↑をVue.jsでやってみた。

プロジェクトセットアップ

$vue create change_texture_vue
$cd change_texture_vue
$npm install three
$npm run serve

今回はコントローラは使わない。
App.vueからHelloWorld部分を削除して、新しく TextureChange.vue コンポーネントをインポートする。

ソースコード

基本的にはHTML+JavaScript版と同じ。ちょっとVue仕様に変更しただけ。
Sceneはbodyのchildとしてぶち込んでるけど、レイアウト綺麗にしたいならdivタグとかのchildにしたらいいのかも。

TextureChange.vue
<template>
  <div>
    <select @change="changeImage">
      <option :value="logoURL" selected>Vue logo</option>
      <option :value="goriURL">Gori</option>
    </select>
  </div>
</template>

<script>
import * as THREE from 'three'
export default {
  name: 'textureChange',
  data() {
    const width = 600;
    const height = 400;
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, width / height, 1, 1000);
    const cubeGeometry = new THREE.BoxGeometry(5, 5, 5);
    const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
    const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    const logoURL = require('@/assets/logo.png'); // need require when local image
    const goriURL = require('@/assets/gori128.png');
    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    return {
      width,
      height,
      scene,
      camera,
      cubeGeometry,
      cube,
      logoURL,
      goriURL,
      renderer,
    }
  },
  mounted() {
    this.initialize()
  },
  methods: {
    initialize() {
      // camera
      this.camera.position.set(0, 0, 10)
      // renderer
      this.renderer.setSize(this.width, this.height);
      this.renderer.setClearColor({ color: 0x000000 });
      // cube
      const cubeMaterial = new THREE.MeshBasicMaterial({
        map: new THREE.TextureLoader().load(this.logoURL),
      })
      cubeMaterial.needsUpdate = true;
      this.cube = new THREE.Mesh(this.cubeGeometry, cubeMaterial);
      this.cube.name = 'cube'; // need name to find object afterwards
      this.scene.add(this.cube);
      this.renderer.render(this.scene, this.camera);
      document.body.appendChild(this.renderer.domElement);
      this.render();
    },
    render() {
      this.cube.rotation.x += 0.1;
      this.cube.rotation.y += 0.1;
      requestAnimationFrame(this.render);
      this.renderer.render(this.scene, this.camera);
    },
    changeImage(e) {
      const image = e.target.value;
      const object = this.scene.getObjectByName('cube'); // find obj by name
      object.material.map = new THREE.TextureLoader().load(image);
      object.material.needsUpdate = true;
    },
  },
}
</script>

結果

  1. Vueのロゴが表示される

背景黒いな…
image.png

  1. テクスチャ切り替え
    image.png

  2. Goriちゃんに切り替わった
    image.png

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

【プログラミングスクールさんへ】フロントとバックを分けたポートフォリオを作ってみませんか?という話【ごめんなさい】

はじめに

タイトルはプログラミングスクールさんに、面倒ごとを増やしたらごめんなさいという謝罪の意図です。

未経験からDWCというプログラミングスクールを卒業してWebエンジニアになりましたyukiです。
もう4ヶ月が経ちました。支えてくださった皆様のおかげで、楽しい日々を送っています。

今回は、未経験転職の際におそらく作るポートフォリオに関しての記事です。
ただ、はじめに声を大にして伝えたいことを次に記します。

記事の対象者

この記事の対象者は、プログラミングスクール(以下PGS)に通っており、

  • PGSの課題が入学前に終わってるレベル
  • 完全に理解して人に説明できるレベル
  • 余裕があって何やっていいか分からないレベル

の人向けです。

また、こんな記事を書いておいてなんですが、マインドの部分で言うと

  • フロントとバックを分けた開発に挑戦したい理由が明確
  • 最悪、自分一人で調べて周りの人に迷惑をかけない覚悟がある
  • さらに間に合わなかった場合のリスク回避策を持っている

方向けです。

なぜそれを実装すると良いのか分からないまま挑戦すると失敗しますし、きっと受ける企業からも「あんまわかってないな」と思われるはずです。
ここまで読んだ上で、もし自分が対象者だ!と思う方はお進みください。

※ 初学者向けに表現を崩している部分があるため、厳密に見るとグレーな部分もあるかと思います。その際は、こういう考えもあるよとご指摘ください。

最後に、自分が挑戦したから天狗になって「みんなもやろうね!」的な記事ではありません。こういうポートフォリオ作る人もいるんだな〜やってみようかなぁ程度の参考になれば幸いです。

フロントとバックを分けるとは?

1つのフレームワークでWebアプリケーションを開発することは、できます。

例えば、PGSでよく利用されるRailsでは、Controller側で定義したActionに対し、viewファイルという画面を構成するファイルが対応して存在します。基本的にはRailsだけあれば、Webアプリケーションのポートフォリオを作ることはできるのです。

ただここで、冒頭のフロントとバックを分ける開発という概念を考えてみたいと思います。

フロントエンドとバックエンドで違うフレームワークを用いる

入社してからも実感したのですが、実務ではWebアプリケーションの設計においてフロントエンド(人の見る部分)とバックエンド(処理を書く部分)に、それぞれ違うフレームワークを使っている場合があります。

イメージがつきやすいと思うので、今回はそのように開発することを「フロントとバックを分ける」というコトバの定義とします。

2つのフレームワークを使うと(皮肉ではなく)Railsのみで開発をしている人にはちょっと想像が難しいと思いますが、Railsの業務をコントローラーとモデルの処理のみに絞らせて、フロントのフレームワークには画面の書き換えのみに専念してもらうことができるのです。

※ メリットに関しては、ここでは言及しませんので各自調べてみてください。

具体的な説明:バックの役割

具体的には、Railsなどバックエンドを担当するフレームワークにはAPIとして動いてもらいます。今回開発する想定のAPIは、フロント側のリクエストが来た際に値を返すだけのものになります。

調べる際は、こちらの記事がとても参考になったので、ご覧ください。

通常ならコントローラーのアクションでは最後にredirect_toなどで画面遷移をさせますが、こちらの記事を見るとjsonというデータを最後に返して処理を終えています。

フロント側では、こちらのjsonを受け取って、それで画面を書き換えます。

具体的な説明:フロントの役割

受け取ったjsonで画面の書き換えをしようとすると、非同期で素早く書き換えるなんてことも、簡単にできるようになります。
フロント側を作成するフレームワークとしては、Vue.jsやNuxt.js、React.jsやAngularなどが挙げられるのではないでしょうか。フロントとバックを分けたポートフォリオ作成に挑戦するにあたり、これらを勉強するのはいいことだと思います。

いろいろな成長につながるため、ぜひ挑戦してみてください!

以上です。以下、個人の見解なので読まなくていただいても大丈夫です。

挑戦した方がいいと思った理由

私がフロントエンドとバックエンドを分けたポートフォリオに挑戦すると良いと思った理由は、2つあります。

一つは、転職市場の戦略としてきっと有効だから

大前提として、他の転職希望者と差別化するためにフロントのフレームワークに挑戦することは、私はあまり好ましく思っていません。なぜなら、目的を間違っているような気がするからです。

冒頭で「フロントとバックを分けた開発に挑戦したい理由が明確」の人が本記事の対象と述べましたが、何でフロントとバックを分けたのか?という問いに対する回答が「就活のため」であっては欲しくないのです。

具体的に述べますと、プログラミングは何か解決したい課題があって、技術の選定はそれに対して最適なものを選ぶ(もしくは、社内のナレッジを蓄積するためにor知見を広げるために挑戦してみる)ものだと思っています。フロントバックを分ける必要がないなら、無理して分けなくてもいいと思います。

それに対し、ただ漠然とした理由でやってみたいから、転職活動に有利そうだからという理由で挑戦すると、エンジニアを目指す上で大切なその根本の概念を否定しているように思えてしまうのです。

とは言え、昨今の転職市場を見るにコロナウイルスの影響などで非常に厳しい風が吹いているように思えます。そんな中で、「なぜやりたいのか」が明確になっている人には、ぜひアピールポイントを増やすという意味で挑戦していただけたら、会社選びの際に、より良い結果を生むのではないかなと思い、この記事を書きました。

実務にスムーズに合流する手段としてきっと有効だから

私の例になってしまいますが、実務に入って自分でAPIを作成し、フロントとバックを分けて開発するという業務に取り組んでおります。PGSではGoogleのAPIを使うなど簡単な開発は学習しましたが、フロントエンドを別フレームワークで開発するところまで指導してくれるPGSは少ないのではないでしょうか。

たまたま私はポートフォリオでそのような開発経験があったため、応用して活かすことができました。ただ、これを経験しないまま実務に入って行ったら相当苦労しただろうなぁと思うわけです。

全ての会社がフロントバックを分けた開発をしているわけではもちろんないですが、一定量現在の流行だったり、今後目指すべき場所として「フロントバックを分けたい」という声も周囲で耳にします。

可能性があるならば、挑戦してみるのも良いかと思った次第です。もしかしたら、今分けていない会社でも、あなたがフロントバック分離のプロジェクトを担当できるかもしれません。

参考記事

フロントエンドとバックエンドをわけて開発する

頑張って作った過去のポートフォリオ

https://github.com/yuki-snow1823/DTODO
何かあればDMまでどうぞ!

よければ読んでくださいっ

【卒業生】DMMWEBCAMPに通おうか迷っている人に伝えたい事

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

vue.jsでproxyを使ってみた時のエラーがlocalhostのままで、proxy設定したurlにならなかったこと

背景

vue.jsの勉強をしていて、郵便番号検索APIを使ったところ、CORSが発生してうまく表示できなかった。
開発中のことなので、楽にCORSが回避できないか方法を探ったところ、proxyを使うと良いという記事を見つけた。
早速やってみたものの、コンソールに出たエラーが示すURLが変わらず、解決まで意外と時間がかかったので、メモを残すことにした。

ちなみに、郵便番号検索には、zipcloudを利用した。

問題点

郵便番号検索APIのURLとローカル開発中のURLは別物で、originが違うので怒られる。

開発中のもの http://localhost:8080
郵便番号検索 https://zipcloud.ibsnet.co.jp/

これはポートを違えても同様なので、ローカルでフロントエンドとバックエンドを別々に開発している場合にも発生する。
これを開発環境側を変更せずに解決したい。

proxyの設定と問題発生

proxyの設定は、プロジェクトルートに配置するvue.config.jsに行う。
vue/cli 4.5.8で作ったプロジェクトにはそれがなかったので、追加して中身を記述する。
ここでの目的は、ローカル開発環境からhttp://localhost:8080/postalにアクセスしたら、郵便番号検索バックエンドのURLに変えてアクセスすることだ。

vue.config.js
module.exports = {
    devServer: {
        port: 8080,
        proxy: {
            '/postal': {
                target: "https://zipcloud.ibsnet.co.jp/api",
                changeOrigin: true,
            }
        }
    }
};

APIを実行する側は以下の通り。

axios
    .get("/postal/1234567")
    .then((res) => {
        console.log(res.data);
    })
    .catch((err) => {
        console.log("エラー発生");
        console.log(err);
    });

機体としてはhttps://zipcloud.ibsnet.co.jp/api/postal/1234567になって、見つからないというようになるのかな、と思ってましたが、実際に表示されたエラーはhttp://localhost:8080/postal/1234567でproxyされてないっぽい。

GET http://localhost:8080/postal/1234567 404 (Not Found)

解決方法

解決方法と言って良いか迷うところだが、ここでの問題点はproxyで変わった結果のurlでエラーが表示されていなかったということだ。
期待したエラーは以下のようなものだが、実際は上記のようになっていた。

GET https://zipcloud.ibsnet.co.jp/api/postal/1234567 404 (Not Found)

zipcloudの郵便番号検索APIをご覧いただければわかるが、targetのurlはapiで止まらず、その続きがある。パラメータも必要だ。これらがないので、Not Foundになる。ここまでは予想していた。ただエラーの出方が期待と違っていた、というわけだ。
targetのurlが存在しないものになってしまうような設定になってしまうと、proxyが働いてないじゃないか、みたいに悩まされた。

結果としては、以下のようになっていると、やりたいことが実現できた。

vue.config.js
module.exports = {
    runtimeCompiler: true,
    devServer: {
        port: 8080,
        proxy: {
            '/postal': {
                target: "https://zipcloud.ibsnet.co.jp/api/search",
                changeOrigin: true,
                pathRewrite: p => {
                    console.log(p);
                    r = p.replace(/^\/postal\/*/, '?zipcode=');
                    console.log("result:" + r);
                    return r;
                },
            }
        }
    }
};
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

jQeuryとVueを併用してた際のdataTableのUncaught TypeError: Cannot read property 'style' of undefinedエラー

jQueryとVueを併用していてjQueryのdataTableが動かなくてハマってたので備忘録的に。

エラー文
Uncaught TypeError: Cannot read property 'style' of undefined

通常のHTML内では

<thead>
  <th>

って<tr> なくてもdataTable動いてたのに、

Vueのtemplate内では

<thead>
 <tr>
   <th>

って<tr>をちゃんと書かないとdataTabeが動かない。

まぁVueとjQueryを一緒に使うことはあんまりないと思いますが、当時のプロジェクトの都合もあって使っていて、ハマったのでメモがてら。

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

11/4 Vue.js 学習1回目

Vue.jsとは

 https://jp.vuejs.org/
 UIフレームワーク

Vue Devtools

  • Vue Devtools:Vue開発サポートツール

   https://github.com/vuejs/vue-devtools#vue-devtools
   ・Google Chromeに追加
   <機能>
   ・Componentタブ:親子関係やデータを確認
   ・Vuexタブ:storeの状態を確認
   ・イベントタブ:イベント実行履歴を確認

  • 「Vue.js not detected」が表示される

   https://qiita.com/hashimoto-1202/items/c81f5d4c271eef16d957
   ・拡張機能の設定で「ファイルの URL へのアクセスを許可する」を有効にする

Vue環境構築

  • 直接読み込み: <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  • NPM:Node.jsパッケージ管理
  • CLI:コマンドラインインターフェース

fiddle

https://jsfiddle.net/

Hello Worldの表示

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