20200220のvue.jsに関する記事は8件です。

Laravelでミニブログを作ろう #1

laravelの使い方を一通り習ったので、laravelを使って(競プロの勉強の合間に)ちょこちょこミニブログを作っていくことにします。
作成していく過程で最近学習したAWSだったりCircle CIだったりの復習をしていければと考えてます。
(果たして完成するまでに何ヶ月かかるのか)

要件定義

アプリの概要

Markdown記法で記事が書けるミニブログ

主要な機能

  • 記事の作成、編集、更新、削除、下書き(ユーザーは複数人登録できる)
  • 画像投稿
  • タグ付け機能(記事を作成したユーザー以外もタグ付けできる)
  • いいね機能
  • Markdownエディタ
  • レスポンシブデザイン
  • 管理人機能(ユーザー一覧、ユーザー詳細表示)

技術要件

  • フロント
    • Vue.js (いいね機能、タグ付け機能の実装のため)
    • Scss
  • バックエンド
    • php
    • laravel
  • サーバー
    • nginx
  • DB
    • mysql 5.7(ローカル)
    • RDS(AWS)
  • インフラ
    • AWS
    • ECS/ECR
    • RDS(mysql)
    • EC2
    • S3
    • VPC
    • Route53
    • ALB
    • ACM
  • Terraform(AWSをコード化)
  • heroku(多分AWS版のアプリ完成した後、herokuに移行すると思います。お金無いので)
  • CircleCI

その他Googleアナリティクスの導入

(非技術要件も定義できれば尚良いんですが...)

作成手順

環境設定(Dockerfile→Circle CI,PHPUnit(テスト),Terraform等)→laravelでアプリの中身を作り上げていく→デプロイ の流れ

laravelのインストール

rootディレクトリに移動してlaravelをインストールします

$ composer create-project laravel/laravel larablog 
─── laravel(ルートディレクトリ)
    ├── larablog       ・・・今回のアプリ
        ├── app 
        ├── bootstrap
        .
        .
        .

次回からDockerfileを書いていきます

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

【Vue.Draggable】二列間の移動

ドラッグ&ドロップが実装できるライブラリを使ってみたので、メモです。

SortableJS/Vue.Draggable

前回の記事
この記事の目標
  • 項目ドラッグで、リスト間の列移動ができるところまで

目次

  1. 全体
  2. ポイント
  3. 参考
環境
  • Vue.js 2.6.11

  • Vue.Draggable 2.23.2

1.全体

<template>
  <div class="draggable">
    <div class="d-flex">
      <!-- ポケモン -->
      <div class="col-4">
        <h6 class="font-weight-bold">ポケモン</h6>
        <draggable group="monsters" tag="ul" class="list-group" :list="pokemons">
          <li class="list-group-item" v-for="pokemon in pokemons" :key="pokemon.no">
            {{ pokemon.name }}
          </li>
        </draggable>
      </div>
      <!-- デジモン -->
      <div class="col-4">
        <h6 class="font-weight-bold">デジモン</h6>
        <draggable group="monsters" tag="ul" class="list-group" :list="digimons">
          <li class="list-group-item" v-for="digimon in digimons" :key="digimon.no">
            {{ digimon.name }}
          </li>
        </draggable>
      </div>
    </div>
  </div>
</template>

<script>
import draggable from 'vuedraggable'

export default {
  components: {
    draggable
  },
  data () {
    return {
      pokemons: [
        { no: '001', name: 'フシギダネ' },
        { no: '004', name: 'ヒトカゲ' },
        { no: '007', name: 'ゼニガメ' },
        { no: '025', name: 'ピカチュウ' }
      ],
      digimons: [
        { no: '111', name: 'アグモン' },
        { no: '222', name: 'カブテリモン' },
        { no: '333', name: 'エンジェウーモン' },
        { no: '444', name: 'セントガルゴモン' }
      ]
    }
  }
}
</script>

<style scoped>
li {
  cursor: pointer;
}
</style>

