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

アニメ情報のWebアプリ開発してみたけど上手くいかず、、(要改善)

出来たもの

「検索」で、指定した年度・クールごとのアニメ番組一覧を表示してくれるWebアプリ。
 ※実際に動くものはコチラにアップしてます。

利用ライブラリ

 ・Vue.js
  CDN:https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js
 ・Bootstrap
  CDN:https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
  CDN:https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js
 ・axios
  CDN:https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.0/axios.min.js
 ・ShangriLa Anime API

やりたかったこと

新アニメが始まった時にとりあえず1話見てみて、減らしていくことが多い。(1話すら見ないこともあるが。)
始まってすぐだと、タイトルだけだと分からないことが多いので、自分用で優先順位を管理できるようなWebアプリを作ってみたかった。
 ・年度、クールでアニメ番組を取得して取捨選択。
 ・優先順付けて並び変え。または削除。
みたいなことをやりたかった。

出来なかったこと

四苦八苦の様子、参考にしたURLなどは自分用メモとして保管してます。
Webサイトのサムネイル画像を取得して表示したかったが、上手くいかず。。
色々調べて試してみて、最終的にはWebページのOGPイメージ(og:image)を取得すれば良い考えにシフトしたが時間が足りなくイメージ画像の取得が上手くいってません。

改善点(今後に期待)

今回時間なくて断念したが、色々改造したい。
 ・ちゃんとサムネイル画像を表示できるようにしたい。
 ・ビジュアルをもっとかっこよくしたい。
 ・番組の曜日、時間、PV再生など追加したい。
 ・検索結果の保存。
 ・カードの並び変えや削除。

コード

html
<!-- 全体をVue.js有効にする -->
<div class="container text-center text-white bg-dark" id="app">

  <!-- タイトル行 -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto"><h1>ANIME Watch</h1></div>
  </div>

  <!-- 検索フォーム -->
  <div class="form-inline justify-content-center">
    <input v-model:value="Year" placeholder="2020" class="form-control">
    <label class="col-sm-1"></label>

    <select v-model:value="Cours" class="custom-select">
      <option></option>
      <option></option>
      <option></option>
      <option></option>
    </select>

    <div class="col-sm-2">
      <button v-on:click="Search" class="btn btn-primary">検索</button>
    </div>
  </div>

  <!-- 全てのタスクをクリアするボタン -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto">
      <button v-on:click="clearAll" class="btn btn-danger">検索結果のクリア</button>
    </div>
  </div>

  <!-- タスク追加されると表示される部分 -->
  <div class="flex-container">
      <p v-for="Anime in AniData">{{Anime.Title}}<br>
      <a v-bind:href="Anime.WebUrl" target="_blank">
        <img v-bind:src="Anime.ImgUrl" width="250" height="150"></img>
      </a>
      </p>
  </div>
</div>
js
const app = new Vue({
  el: '#app', // Vueが管理する一番外側のDOM要素

  data: {
    // Vue内部で使いたい変数は全てこの中に定義する
    Year: '2020',  // 年
    Cours: '',   // クール
    Animes: '',    // APIで取得したアニメ情報JSON
    AniData: [],   // 表示するアニメ情報配列
  },
  methods: {
    // 関数はココに記述
    Search: async function() {
      // 検索時の関数
      try {
        // クール値を取得
        let CoursNo=4;
        switch (this.Cours){
          case '': CoursNo=1; break;
          case '': CoursNo=2; break;
          case '': CoursNo=3; break;
          case '': CoursNo=4; break;
        }

        // ShangriLa Anime API Server
        let response;
        response = await axios.get(`https://api.moemoe.tokyo/anime/v1/master/${this.Year}/${CoursNo}`);
        this.Animes = response.data;

        // アニメ情報表示用配列作成
        this.AniData = [];
        for (var item in this.Animes) {
          var data = {Title: this.Animes[item].title, 
                      WebUrl: this.Animes[item].public_url,
                      ImgUrl: ""};
          this.AniData.push(data);
        }

        /*
        // OGP取得 上手くいかないからあきらめ。
        const CORS_PROXY = 'https://cors-anywhere.herokuapp.com/'
        for await (var item of this.Animes) {
          await fetch(CORS_PROXY + this.Animes[item].public_url)
            .then((res) => res.text())
            .then((text) => {
              const el = new DOMParser().parseFromString(text, 'text/html')
              const headEls = el.head.children
              Array.from(headEls).map((v) => {
                //console.log(v)
                const prop = v.getAttribute('property')
                if (!prop) return
                if (prop == "og:image") {
                  //console.log(prop, v.getAttribute('content'))
                  var ogimg = v.getAttribute('content')
                }
              })

              var data = {Title: this.Animes[item].title, 
                          WebUrl: this.Animes[item].public_url,
                          ImgUrl: ogimg};
              this.AniData.push(data);
            })           
          }*/
      } catch (error) {
        console.error(error);
      }
    },

    clearAll: function() {
      // 表示クリア時の関数
      this.AniData = [];
      console.log('クリア');
    },
  },
});
css
.flex-container {
  display: -webkit-flex;
  display: flex;
  -webkit-justify-content: center;
  justify-content: center;
  -webkit-align-items: center;
  align-items: center;
  flex-wrap: wrap;
}

感想

Web開発は初でしたが、色々勉強にはなったかな。。
経験積んで、技術力を上げたいと思う。(Web開発は非常に興味あるので。)

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

vueのクリックイベントで、子のイベントを親に渡す方法。

Vueのクリックイベントで子のイベントを親に引き継ぐ方法。

(子テンプレートのボタンをクリックしたときに、親テンプレートで定義しているメソッドを実行する方法)

設定手順

子:①クリックイベントを設定 @click=$emit('イベント名')
  ↓
親:②子のイベントを受け取る (子のタグ内で設定したイベント名)
  ↓
親:③methodsに処理を記述

・子から親にイベントを引き継ぐ。
$emit  子から親へのデータ/イベント受け渡し
@click  v-on:click の省略形


記述例

・用意するファイルは2つ
親:parent.vue
子:TmpBtn.vue

・実現したいこと
親で呼び出した小テンプレートのボタンをクリックしたときに、親テンプレートで設定してあるメソッドを実行する。

(子)TmpBtn.vue
<template>
    <v-btn
    elevation="2"
    rounded
    width="20%"
    //①クリックイベントを設定
    @click="$emit('child-click')"
    >
    ボタン
    </v-btn>
</template>

子テンプレートのボタンがクリックされると、child-clickというイベントを親に渡す。

(親)parent.vue
<template>
  <v-app>
    <TmpBtn
  <!--②子のイベントを受け取る-->
    @child-click="BtnClicked(hello)"
    />
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  components:{
    TmpBtn
  },
  data(){
    return{
      hello:"親テンプレートのメソッドを実行"
    }
  },
  methods:{
    //③methodsに処理を記述
    BtnClicked(a){
      console.log(a)
    }
  }
}
</script>

子テンプレートのボタンがクリックされたら、BtnClickedメソッドを実行する。

▼実行例
image.png

image.png

子テンプレートのボタンクリックで、親テンプレートで設定したイベントの発火に成功。


$emitしないとどうなるか

$emitしない場合、イベント設定は2種類考えられる。

  1. 子テンプレートにclickイベントとメソッドを記述 → OK
  2. 親テンプレートにclickイベントとメソッドを記述 → NG

上記の場合、正常に作動するのは1のみ
2の親テンプレートで呼び出した子テンプレートタグにclickイベントを設定しても動作しない。


子テンプレートに記述する場合

<template>
    <v-btn
    elevation="2"
    rounded
    width="20%"
    @click="ChildClicked(child)"
    >
    ボタン
    </v-btn>
</template>

<script>
export default {
  methods:{
    ChildClicked(a){
      console.log(a)
    }
  },
  data(){
    return{
      child:"子テンプレートのボタンがクリックされました"
    }
  }
}
</script>

image.png

正常に作動。

親テンプレートに記述する場合

(親)parent.vue
<template>
  <v-app>
    <TmpBtn
    :bind="text"
    <!--子テンプレートを呼び出し、クリックイベントを設定-->
    @click="BtnClicked(hello)"
    />
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  components:{
    TmpBtn
  },
  data(){
    return{
     hello:"親テンプレートのメソッドを実行"
    }
  },
  methods:{
    BtnClicked(a){
      console.log(a)
    }
  }
}
</script>

image.png

反応なし。。

親テンプレートに記述したメソッドを実行する場合は下記2パターンで検討する必要がある。

①子からイベントを引き継ぐ
②親テンプレート内にボタンを作成したクリックイベントを設定する


イベント情報を渡す ($event)

変数$eventを使うことで、クリックした画面上の位置情報などを渡すことができる。

(子)TmpBtn.vue
<template>
    <v-btn
    elevation="2"
    rounded
    width="20%"
    <!--clickイベントの引数で$eventを渡す-->
    @click="$emit('chiled-clicked', $event)"
    >
    ボタン
    </v-btn>
</template>
(親)parent.vue
<template>
  <v-app>
    <TmpBtn
    <!--子テンプレのイベントを受け取り、メソッドを実行-->
    @chiled-clicked="BtnClicked(hello, $event)"
    />
    <br>
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  name: "Parent",
  components:{
    TmpBtn
  },
  data(){
    return{
      hello:"親テンプレートのメソッドを実行"
    }
  },
  methods:{
    //第2引数に$eventを渡す
    BtnClicked(a, b){
      console.log(a)
      console.log(b)
    }
  }
}

▼実行結果
image.png