05f09e0e9676693f4c8ccd6c43e72b29.gif

  • ポケモンリストとデジモンリストについて、ドラッグで列間移動できる

2.ポイント

  • <draggable>に、group="任意のグループ名" を付与する

  • 同じ名前のグループ同士は、列間の移動ができるようになる

4行目〜
<!-- ポケモン -->
<div class="col-4">
  <h6 class="font-weight-bold">ポケモン</h6>
  <draggable group="monsters" tag="ul" class="list-group" :list="pokemons">
13行目〜
<!-- デジモン -->
<div class="col-4">
  <h6 class="font-weight-bold">デジモン</h6>
  <draggable group="monsters" tag="ul" class="list-group" :list="digimons">

↑ ポケモンとデジモンのリストそれぞれに、monstersグループを付与しています

3.参考

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

Vue.jsのコンポーネントについて

vue.jsを触っていると、インスタンスとコンポーネントとか概念が出てきてごっちゃになりそうだったので、ここではコンポーネントについてまとめます。

コンポーネントとは

  • 同じような処理を行う部分を部品としてまとまった部品

  • ある部品が、HTML上で、「どのように表示されるのか」をオブジェクトとしてまとめるには、templateオプションを使います。そのtemplateオプションでまとめたオブジェクトに名前(コンポーネントのタグ名)をつけたもの。

index.html
<my-component></my-component> <!-- ←ここに部品が表示される -->

ちなみに

コンポーネントの命名規則は、
パスカルケース(アッパーキャメル) or ケバブケースだそうです

  • パスカル(アッパーキャメル)ケース・・・単語の最初を大文字で始める書き方 (HogeFuga など)
  • ケバブケース・・・単語間をハイフンで繋ぐ書き方 (hoge-fuga)

なので上の例では、ケバブケースで書かれてるってことになります

作ったコンポーネントの使い方

  • グローバルに登録する方法
  • ローカルに登録する方法

がありますが、ローカルに登録する方法を書いていきます。

ローカルに登録してコンポーネントを使えるようにする

Vueインスタンスのcomponentオプションに、「コンポーネントのタグ名:コンポーネントのオブジェクト名」と指定して、このVueインスタンス内で使えるように登録する。

vue.js
var コンポーネントのオブジェクト名 = {
   template:'HTML部分'
}
new Vue({
  el:'#app'
  components:{
  'コンポーネントのタグ名':コンポーネントのオブジェクト名
}
})

という感じで書きます

<div id="app">
 <my-component></my-component>
 <my-component></my-component>
 <my-component></my-component>
</div>
vue.js
 var MyComponent = {'<p class="my-comp">Hello</p>'
 }
new Vue({
  el:'#app',
  components:{
   'my-component':MyComponent
 }
})

Vueインスタンスの「components:」には、「コンポーネントのタグ名:コンポーネントのオブジェクト名」と指定し、「my-component 」というタグ名に「MyComponent」オブジェクトを設定する。
これで、HTML 上に<my-component></my-component>と書くだけで、作ったコンポーネントが表示されるようになります。

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

Vue.jsで表示させる方法三種類

表示させるには、3種類ある

  1. DOMとマスタッシュタグで表示させる方法
  2. templateプロパティを使って文字列のみでかく
  3. render関数でかく

「こんにちはユーザー名さん」
をブラウザに表示させるために・・・

1.普通にテンプレートでかく

index.html
<div id="app">
 <p>こんにちは</p>
  <p>{{name}}</p>
  <p>さん</p>
</div>
main.js
new Vue({
  el:'#app'
  data:{
   name:'ユーザー名',
 }
})

2.templateでかく

以下のような感じで
(基本的には使わないけど)

index.html
<div id="app1"></div>
main.js
var data = {
  name:'ユーザー名'
}

var vm = new Vue ({
    el:'#app1',
    data:data,  
    template:'<p>こんにちは{{name}}さん</p>'
})

3.render関数でかく