$eventの中身
MouseEvent {isTrusted: true, screenX: 77, screenY: 151, clientX: 77, clientY: 17, …}
isTrusted: true
screenX: 77
screenY: 151
clientX: 77
clientY: 17
ctrlKey: false
shiftKey: false
altKey: false
metaKey: false
button: 0
buttons: 0
relatedTarget: null
pageX: 77
pageY: 17
x: 77
y: 17
offsetX: 61
offsetY: 10
movementX: 0
movementY: 0
fromElement: null
toElement: span.v-btn__content
layerX: 61
layerY: 9
view: Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
detail: 1
sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}
which: 1
type: "click"
target: span.v-btn__content
currentTarget: null
eventPhase: 0
bubbles: true
cancelable: true
defaultPrevented: false
composed: true
timeStamp: 132300.8249999839
srcElement: span.v-btn__content
returnValue: true
cancelBubble: false
path: (8) [span.v-btn__content, button.v-btn.v-btn--rounded.theme--light.elevation-2.v-size--default, div.v-application--wrap, div#app.v-application.v-application--is-ltr.theme--light, body, html, document, Window]
__proto__: MouseEvent



$event内の特定のデータが欲しい場合はプロパティを指定する。

  methods:{
    BtnClicked(a, b){
      console.log(b.type)
    }
  }

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

娘とあと何日お風呂に入れるか計算するWebアプリ作ったら泣けてきた

娘とあと何回一緒にお風呂入れるだろう?

 「もう一緒に入りたくない」と言われる前に自ら娘とのお風呂は卒業したいもの。とはいえ、可能な限り一緒に入りたいというのが、父親の心情。あと何回一緒に入れるだろうかと考えたら、今日の1回も特別に思えるはず。そんな思いから、娘とあと何日一緒にお風呂に入れるか計算するWebアプリを作ってみました。
作ったWebアプリはこちら:point_right:あと何日一緒にお風呂に入れる?
image.png

あとこれしかない。。泣けてきた。。

娘の「パパ風呂」卒業のタイミングは、小学校3~4年生頃が多いようです。
娘の9歳の誕生日を卒業する日と定めると...
2020年10月26日時点で、あと、2608日
2日に一回だとしたら1304日
一週間に一回だとしたら372日...
泣けてきた:cry:

環境

コーディング
CodePen:Webブラウザ上でHTML/CSS/JavaScriptなど、主にフロントエンド言語のコーディングができるサービス
使用したライブラリ
vue.js
splitting.js:テキストアニメーションが実装できるライブラリ

ソース

index.html
<!-- 全体をVue.js有効にする -->
<div class="container text-center text-white" id="app">

  <!-- タイトル行 -->
  <div class="row my-3">
  <div class="col-sm-15 mx-auto"><div data-splitting><h1>あと何日一緒にお風呂入れる?</h1></div>
  </div>
  </div>

<img src="https://4.bp.blogspot.com/-YUk507i8b7s/UfIJFj6AMQI/AAAAAAAAWc0/KzQO-AiH6Jg/s800/dakko_papa_girl.png" width="30%"/>

  <div class="form-group">
  <label for="lastday">卒業する日</label><input class="form-control col-sm-6 mx-auto" type="date" id="lastday" onChange="calc();"/>
    <label for="today">今日の日付</label><input class="form-control col-sm-6 mx-auto" type="date" id="today" onChange="calc();"/>
 </div>
  <div class="form-group">
    <label for="days">一緒にお風呂に入れる日数</label><input class="form-control col-sm-6 mx-auto" type="text" readonly id="days"/>
  </div>

 <div data-splitting><label for="days">卒業のその日まで、有意義に過ごしてほしい。小さい娘を持つ全てのパパへ。</label></div>
<br>
</div>
<!-- 全体ここまで -->
style.css
@import url(https://fonts.googleapis.com/css?family=Kanit:600);

html { height: 100%; display: flex; }
body { margin: auto; }
html, body {
  background: #00043C;
  color: #FFF;
  font: normal 600 1.5vw/1.5 Kanit, sans-serif;
}

.splitting .char {
  animation: slide-in 1s cubic-bezier(.5, 0, .5, 1) both;
  animation-delay: calc(60ms * var(--char-index));
}

@keyframes slide-in {
  from {
    transform: translateY(-1em) rotate(-.5turn) scale(0.5);
    opacity: 0;
  }
}
script.js
Splitting();

function calc() {
  lastday = new Date($('#lastday').val());
  today = new Date($('#today').val());
  console.log(lastday.getTime());
  console.log(today.getTime());

  var days = Math.floor((lastday.getTime() - today.getTime()) / (1000 * 60 * 60 *24));

  $('#days').val(days);  
}

function today() {
  $('#today').val(formatdate());
}

function formatdate(date) {
  var toTwoDigits = function (num, digit) {
    num += ''
    if (num.length < digit) {
      num = '0' + num
    }
    return num
  };

  date = date ? date : new Date()
  var year = date.getFullYear()
  var month = date.getMonth() + 1
  var day = date.getDate()
  var yyyy = toTwoDigits(year, 4)
  var mm = toTwoDigits(month, 2)
  var dd = toTwoDigits(day, 2)
  var ymd = yyyy + "-" + mm + "-" + dd;
  return ymd;
}

$(function() 
{
  $('#lastday').val(formatdate());
  $('#today').val(formatdate());
}());

はじめてのWebアプリケーション

 プログラミング初心者の私でもCodepenと便利なライブラリを駆使して、割と簡単に実装することができました。今後は音を入れるとか、もう少しリッチな見た目とか、スマホ用に便利な画面とか、作れるようになったらより楽しいだろう。時間を見つけて、色々と試作してみたいです。

おまけ

 あまりに早く成長してしまうことが悲しいと思うこともありますが、我が子の成長はやはり嬉しいものです。一緒にお風呂に入れなくなっても、いつか娘と一緒にプレモルが飲めることを楽しみに頑張ります:beers:

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

vueのcss-scopedとcss-moduleの違い

この記事の対象者

vueの基礎を理解している

css-scopedのcss-moduleの共通点

両方ともコンポーネントのスタイルとして定義される

css-scoped

<template lang="html">
  <button class="button">ボタン</button>
</template>
<style lang="scss" scoped>
.button {
  // スタイル定義
}
</style>

ビルドの後のHTMLではクラス名の変化は特になし

<button data-v-015de462="" data-v-fae5bece="" type="button" class="button"> OK </button>

開発ツールでのCSSの見た目
クラス名の後ろに[data-v-015de462]が付与されている。

.button[data-v-015de462] {}

css-module

<template lang="html">
  <button :class="$style.button">ボタン</button> // $style.button という指定の仕方になる
</template>
<style lang="scss" module>
.button {
  // スタイル定義
}
</style>

ビルド後のHTMLを見るとクラス名が変化しています!!

<button data-v-fae5bece="" type="button" class="Button_button_Mvymr"> OK </button>

開発ツールでのCSSの見た目
scopedとは違い[data-XXX]は付かずビルド後に変化したクラス名が使われています!!

.Button_button_Mvymr {}

css-scopedとcss-moduleの異なる点とは

  • css-moduleの$style.buttonscript内でも使用することが可能。

公式ドキュメントから抜粋

<script>
export default {
  created () {
    console.log(this.$style.red)
    // -> "_1VyoJ-uZOjlOxP7jWUy19_0"
    // filename と className に基づいて出力された識別子。
  }
}
</script>
  • css-moduleは::v-deepでは決して上書きが決してできない

本来では下記の指定をすると子コンポーネントでscopedを指定していても::v-deepを使用するとスタイルを上書きすることが可能になりますが、css-moduleの場合は決して上書きすることができません

<style lang="scss" scoped>
::v-deep .button {
  background-color: green;
}
</style>

最後に

普段からクセでscopedを使いがちですが、今回はVSCodeの予測変換からmoduleが表示されていたので気になって調べて見ました。
css-moduleであればtemplate, script, styleから参照し合えるのでscopedより使いやすそうです。

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

VueRouter 404エラー対策

VueRouterを使ったデモアプリを作成

フロントはVue.js、バック(RESTAPI)はSpringBootのデモアプリを作りました
アプリケーションはjar実行しています(SpringBoot組み込みTomcatを利用)

トップページのBLOGボタン押下でブログページを表示します
image.png
ブログページはSpringBootで作成したRESTAPIのデータを表示しています
image.png
ブログページに表示している記事はRESTAPIで取得しています
image.png

ページをリロードしようとすると404エラーが発生

ブログページでリロードしようとすると404エラーで白い画面になってしまいます
image.png

この事象はVueRouterのリファレンスでも以下のように説明されています
VueRouterガイド-HTML5 History モード

しかしながら一点問題があります。シングルページのクライアントサイドアプリケーションなので、適切なサーバーの設定をしないと、ユーザーがブラウザで直接 http://oursite.com/user/id にアクセスした場合に 404 エラーが発生します。

router.jsでワイルドカードを指定するだけではダメだった

404エラー時に表示したいエラーページを作成して、router.jsにルーティング設定をしただけでは解消されませんでした

ErrorPage.vue
demo\web\src\pages\ErrorPage.vue
<template>
  <v-app>
    <v-app-bar
        absolute
        color="red lighten-1"
        dark
    >
      <v-toolbar-title>エラーが発生しました</v-toolbar-title>
    </v-app-bar>
    <v-container class="ml-0 mt-16">
      <v-row>
        <v-col cols="12">
          トップページに戻ってください
        </v-col>
      </v-row>
      <v-row>
        <v-col cols="4">
          <v-btn
              color="blue-grey lighten-4"
              width="100"
              v-on:click="clickTopPageBtn"
          >
            top page
          </v-btn>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: "ErrorPage",
  methods: {
    clickTopPageBtn: function () {
      this.$router.push("/")
    }
  }
}
</script>

<style scoped>

</style>


image.png

demo\web\src\router.js
import Vue from "vue"
import Router from "vue-router"

import TopPage from "@/pages/TopPage";
import BlogPage from "@/pages/BlogPage";
import ErrorPage from "@/pages/ErrorPage"

Vue.use(Router)

export default new Router({
    mode: "history",
    routes: [
        {
            path: "/",
            name: "トップページ",
            component: TopPage
        },
        {
            path: "/blogPage",
            name: "ブログ",
            component: BlogPage
        },
        {
            path: "*",
            name: "エラーページ",
            component: ErrorPage
        }
    ]
})

Apache .htaccessで解決

Windows用のApacheを導入しました(VueRouter公式ガイドにもWebServerを使えと書いてありましたね…)
Apache+SpringBootJar構成でアプリが動くように設定していきます

AJP通信の設定

今回のアプリはブログページでVue.jsの画面からSpringBootのAPIを呼び出すので
AJP通信を利用してフロントとバックを繋ぎます

ApacheのAJP通信設定

Apacheにはビルド済みVue.jsを配置します
8009ポートでAJP通信できるようにhttpd-proxy-ajp.confを作成します

\httpd-2.4.46-o111h-x86-vc15\Apache24\conf\extra\httpd-proxy-ajp.conf
<Location /blog>
  ProxyPass ajp://127.0.0.1:8009/blog
</Location>

httpd.confでもAJP通信ができるよう修正します

\httpd-2.4.46-o111h-x86-vc15\Apache24\conf\httpd.conf
# 以下のモジュール読み込み箇所のコメントを解除
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
# 末尾に先ほど作成したhttpd-proxy-ajp.confを読み込む設定
Include conf/extra/httpd-proxy-ajp.conf

SpringBootのAJP通信設定

SpringBootの組み込みTomcatでApacheとAJP通信する設定クラスを作成します

demo\src\main\java\com\example\demo\config\AppConfig.java
package com.example.demo.config;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.ajp.AbstractAjpProtocol;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Connector ajpConnector = new Connector("AJP/1.3");
        ajpConnector.setPort(8009);
        ajpConnector.setSecure(false);
        ajpConnector.setAllowTrace(false);
        ajpConnector.setScheme("http");
        ((AbstractAjpProtocol) ajpConnector.getProtocolHandler()).setSecretRequired(false);
        tomcat.addAdditionalTomcatConnectors(ajpConnector);

        return tomcat;
    }
}

.htaccess対応

.htaccessにはリダイレクトの設定を記述します
Apacheのドキュメントルートに配置しただけだと.htaccessが適用されません

httpd.confの.htaccess適用設定

httpd.confを以下のように変更します

\httpd-2.4.46-o111h-x86-vc15\Apache24\conf\httpd.conf
# 以下のモジュール読み込み箇所のコメントを解除
LoadModule rewrite_module modules/mod_rewrite.so
# ドキュメントルートのAllowOverride NoneをAllに変更
DocumentRoot "${SRVROOT}/htdocs"
<Directory "${SRVROOT}/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

また、Apacheを配置しているディレクトリにmod_rewrite.soファイルが存在することを確認します
私の環境ではC:\httpd-2.4.46-o111h-x86-vc15\Apache24\modules\mod_rewrite.soでした

.htaccessを作成

VueRouter公式ガイドに記載されている設定内容をそのまま使っています

\httpd-2.4.46-o111h-x86-vc15\Apache24\htdocs\.htaccess
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

このファイルをApacheのドキュメントルートに配置します
私はC:\httpd-2.4.46-o111h-x86-vc15\Apache24\htdocs\に配置しました

これでApacheとアプリケーションの設定は完了です

ApacheにVue.jsリソースを配置

いつも通りnpm run buildを実行すればOKです