index.html
<div id="app"></div>
main.js
new Vue ({
    data:{
        name:'ユーザー名'
    },
  render:function(createElement){
  //第一引数でタグをとる
  //第二引数で中に入れたいもの(JavaScriptのように)
        return createElement('h1','こんにちは'+this.name+'さん');
    },
}).$mount('#app')

createElement出なくてもhとかでもなんでも良い

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

Udemyで学んだVue.jsの仮想DOMの話

VNode(仮想node)

  • DOM要素ではない
  • DOM要素を模したJavaScriptオブジェクト
  • DOMに直接アクセスするのはスピードが遅い
  • どうすれば効率よくあまりいじらずに済むか

アルゴリズム的な話で

  • 仮想DOMはDOMのドキュメントオブジェクトの形になってる
  • 本物のDOMはJavaScriptでなくHTMK上にある
  • そこにアクセスするのに時間がかかる
  • JavaScript上ならすぐアクセスして変更できたりする
  • 前回作った仮想DOMと、今新しく作った仮想DOMを見比べて、変わってる分だけ実際のDOMに適用する(mount)

スクリーンショット 2020-02-20 15.18.15.png

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

【Vue.js】Chromeのデベロッパーツールでデバッグする方法

Vue.js入門 基礎から実践アプリケーション開発まで で、VueRouterの勉強をしていたところ、なぜか値が画面に表示されないエラーが発生。
Vue.js devtoolsではいまいち原因が特定できなかったので、標準でついてるChromeのデベロッパーツールでデバッグしてみた。

問題のコードはこちら(トップページ、ユーザー一覧ページの実装は省略)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>SPA</title>
    </head>
    <body>
        <script src="https://unpkg.com/vue@2.5.17"></script>
        <script src="https://unpkg.com/vue-router@3.0.1"></script>

     <div id="app">
        <router-view></router-view>
     </div>

        <script type="text/x-template" id="user-detail">
            <div>
                <div class="loading" v-if="loading">読み込み中...</div>
                <div v-if="error" class="error">
                    {{ error }}
                </div>
                <div v-if="user">
                    <h2>{{ user.name }}</h2>
                    <p>{{ user.description }}</p>
                </div>
            </div>
        </script>

        <script>

            var userData = [
                {
                    id: 1,
                    name: 'hoge',
                    description: 'hogehogehogehoe'
                },
                {
                    id: 2,
                    name: 'wafu',
                    description: 'wafuwafuwafuawefu'
                }
            ]

            var getUser = function (userId, callback) { //userIdを使う
                setTimeout(function(){
                    //与えられた callback 関数を配列の各要素に対して一度ずつ呼び出し、callback が true と評価される値を返したすべての要素からなる新しい配列を生成
                    var filteredUsers = userData.filter(function(user){ 
                        return user.id === userId; //検証
                    })
                    callback(null, filteredUsers && filteredUsers[0]) //callbackの発動を定義
                }, 1000)
            }

            var UserDetail = {
                template: '#user-detail',
                data: function(){
                    return{
                        loading: false,
                        user: null,
                        error: null
                    }
                },
                created: function(){
                    this.fetchData()
                },
                watch: {
                    '$route': 'fetchData'
                },
                methods: {
                    fetchData: function(){
                        this.loading = true
                        getUser(this.$route.params.userId, (function(err, user){ //callbackで渡す
                            this.loading = false
                            if(err){
                                this.err = err.toString
                            }else{
                                this.user = user
                            }
                        }).bind(this))
                    }
                }
            }


            var router = new VueRouter({
                routes: [
                    {
                        path: '/users/:userId',
                        component: UserDetail
                    }
                ]
            })

            var app = new Vue({
                router: router
            }).$mount('#app')
        </script>
    </body>
</html>

http://127.0.0.1:5500/index.html#/users/1を打ち込んでも、ずっと 「読み込み中...」 と表示されてしまう。

では、早速デバッグしていこう。