cd C:\Users\risab\git\demo\web
npm run build

package.jsonで特に指定していなければビルド済みリソースは\dist配下に出力されます

出力されたビルド済みリソースをApacheドキュメントルートに配置します
image.png

リソースを配置したら、WindowsのサービスからApacheサービスを起動しておきます
Apacheサービス登録は以下のコマンドでできます

cd C:\httpd-2.4.46-o111h-x86-vc15\Apache24\bin
httpd -k install

SpringBootJarを生成

詳細な手順はこちら gradleでjarを生成します

cd C:\Users\risab\git\demo
gradlew bootJar

jarが生成されたら以下のコマンドでアプリケーションを起動します

cd C:\Users\risab\git\demo\build\libs
java -jar demo-0.0.1-SNAPSHOT

これで対策完了!

Apacheにフロントリソースを配置しているのでhttp://localhost/にアクセスします
image.png
VueRouterでページ遷移、AJP通信で画面からバックのAPIも呼び出せています
画面のリロード時も404エラーが発生せず、リロードできるようになっています
image.png
また、存在しないURLにアクセスした場合は.htaccessとVueRouterのワイルドカードが適用されて
エラーページが表示されるようになりました
image.png

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

v-bindの使い方。親のデータを子のテンプレートに渡す方法。

Vueのv-bindで、親から子へのデータ受け渡しを整理。

以下のようなvueファイルを見たときに、:keyなどタグの中身(任意で設定した属性)が何を表しているのかを理解できるようになる。

<VrBtn
:key="key"
:disabled="disabled"
:command="command"
/>
export default {
  props: {
    value: { type: Boolean },
    disabled: { type: Boolean, default: false },
    command: { type: Object, required: true },
  },
}


データ受け渡しの流れ

データ受け渡しの流れは4steps。
属性に変数を入れて、その属性を親と子で受けわたす。

親:①子に渡すデータを定義
 ↓
親:②子のテンプレートタグに属性と変数を記述
 ↓
子:③propsで受け取る属性を定義
 ↓
子:④属性を指定してデータ呼び出し

▼注意点
・親から渡すデータは変数。
 ┗ ダブルクオテーションで囲むがテキストではない。
 ┗ :属性名="変数名"の形で記述。属性を子に渡す。
 ┗ : は v-bind: の省略形

・子のpropsではデータの型などを指定可能
 ┗ String:文字列、Boolean:真偽値
 ┗ required: true データの必要性
 ┗ default: false/true 真偽値のデフォルト設定


データの受け渡し例

・使うファイルは2つ
親:parent.vue
子:TmpBtn.vue (vuetifyでボタンを表示)

・実現したいこと
親で定義したデータを子のテンプレート内で呼び出す。

(親)parent.vue
<template>
  <v-app>
    <TmpBtn
    <!--②子のテンプレートタグに属性と変数を記述-->
    :bind="text"
    />
  </v-app>
</template>

<script>
import TmpBtn from "./TmpBtn"

export default {
  name: "Parent",
  components:{
    TmpBtn
  },
  data(){
    return{
      //①子に渡すデータを定義
      text:"Text form Parent"
    }
  }
}
</script>


(子)TmpBtn.vue
<template>
  <v-btn
  width="20%"
  elevation="2"
  rounded
  >
  <!--④属性を指定してデータ呼び出し-->
  {{bind}}
  </v-btn>
</template>

<script>
export default {
  props:{
    //③propsで受け取る属性を定義
    bind: {type:String},
  }
}
</script>



▼出力結果
image.png

子のテンプレートを表示したときに、無事、親のデータを受け渡すことができた。


まとめ

以下のような記述を見たら、親から子にデータを渡していることがわかる。

<VrBtn
:key="key"
:disabled="disabled"
:command="command"
/>

propsがあれば、子のテンプレートで親からデータを受け取っているなということがわかる。

export default {
  props: {
    value: { type: Boolean },
    disabled: { type: Boolean, default: false },
    command: { type: Object, required: true },
  },
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

画面で入力された注文数をグラフに反映するWebアプリ(仮)

入力された注文数をグラフに反映してみた

movie

今日の注文数を入力したらすぐ反映されますね!
DBとか使ってなくてすぐ表示させてるだけだから!

URLはこちらです!→今日までの売上を可視化しよう

使い方

 一日の終わりに、今日注文された数を入力
 →こんだけ増えたよって可視化される

苦労した点 :smile:

今回は、裏のロジックというより簡単な情報をうまく表示するところを意識しました。

・グリッドの理解をしないままbootstrapを使い始めて、表が右に行ったり、めちゃくちゃ高さが低くなったり、小さくなったり。
 それもあって、ちゃんと理解をするためにこちらのサイトで勉強させていただきました。↓
 bootstrapの構造について学ぶ

・最初Chart.jsを使おうとしていましたが、new Chart.jsをするところで、
 Vue.jsから呼び出したかったが、どう記述すればよいのかわからなかったので今回はgstaticを使いました。

今回やりたかったけどできなかったこと :astonished:

・DBを使ってデータの出し入れ
・月を選ぶ。今回のは10月にしか追加されない。。。
・「数値をクリア。」どこのだよ!と思うのを解消する。 今は10月の数値が根こそぎ消える。
・目標の数値の設定や、そことの差の描画
・描画方法の選定 絶対もっときれいでおしゃれなやつあるやろ!

環境

エディタ:codepen
CSS:bootstrap
使用ライブラリ
  vue.js
  loader.js gstatic

ソース

HTML部分はこちら↓

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>CodePen - chart</title>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css'>

</head>
<body>
<!-- partial:index.partial.html -->
<head>
  <script src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<!-- 全体をVue.js有効にする -->
<div class="container text-center text-white bg-dark" id="app">

  <!-- タイトル行 -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto"><h1>一日の終わりに注文数を入力</h1></div>
  </div>

  <!-- タスク入力行 -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto">
      <input v-model:value="task" placeholder="注文数を入力" class="form-control"><br>
      直前に追加した注文数:{{ previous_num }} <button v-on:click="addTask" class="btn btn-primary">追加</button>
    </div>
  </div>

  <!-- 全てのタスクをクリアするボタン -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto">
      <button v-on:click="clearAll" class="btn btn-danger">数値をクリア</button>
    </div>
  </div>

  <!-- タスク追加されると表示される部分 -->
  <div class="row my-3">

    <div class="col-sm-6 mx-auto">
    </div>
  </div>
      <div class="col-lg-10 mx-auto" id="stage"></div>  

</div><!-- 全体ここまで -->
<!-- partial -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue-chartjs/3.5.1/vue-chartjs.min.js'></script><script  src="./script.js"></script>

</body>
</html>




JS部分はこちら↓

//必要なパッケージの読み込み
google.charts.load('current', {packages: ['corechart']});
// google.charts.setOnLoadCallback(drawChart);


const app = new Vue({
  el: '#app', // Vueが管理する一番外側のDOM要素
  data: {
    // Vue内部で使いたい変数は全てこの中に定義する
    task: '',
    todoList: [['', '数量'],
        ['1月', 65],
        ['2月', 59],
        ['3月', 80],
        ['4月', 81],
        ['5月', 56],
        ['6月', 55],
        ['7月', 55],
        ['8月', 55],
        ['9月', 55],
        ['10月', 0],
        ['11月', 0],
        ['12月', 0]], // これは配列
    chart:"",
    previous_num:0,
  },
  methods: {
    // 関数はここ
    addTask: function() {
      console.log('次のタスクが追加されました:', this.task);
      // 配列の先頭に現在のタスク内容を追加する(最後尾の場合はpush)
      this.todoList[10][1] = Number(this.todoList[10][1]) + Number(this.task);
      console.log('現在のToDo一覧:', this.todoList);
      this.previous_num = this.task;
      this.drawChart();
    },
    // 以下を追加、関数名はなんでもよい
    clearAll: function() {
      this.todoList = [['', '数量'],
        ['1月', 65],
        ['2月', 59],
        ['3月', 80],
        ['4月', 81],
        ['5月', 56],
        ['6月', 55],
        ['7月', 55],
        ['8月', 55],
        ['9月', 55],
        ['10月', 0],
        ['11月', 0],
        ['12月', 0]];
      console.log('全てのToDoが消去されました');
        this.drawChart();
    },
    drawChart: function() {
      console.log('drawChart');
      //オプション設定
      var options = {
        'title': '注文数',
      };

      //月別データ
      var array = this.todoList;
      var data = google.visualization.arrayToDataTable(array);

      var stage = document.getElementById('stage');

      //グラフの種類を設定
      var chart = new google.visualization.ColumnChart(stage);

      //データとオプションを設定
      chart.draw(data, options);
    }

  },
});

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

Vue.jsをSpringBootアプリに組み込む

Vue.jsプロジェクトをjarに内包して実行

フロントエンドはVue.js、バックエンドはJava(SpringBoot)でアプリを作りたいけど、
Vue.jsとJavaでプロジェクトを分けたくない…というシーンに遭遇したので書いておきます

ビルド済みVue.jsリソースをjarファイルに内包してSpringBootの組み込みTomcatで実行します

開発環境

  • Windows10Pro
  • AdoptOpenJDKJ9 1.8.0_265
  • npm 6.14.6
  • vue-cli 4.5.4

Vue.js+SpringBootプロジェクトを作成

IntelliJでSpringBootプロジェクトを作成します

以下のコマンドで作成したSpringBootプロジェクトの中にVue.jsプロジェクトを作成します

cd C:\Users\risab\git\demo
vue create web

これでVue.js+SpringBootプロジェクトができました 画像のwebディレクトリがVue.jsプロジェクトです

image.png

アプリケーションを実装する

今回はVue.jsで作成した簡単な画面にSpringBootで作成したRESTAPIのレスポンスを表示するアプリを作成します

RESTAPI

/blog/entries/latestにアクセスすると最新のブログタイトルと記事内容が返される
RESTAPIコントローラーを作成しました

demo\src\main\java\com\example\demo\controller\BlogController.java
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/blog")
public class BlogController {

    /**
     * 最新ブログ記事を取得
     * @return タイトルと内容のMap
     */
    @RequestMapping(value = "/entries/latest", method = RequestMethod.GET)
    public Entry getLatestEntry() {
        Entry entryData = new Entry();
        // TODO DBから最新の記事データを取得
        entryData.setTitle("VueRouterを使ってみた");
        entryData.setContent("VueRouterで簡単にページルーティングができました");
        return entryData;
    }

    /**
     * ブログ記事クラス
     */
    private class Entry{
        private String title;
        private String content;

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }
}

IntelliJでSpringBootアプリを作成するとアプリ起動に必要な以下のクラスは自動で生成されています

DemoApplication.java
demo\src\main\java\com\example\demo\DemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

ServletInitializer.java
demo\src\main\java\com\example\demo\ServletInitializer.java
package com.example.demo;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoApplication.class);
    }

}