スクリーンショット 2020-02-20 14.18.56.png

cdnを使って、htmlファイル1枚でかいている。
それをそのままchromeに置いてもうまくデバッグできなかったので、Vscodeの右下にあるGo Liveで開く。

開けたら、検証=>Sourcesでファイルを選び、行数を選択してブレークポイントを定める。
今回は、getUser関数に問題がありそうなのでその呼び出しのところにブレークポイントを置いた。

スクリーンショット 2020-02-20 14.34.22.png

ブレークポイントを置いた後、http://127.0.0.1:5500/index.html#/users/1にアクセスすると、処理が止まる。

そして、変数の部分、今回はthis.$routeの部分にマウスを当てると、変数が保持している値が一目瞭然となる。

スクリーンショット 2020-02-20 14.41.55.png

this.$route.params.userId が文字列の "1" であることが分かり、return user.id === userId;の処理がうまくいっていないことが判明。

return user.id === Number(userId); とし、無事にエラー解消。

Chromeのデベロッパーツール意外と便利!!!

フォームに値を埋める時とかはVue.js devtoolsの方が分かりやすいかも。
スクリーンショット 2020-02-20 15.55.18.png

[参考]
ChromeのデベロッパーツールでJavaScriptをデバッグする方法(2019年版)

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

Nuxt.jsで共通stylusを使用できる方法

Nuxt.jsでcssを書くときにデフォルトではSassを使うことが多いと思いますが、
もう一歩踏み込んでStylusでやってみたいと思いました。

Stylusとは?

ざっくりStylusの特徴といえば、{}や「 : 」,「 ; 」を使わずにかけることです。
Sassの後発でもあるのでSassの書き方も使えるみたいです。(どこまでかは今お試し中です。)
ソースをコピペするときはそのまま使えたりするので便利ですよね。

Stylusを使えるようにする

ますは必要なモジュールを入れます。

$ yarn add stylus stylus-loader  

vueファイルのstyleタグにlang設定します。

<style lang="stylus">  
.section
  color red
  font-size 1.6rem  
  border 1px solid #000000
  .innner-section
    padding 2em
</style>  

サイトで共通の変数やclassを使いたい

vueファイル内であれば下記のような書き方で変数を使えます。

<style lang="stylus">  
$red #ff0000
.section
  color $red
  font-size 1.6rem  
  border 1px solid $red
</style>  

しかし、別のvueファイルでの変数は使えません。
共通用のファイルを作成する必要があります。

assets
 -variables.scss

このままだSassのままなので下記のコマンドを叩き、追加してください。

$yarn add @nuxtjs/style-resources

さらに下記にファイル構成を変更(こんな感じのほうがまとまりがいいと思います。)

assets
 -stylus
  -_variables.styl 

先ほど作成したファイルに変数などをまとめます。

assets/stylus/_variables.styl
$white = #ffffff  
$black = #000000
$display01 = 600px

nuxt.config.jsの設定を行います。

nuxt.config.js
export default {  
    // 中略  
    modules: [ '@nuxtjs/style-resources' ],  
    styleResources: {  
        stylus: [  
            '~/assets/stylus/_variables.styl'  
        ]  
    }  
}  

これで各vueファイルに変数の使用や共通styleを使うことができます。

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

vue.jsのfilterをthisから呼び出す

テキストを変換する処理を切り分けられるので可読性も上がって便利なfilter。
公式 (https://jp.vuejs.org/v2/guide/filters.html) では

{{ message | capitalize }}

<div v-bind:id="rawId | formatId"></div>

のmustache展開とv-bind式の二種のみの使い方しか紹介していない。
実はmethod内等から呼び出して使いたい場合は

this.$options.filters.capitalize(this.message)
this.$options.filters.formatId(this.rawId)

のようにthis.$options.filtersから呼び出せる。
nuxtjsだとhead()内などで呼び出したいこともあると思う。

意外と日本語で記載している記事を見かけなかったので一応メモ。

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