アプリ画面

Vue.js+Vuetify+VueRouterで簡単な画面を2つ作成しました

トップページは画面タイトルと「BLOG」ボタンだけのシンプルな画面です

demo\web\src\pages\TopPage.vue
<template>
  <v-app>
    <v-app-bar
        absolute
        color="teal lighten-3"
        dark
    >
      <v-toolbar-title>トップページ</v-toolbar-title>
    </v-app-bar>
    <v-container class="ml-0 mt-16">
      <v-row>
        <v-col cols="4">
          <v-btn
              color="brown lighten-3"
              width="100"
              v-on:click="clickBlogBtn"
          >
            blog
          </v-btn>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: "TopPage",
  methods: {
    clickBlogBtn: function () {
      this.$router.push("/blogPage")
    }
  }
}
</script>

<style>
</style>

ブログページは先ほど作成したRESTAPIを呼び出してブログ記事データを表示します

demo\web\src\pages\BlogPage.vue
<template>
  <v-app>
    <v-app-bar
        absolute
        color="teal lighten-3"
        dark
    >
      <v-toolbar-title>tech blog</v-toolbar-title>
    </v-app-bar>
    <v-container class="ml-0 mt-16">
      <v-row>
        <v-col cols="4">
          <v-btn
              color="blue-grey lighten-4"
              width="100"
              v-on:click="clickTopPageBtn"
          >
            top page
          </v-btn>
        </v-col>
      </v-row>
      <v-row>
        <v-card class="ml-3" color="yellow lighten-5">
          <v-card-title>{{ blogPost.title }}</v-card-title>
          <v-card-text>
            {{ blogPost.content }}
          </v-card-text>
        </v-card>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: "BlogPage",
  data: () => ({
    // APIから取得した記事データをバインド
    blogPost: {
      title: "",
      content: ""
    }
  }),
  mounted() {
    // RESTAPI呼び出し
    const el = this
    this.axios.get("/blog/entries/latest")
        .then(response => {
          el.blogPost = response.data
        })
  },
  methods: {
    clickTopPageBtn: function () {
      this.$router.push("/")
    }
  }
}
</script>

<style>
</style>

以下のファイルも修正・作成しました main.jsは変更不要です

App.vue
demo\web\src\App.vue
<template>
  <v-app>
    <router-view/>
  </v-app>
</template>

<script>
export default {
  name: 'App'
};
</script>

router.js
demo\web\src\router.js
import Vue from "vue"
import Router from "vue-router"

import TopPage from "@/pages/TopPage";
import BlogPage from "@/pages/BlogPage";

Vue.use(Router)

export default new Router({
    mode: "history",
    routes: [
        {
            path: "/",
            name: "トップページ",
            component: TopPage
        },
        {
            path: "/blogPage",
            name: "ブログ",
            component: BlogPage
        }
    ]
})


これでアプリケーションの作成は完了です

ビルド済みVue.jsの出力先を変更

この時点でwebディレクトリで npm run build するとweb\dist\配下にビルド済みVue.jsリソースが出力されます
web\package.jsonを修正してJavaから見える場所に出力するようにします

scripts.buildを以下のように修正してSpringBootプロジェクトの静的リソースディレクトリに出力するようにします

demo\web\package.json
{
  "name": "demo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --dest ../src/main/resources/static/",
    "lint": "vue-cli-service lint"
  },

上記の通りpackage.jsonを修正してビルドすると以下のようになります

cd C:\Users\risab\git\demo\web
npm run build

image.png

jarを生成する

jarファイルはgradleで生成するので、以下の記述をbuild.gradleの末尾に追加します
Main-Classには@SpringBootApplicationを付けているクラスを指定します

demo\build.gradle
jar {
    manifest {
        attributes 'Main-Class': 'DemoApplication'
    }

以下のコマンドを実行するとbuild\libs\配下にjarファイルが生成されます

cd C:\Users\risab\git\demo
gradlew bootJar

image.png

あとは生成されたjarファイルを実行するだけです!

cd C:\Users\risab\git\demo\build\libs
java -jar demo-0.0.1-SNAPSHOT

Started DemoApplication in 2.893 seconds (JVM running for 3.378)のように出力されていればSpringBootアプリケーションが起動できています

SpringBootの組み込みTomcatを利用しているので、ブラウザでhttp://localhost:8080/にアクセスします
image.png

Vue.jsからJavaで作ったRESTAPIも実行できています
image.png

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

英単語から絵文字を検索するWebアプリを作ってみた

まずは動かしてみた

英単語「dog」をいれると犬の絵文字が出てきました。
image.png

もし、その絵文字がなければ、エラーメッセージが出るようにしてます。
image.png

URL

画面は一般公開しています。
https://todo-heihei.tk/
c

使用したライブラリ

■Javascript
●Vue.js
https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js
●jQuery.js
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
●Bootstrap
https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js
●emojione
https://cdnjs.cloudflare.com/ajax/libs/emojione/4.5.0/lib/js/emojione.min.js

■CSS
●Bootstrap
https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css
●emojione
https://cdnjs.cloudflare.com/ajax/libs/emoji-awesome/0.0.2/css/emojione.min.css

ソース

プログラム自体はCodePenを利用しています。

index.html
<!DOCTYPE html>
<html lang="ja" >
<head>
  <meta charset="UTF-8">
  <title>絵文字検索ツール</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css'>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/emoji-awesome/0.0.2/css/emojione.min.css'>
</head>
<body>
<!-- partial:index.partial.html -->
<!-- 全体をVue.js有効にする -->
<div class="container text-center text-white bg-dark" id="app">

  <!-- タイトル行 -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto"><h1>絵文字検索ツール</h1></div>
  </div>

  <!-- タスク入力行 -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto">
      <input v-model:value="word" placeholder="単語を入力…" class="form-control"><br>
      <button v-on:click="searchEmoji" class="btn btn-primary">絵文字を調べる</button>
    </div>
  </div>

  <!-- タスク追加されると表示される部分 -->
  <div class="row my-3">
    <div class="col-sm-6 mx-auto">
      <p v-if="emoji === ''" class="alert alert-danger">対象の絵文字がないよ</p>
      <p v-else class="alert alert-success">{{ emoji }}</p>
    </div>
  </div>

</div><!-- 全体ここまで -->
<!-- partial -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/emojione/4.5.0/lib/js/emojione.min.js'></script>
  <script  src="./script.js"></script>

</body>
</html>
script.js
const app = new Vue({
  el: '#app', // Vueが管理する一番外側のDOM要素
  data: {
    // Vue内部で使いたい変数は全てこの中に定義する
    word: '',
    emoji: '', 
  },
  methods: {
    // 関数はここ
    searchEmoji: function() {
      console.log('次の単語が入力されました:', this.word);
      console.log('絵文字は次の通りです:', emojione.toImage(':' + this.word + ':'));
      this.emoji = emojione.toImage(':' + this.word + ':');
      if (this.emoji.indexOf('img') == -1) {
        this.emoji = '';
      }      
    },
  },
});

考察

・絵文字だけ返すことができずに、imgタグが出てくるかっこ悪い表示となっている。
 →絵文字だけ返却できるようにしたい。

・英単語しか検索できない。
 →日本語で検索できるようにしたい。

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

タグクラウド、ワードクラウド laravel と vue.js を添えて

タグクラウド作りてぇ。
ということでライブラリと作り方を紹介

海外では タグクラウド ではなく、 ワードクラウドというのだろうか。

インストール

https://github.com/feifang/vue-wordcloud

npm install vue-wordcloud

コピペで動く

<style>

    div.tooltip {
        position: absolute;
        width: 210px !important;
        height: 70px !important;
        padding: 16px;
        font: 18px Arial;
        line-height: 24px;
        color: white;
        background: black;
        border: 0px;
        border-radius: 2px;
        pointer-events: none;
    }

</style>

<template>
    <div>

        <div class="cloud">

            <wordcloud
                    :data="defaultWords"
                    nameKey="name"
                    valueKey="value"
                    :showTooltip="true"
                    :wordClick="wordClickHandler">
            </wordcloud>

        </div>


    </div>
</template>

<script>



    import wordcloud from 'vue-wordcloud'

    export default {
        components: {
            wordcloud
        },

        data () {

            return {

                myColors: ['#1f77b4', '#629fc9', '#94bedb', '#c9e0ef'],
                defaultWords: [
                    {
                    "name": "りんご",
                    "value": 26
                },
                    {
                        "name": "みかん",
                        "value": 19
                    },
                    {
                        "name": "おれんじ",
                        "value": 18
                    },
                    {
                        "name": "look",
                        "value": 16
                    },
                    {
                        "name": "two",
                        "value": 15
                    },
                    {
                        "name": "fun",
                        "value": 9
                    },
                    {
                        "name": "know",
                        "value": 9
                    },
                    {
                        "name": "good",
                        "value": 9
                    },
                    {
                        "name": "play",
                        "value": 6
                    }
                ],
            };
        },

        methods: {
            wordClickHandler(name, value, vm) {
                console.log('クリックされたよ', name, value, vm);
            },
        }




    }
</script>


以上

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

Vue.js × django REST framework 学習ロードマップ

はじめに

本記事は「急がば回れ」精神に基づいて、じっくり確実に Vue.js と django を組み合わせ使えるようになるための学習教材を列挙しました。

Vue.js の学習教材

超Vue.js 2 完全パック - もう他の教材は買わなくてOK! (Vue Router, Vuex含む) | Udemy
https://www.udemy.com/course/vue-js-complete-guide/
→ Vue.js の基礎を一通り動画で学ぶ。

django の学習教材

【徹底的に解説!】Djangoの基礎をマスターして、3つのアプリを作ろう! | Udemy
https://www.udemy.com/course/django-3app/
→ django の基礎を一通り動画で学ぶ。

django REST framework の学習教材

Django REST Framework で API サーバーを実装して得た知見まとめ(OAuthもあるよ)
https://qiita.com/furuuchin/items/c6d6230aa327ad7b337a
→ 下記の英語動画に備えて、こちらの記事のコードを写経して概要を掴む。

The Complete Guide to Django REST Framework and Vue JS | Udemy
https://www.udemy.com/course/the-complete-guide-to-django-rest-framework-and-vue-js/
→ django REST framework の基礎と Vue.js との組み合わせ方を一通り動画で学ぶ。英語字幕出せます。

[Django REST Framework] View の使い方をまとめてみた - くろのて
https://note.crohaco.net/2018/django-rest-framework-view/
→上記の動画は英語なので View についての補足はコチラで。

[Django REST Framework] Serializer の 使い方 をまとめてみた - くろのて
https://note.crohaco.net/2018/django-rest-framework-serializer/
→上記の動画は英語なので Serializer についての補足はコチラで。

さいごに

追記してアップデートしていきます。

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