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

【SVG・CSS・Vue.js】SVGが画面サイズの変化時にちらつく場合の対処

width・heightの設定を確認

svgのある画面でVue.jsにてv-bindで要素の表示・非表示を切り替えていたところ、
svgの中身がピクピクと小さくなったり大きくなったりする(ちらつく)場面に遭遇。
height・widthの片方を指定するとサイズが定まらず事象が起こる模様。

簡単な対処法にも関わらず手間取ったためメモします。

  // svgをwrapした要素
  #svg_img {
    width: 100px;
    height: 20px; // heightの指定が抜けていた
  }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.jsの <template>タグには複数の役割がある

先に結論書いてしまいますと、全部公式ドキュメントに書いてあります。

でも、書いてある箇所がバラバラなので
先に公式ドキュメントをちゃんと目を通していれば混乱しないのでしょうが、
ちゃんと読まずにいきなり現場のソースコード読んで、まぁどうにかなんだろうと思ったら
ん?この <template><template> はなんか違うの?? と混乱してしまった人(私です)向けにまとめました。

<template> タグには以下の役割があります。

  • 条件付きレンダリングで複数要素を対象とする場合(v-if)
  • リストレンダリングで複数要素を対象とする場合(v-for)
  • 名前付きスロット(v-slot)
  • 単一ファイルコンポーネント

条件付きレンダリングで複数要素を対象とする場合(v-if)

公式ドキュメントはこちら
https://jp.vuejs.org/v2/guide/conditional.html#%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%A7%E3%81%AE-v-if-%E3%81%AB%E3%82%88%E3%82%8B%E6%9D%A1%E4%BB%B6%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97

公式サイトにある例を引用:

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

v-if 属性を持った <template> タグは、 条件付きレンダリングです。

上の例でいうと、oktrue と評価される場合、以下のようにレンダリングされます。

  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>

<template> タグ自体はレンダリングされません。

リストレンダリングで複数要素を対象とする場合(v-for)

公式ドキュメントはこちら
https://jp.vuejs.org/v2/guide/list.html#lt-template-gt-%E3%81%A7%E3%81%AE-v-for

公式サイトにある例を引用:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for 属性を持った<template> タグは、 リストレンダリングです。

上の例でいうと、例えば items[{msg: "foo"},{msg: "bar"},{msg: "baz"}] なら
以下のようにレンダリングされます。

<ul>
    <li>foo</li>
    <li class="divider" role="presentation"></li>
    <li>bar</li>
    <li class="divider" role="presentation"></li>
    <li>baz</li>
    <li class="divider" role="presentation"></li>
</ul>

<template> タグ自体はレンダリングされません。

名前付きスロット(v-slot)

公式ドキュメントはこちら
https://jp.vuejs.org/v2/guide/components-slots.html#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%82%B9%E3%83%AD%E3%83%83%E3%83%88

こちらはまず「コンポーネント」の理解から始めないといけないのですが
その説明をしだすと長くなるので、公式ドキュメントをみていただくとして、雑に説明すると

「コンポーネント」は、Vueの要素を部品化したもので
「スロット」は、コンポーネントを利用する際に、コンポーネントを呼び出す側からデータ等を渡すことができるのですが、それをはめ込む要素
のことです。

公式サイトの例を一部修正して引用 1

base-layout というコンポーネントが、以下のような構成だったとして。

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot name="main"></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

base-layoutを呼び出す側で、スロットに入れたい内容を、 v-slot 属性を指定した <template> タグで指定します。

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <template v-slot:main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

実際のレンダリングは以下の通り:

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

単一ファイルコンポーネント

公式ドキュメントはこちら
https://jp.vuejs.org/v2/guide/single-file-components.html

中規模以上のアプリケーションを実装していく場合
コンポーネントをそれぞれのファイル(.vueファイル)に分割し
webpack等でビルドする…という流れになります。

この時、コンポーネント化された.vueファイルで
HTML部、JavaScript部、CSS部を分離したとき、
HTML部のルート要素として <template> タグ を指定します。

公式ドキュメントより引用

<template>
  <p>{{ greeting }} World!</p>
</template>

<script>
module.exports = { 
  data: function () { 
    return { 
      greeting: 'Hello' 
    } 
  } 
} 
</script> 

<style scoped>
p {
  font-size: 2em;
  text-align: center;
}
</style>

  1. デフォルトスロットの説明がまた面倒なので、デフォルトスロットを使わない説明に変えています。 

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

はじめてVue.jsを触ってみた

今までReactしか触ったことがなかったので、以前から触ってみたいなと思っていたVue.jsを初めて触ってみました。
1時間ほどvueを触ってみた感触を書き記しておきます。

Vueの環境構築

Vue.js を vue-cli を使ってシンプルにはじめてみる
上の記事を参考に環境構築をしてみます。

$ vue create vue-test
$ cd vue-test
$ npm run serve

この3つをターミナルで入力するだけでとりあえず初期画面を立ち上げることができました。
ここまでは簡単ですね。
スクリーンショット 2019-08-19 15.09.15.png

コンポーネントを編集してみる

ぱっと見た感じcomponentsフォルダ内のHelloWorld.vueApp.vueで呼び出しているみたいです。
ごちゃごちゃしてて見にくいのでいらないものを全部消していきます。

App.vue
<template>
  <div>
    <HelloWorld />
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "app",
  components: {
    HelloWorld
  }
};
</script>
HelloWorld.vue
<template>
  <div>HelloWorld!</div>
</template>

これで画面上にHelloWorld!が表示されるだけのシンプルな画面になりました。

入力フォームを作ってみる

次にフォームを作成してみます。

HelloWorld.vue
<template>
  <div>
    HelloWorld!
    <br />
    <input v-model="message" />
    <p>入力された文字: {{ message }}</p>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    message: String
  }
};
</script>

scriptタグの中でpropsを定義すれば入力された値が取得できます。
スクリーンショット 2019-08-19 15.41.26.png
Reactで言うところのvalueがvuejsではv-modelになるようですね。
ReactのようにonChangeを使わなくても入力された値を即時に取得することができるみたいです。

ちなみに下記のように書けば他のコンポーネントにもpropsの値を渡すことができるようです

HelloWorld.vue
<template>
  <div>
    HelloWorld!
    <br />
    <input v-model="message" />
    <SecondComponent :msg="message" />
  </div>
</template>

<script>
import SecondComponent from "./SecondComponent.vue";

export default {
  name: "HelloWorld",
  props: {
    message: String
  },
  components: {
    SecondComponent
  }
};
</script>
SecondComponent.vue
<template>
  <div>
    <p>入力された文字: {{ msg }}</p>
  </div>
</template>

<script>
export default {
  name: "SecondComponent",
  props: {
    msg: String
  }
};
</script>

他のコンポーネントに値を渡すのはReactだと{this.props.msg}を書くだけで簡単に渡せるので、この辺りはReactの方が簡単な気がしますね。
(TypeScriptなどを使って型定義する場合はinterfaceを書く必要があるのでVueと書く量は大差ないかもしれませんが)

クリックイベントを使ってみる

クリックイベントはscriptタグ内にmethodを書くことで作成できるようです。

HelloWorld.vue
<template>
  <div>
    <button type="button" @click="onClick">アラート</button>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  methods: {
    onClick: function() {
      alert("アラートを表示");
    }
  }
};
</script>

スクリーンショット 2019-08-19 16.15.37.png

ReactのonClickがvueでは@clickと書くようです。
イベントを作成する時、Reactだとfunctionをbindしてあげる必要があります。

React
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
  }

  onClick() {
    alert("アラートを表示");
  }

クリックイベントの作成はvueの方が楽な気がしますね。

あまり難しいことは試していませんが、ざっとvueを使ってみた感じ、Reactを触ったことがあればvueを使うのはそんなに難しくないなと思いました。
深く調べなくてもvueは直感的に使える気がします。
次はvueでAPI通信とか試してみたいですね。

参考

Vue.jsでフォームを使おう
Vue.js を vue-cli を使ってシンプルにはじめてみる

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

Vue基礎:フィルター

Vueでは日付フォーマットするなどの処理を「|」で簡単に記載できるのはフィルター機能です。
一般的なテキストフォーマットを適用するために使用できるフィルタを定義できます。
フィルタは、mustache 展開と v-bind 式 2 つの場所とも使用できます

フィルターの定義方法

1. コンポーネント内(ローカル)

コンポーネント内で定義する。
例:

filters: {
  formatDate: function (date) {
    if (!date) {
      return ''
    }
    moment.locale("ja");
    var d = moment.tz(date, "YYYYMMDDHHmm", "Asia/Tokyo");
    return d.format("M/D(ddd) HH:mm");
  }
}

2. 共通(グローバル)

main.jsの中で定義するなど
例:

Vue.filter('formatDate', function(date){
  if (!date) {
    return ''
  }
  moment.locale("ja");
  var d = moment.tz(date, "YYYYMMDDHHmm", "Asia/Tokyo");
  return d.format("M/D(ddd) HH:mm");
}

使用例

1. mustache 展開

{{ date| formatDate }}

2. v-bind 式

<div v-bind:label="date | formatDate"></div>

複数のフィルター

Shellのように連続フィルターをしたい場合は、下記のように複数のメソッドを設定できます。

{{ message | filterA | filterB }}

メソッドの呼び出し

メソッドは複数パラメータの場合はメソッド名ではなく、メソッドを呼び出す記載もOKです。

{{ message | filterA('arg1', arg2) }}

filterAは3つのパラメータがあるメソッドです。
例:

function filterA(message, param2, param3) {
  return  message + param2 + param3
}

参考URL:https://jp.vuejs.org/v2/guide/filters.html

以上

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

Vue基礎:Vuexの永続化対応

Vuexのステートデータを永続化対応しないと、F5とかページreloads操作でデータはなくなります。
一般的に永続化の対応が必要だと思います。

ツールとして、「vuex-persistedstate」がよく使います。

vuex-persistedstateとは

Persist and rehydrate your Vuex state between page reloads.

インストール

npm install --save vuex-persistedstate

storeに設定追加

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState()],
})

ストレージの種類

1. LocalStorage

デフォルトのストレージはlocalstorageです。

2. SessionStorage

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({ storage: window.sessionStorage })],
})

3. Cookies

cookieに保存したい場合は、カスタマイズが必要です。
getItem、setItem、removeItemを実装すればよいです。
下記はCookieに保存するサンプルです。

import { Store } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'

const store = new Store({
  // ...
  plugins: [
    createPersistedState({
      storage: {
        getItem: key => Cookies.get(key),
        setItem: (key, value) =>
          Cookies.set(key, value, { expires: 7, secure: true }), //7日間有効
        removeItem: key => Cookies.remove(key),
      },
    }),
  ],
})

js-cookies: https://github.com/js-cookie/js-cookie
vuex-persistedstate:https://github.com/robinvdvleuten/vuex-persistedstate

以上

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

Vuexの永続化対応

Vuexのステートデータを永続化対応しないと、F5とかページreloads操作でデータはなくなります。
一般的に永続化の対応が必要だと思います。

ツールとして、「vuex-persistedstate」がよく使います。

vuex-persistedstateとは

Persist and rehydrate your Vuex state between page reloads.

インストール

npm install --save vuex-persistedstate

storeに設定追加

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState()],
})

ストレージの種類

1. localstorage

デフォルトのストレージはlocalstorageです。

2. sessionStorage

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({ storage: window.sessionStorage })],
})

3. cookie

cookieに保存したい場合は、カスタマイズが必要です。
getItem、setItem、removeItemを実装すればよいです。
下記はCookieに保存するサンプルです。

import { Store } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'

const store = new Store({
  // ...
  plugins: [
    createPersistedState({
      storage: {
        getItem: key => Cookies.get(key),
        setItem: (key, value) =>
          Cookies.set(key, value, { expires: 7, secure: true }), //7日間有効
        removeItem: key => Cookies.remove(key),
      },
    }),
  ],
})

js-cookies: https://github.com/js-cookie/js-cookie
vuex-persistedstate:https://github.com/robinvdvleuten/vuex-persistedstate

以上

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

Vue.jsを仮想ウインドウ化するモジュールをnpmに登録してみる

Vue.jsを仮想ウインドウ化するモジュールをnpmに登録してみる

1.動作画面

動作画面

 
見ての通り、Vue.jsを仮想ウインドウ化してみました。
内容的には大したことはしていません。
以前作成したJavaScript-Window-Framework(JWF)にVueのコンポーネントをマウントする処理を入れただけです。

2.使い方

モジュールのインストール

npm -D i @jswf/vue

 npmでjwfスコープを取りたかったのですが、すでに取得済みだったようなのでjswfになっています。
 そのうちJWF本体をこちらのスコープに移すかもしれません。
 ちなみにnpmのスコープ登録の仕方を知ったのは最近になってからです。

サンプルコード

以下はrouterを有効にしたテンプレートに、必要なコードを追加したものです。

main.ts
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import { VueWindow } from '@jswf/vue';

Vue.config.productionTip = false;

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

//---------------------
//Create Virtual Window
const win = new VueWindow(
  new Vue({router,render: h => h(App)})
);

win.setTitle('WindowTest');  //タイトル設定
win.setPos();               //位置を中心に揃える
//---------------------

3.まとめ

 JWF自体はウインドウ生成や子ウインドウの配置を主にしているフレームワークなので、クライアント領域に表示するコンテンツには干渉しない形になっています。そのためJWFに標準機能として付いているTreeViewやListViewは、かなり大きめのコードになっています。この状態で機能を追加しようと思ったら、自由はききますが、がっつりコードを書かなければなりません。今回はVue.jsを入れることによって、Vueのコンポーネントを簡単に持ってこられるようにしました。これでユーザからの入出力が頻繁に起こる部分の作成がかなり楽になると思います。

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

Vue.js & Django を Docker と組み合わせてSPA+APIサーバー環境をつくる

はじめに

今回は、Django REST Frameworkを使った、
Vue.jsをSPAとして運用できる環境の作り方をシェアできればと思います。

Docker Composeを使うので、本番で使うときはGKEなどの
モダンなコンテナ型オーケストレーションツールを選択可能かつ、開発でも
メンバーの増員などに柔軟に対応できる環境を作れたらと思います。

今回は抜粋で書いているので、
不足等ございましたら、ご連絡よろしくお願いいたします。

構成

構成は下記のような形にします。
本来だと下記に+DBもあるような構成が基本ですが、
コンテナ上で動かす場合と、クラウドのDBサービスを使用する場合など
多岐の選択があるため、今回はなしとします。

サーバー構成

サーバー名 名称 ポート番号
開発サーバー(Vue.js) front 8080
APIサーバー(Django) back 8001
Webサーバー(Nginx) web 8000

Docker Compose ファイルで骨組みを作る

最初にdocker-compose.ymlファイルと各種サーバーのDockerfileを作成して、
骨組みを形作っていきます。

1. docker-compose.ymlを作成

注意点としては、バックエンド側のstaticファイルをnginxに置いて
配信可能とする点です。
今回はAPIサーバーとしての使用のため、不要と思われますが、
djangoのデバッグ画面(管理画面など)を表示する際に使用できるので、
volumesにて、同期します。
基本的に起動は、拡張していくことも考えて、
Shellファイルに落とし込んでいきます。
(直で記載でも良いとは思います。)

docker-compose.yml
version: '3'

services:

  web:
    build:
      context: ./
      dockerfile: ./web/Dockerfile
    environment:
      TZ: 'Asia/Tokyo'
    ports:
      - 8000:8000
    volumes:
      - ./web/logs/nginx/:/var/log/nginx/
      - ./web/uwsgi_params:/etc/nginx/uwsgi_params
      - ./back/static:/var/www/static/
    depends_on:
      - back

  back:
    build:
      context: ./back
      dockerfile: Dockerfile
    command: 'sh /server/start.sh'
    expose:
      - "8001"
    volumes:
      - ./back:/server/

  front:
    build:
      context: ./front
    command: 'sh /app/start.sh'
    volumes:
      - ./front:/app/:cached
      - ./front/node_modules:/app/node_modules
    ports:
      - "8080:8080"

2. DockerFile フロントエンド側を作成

npmを使用するために、nodeイメージを入れます。
後ほど立ち上げるためにコメントアウトなども挟むので、
一旦スキップしても構いません。

Dockerfile(フロントエンド)
FROM node:10.7.0

WORKDIR /app
RUN npm install -g @vue/cli
ADD ./package.json /app/package.json
RUN npm install
ADD ./start.sh /app/start.sh

3. DockerFile バックエンド側を作成

バックエンド側をゴリゴリ書いていきます。
ライブラリのインストールも都度できるように
requirements.txt経由でインストールします。

Dockerfile(バックエンド)
FROM python:3.7
ENV PYTHONUNBUFFERED 1

WORKDIR /server
ADD . /server/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

4. DockerFile Webサーバー側を作成

設定ファイル、Vue.jsで作成しビルドしたものを格納します。
バージョンはお好みのものをご使用ください。

Dockerfile(Webサーバー)
FROM nginx:1.11.7

# 設定ファイル
ADD ./web/nginx.conf /etc/nginx/nginx.conf
ADD ./web/default.conf /etc/nginx/sites-available/default
ADD ./web/default.conf /etc/nginx/sites-enabled/default
ADD ./web/uwsgi_params /etc/nginx/uwsgi_params

RUN mkdir /var/www
RUN mkdir /var/www/front
RUN mkdir /var/www/static

ここまで作成するとある程度骨組み部分は出来上がった状態になります。
ここから、実際にサーバーとして使用できるように
各サーバー内に手を加えて初期構築をしていきます。

フロントエンド側を作成

Vue.jsを使えるようにVue CLIを導入して、
使用できる状態にしていきます。
エラーを防ぐために一旦Dockerfileで書いた下記をコメントアウトします

FROM node:10.7.0

WORKDIR /app
RUN npm install -g @vue/cli
# ADD ./package.json /app/package.json
# RUN npm install
# ADD ./start.sh /app/start.sh

Vue CLIを入れることで、Vueの開発環境を簡単に作成することができます。
早速Terminalからプロジェクトを作成し、開発サーバーとして立ち上げてみましょう。
各種設定方法を聞かれますが、enterで進んでいくとデフォルトのものがインストールされます。

ターミナル
// hoge-projectにはプロジェクト名を入力してください。
$ docker-compose run front vue create hoge-project

先ほどDockerfileに入力したコメントアウトを外して、
start.shを軽く記載した後、立ち上げてみましょう。
(プロジェクト先に向き先を当てるため、ファイルの向き先も変更するか、
 プロジェクトフォルダを移動して、動くか確認してみてください。)

start.sh
npm run serve
ターミナル
$ docker-compose build front
$ docker-compose up -d front

ローカルホストで確認すると無事立ち上がっているかと思います。

バックエンド側を作成

次にDjango側を作成していきます。
ターミナルからDjangoアプリの初期作成コマンドを打ちます。

ターミナル
$ docker-compose exec back django-admin startproject mysite

次にアプリケーションを作成します。
最後の確認の際に使います。

ターミナル
$ docker-compose exec back python mysite/manage.py startapp testapi

起動用のシェルも書いておきます。

start.sh
#!/bin/bash
sleep 5
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic --noinput
uwsgi --socket :8001 --module mysite.wsgi

Django REST Frameworkを使用するので
インストールする設定ファイルに記載します。

requirements.txt
django>=2.1.10
uwsgi==2.0.17.1
djangorestframework==3.8.2

一旦ここまでで、最後に疎通確認するので、
次に進みます。

Webサーバーを立てる

nginx.conf, default.conf, uwsgi_paramsなどの
設定ファイルを作成していきます。

1. nginx.conf

nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
daemon off;

events {
    worker_connections 65535;
    multi_accept on;
    use epoll;
}

http {

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    types_hash_max_size 2048;
    client_max_body_size 20M;
    keepalive_timeout     3600;
    proxy_connect_timeout 3600;
    proxy_send_timeout    3600;
    proxy_read_timeout    3600;
    send_timeout          3600;
    client_body_timeout   300;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format with_time '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $body_bytes_sent '
                         '"$http_referer" "$http_user_agent" $request_time';

    access_log /dev/stdout with_time;
    error_log stderr;

    gzip on;
    gzip_disable "msie6";

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s;
    limit_req_status 429;
}

2. default.conf

default.conf
# development
upstream webserver {
  ip_hash;
  server back:8001;
}

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {
  listen 8000;
  server_name 127.0.0.1;

  client_header_buffer_size 1k;
  large_client_header_buffers 8 32k;

  add_header Strict-Transport-Security 'max-age=31536000';
  add_header X-Frame-Options DENY;
  add_header X-XSS-Protection "1; mode=block";

  error_page 500 502 503 504 /50x.html;

  # フロントエンド
  location / {
    root /var/www/front;
    try_files $uri $uri/ /index.html;
  }

  # バックエンドサーバー 静的ファイル群
  location /static {
    alias /var/www/static;
  }

  # バックエンドサーバー
  location /back/ {
    include /etc/nginx/uwsgi_params;
    uwsgi_pass webserver;
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
    proxy_read_timeout 86400s;
    proxy_send_timeout 86400s;
  }

  # バックエンド adminサーバー
  location /admin/ {
    include /etc/nginx/uwsgi_params;
    uwsgi_pass webserver;
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
  }

  location = /50x.html {
    root /usr/share/nginx/html;
  }
}

3. uwsgi_params

uwsgi_params
uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

問題ないかテスト

試しにVue.js側でAxiosを導入して、
リクエストを送ってみて、きちんとAPIサーバーから値が帰ってくるか、
確認してみます。

1. Vue.js側のAxios通信の作成

試しにボタンからAPIサーバーへリクエストを送る処理を書いていきます。
戻り値を表示する部分も用意します。

ターミナル
$ docker-compose run front npm install -S axios

インストールしたAxiosをmain.jsにセッティングします。

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

Vue.config.productionTip = false
Vue.prototype.$axios = axios
new Vue({
  render: h => h(App),
}).$mount('#app')

初期作成されたHelloWorld.vueに追記していきます。

HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <!-- 下記記載 -->
    <h2>ここに結果が表示されます → {{ result }}</h2>
    <button @click="getAPI()">クリック!</button>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>

<!-- ~~~ 割愛 ~~~ -->
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  // 下記記載
  data () {
    return {
      result: 'No Result',
      url: 'http://localhost:8000/back/testapi/get/'
    }
  },
  methods: {
    getAPI () {
      this.$axios.get(this.url)
      .then(response => {
        this.result = response.data.message
      })
    }
  }
}
</script>

2. Django側のレスポンス処理の作成

URLConfへの記載、Views.pyにてレスポンス処理を書いていきます。
今回はhello worldを返すようにします。

root側のurls.py
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('back/testapi', include('testapi.urls', namespace='testapi')),
]
App側のurls.py
from django.urls import include, path
from .views import *

app_name = 'testapi'

urlpatterns = [
    path('get/', GetTestAPI.as_view()),
]
views.py
from django.shortcuts import render
from rest_framework import status, viewsets, filters
from rest_framework import permissions
from rest_framework.response import Response

class GetTestAPI(APIView):
    permission_classes = (permissions.AllowAny,)

    def get(self, request, format=None):
        return Response(data={'status': 'Hello World!'}, status=status.HTTP_200_OK)
settings.py
# ~~ 省略 ~~

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'testapi'
]

# ~~ 省略 ~~

3. 疎通

サーバーを立ち上げてブラウザ上から確認してみます。

$ docker-compose up -d

まとめ

現在SPA+APIサーバー環境をDocker上で構築することで、
短い時間で、簡単に構築することができます。

現在弊社では、HRモンスターと呼ばれる
採用の新しいスタイルを提供するサービスをローンチいたしました。

ローンチ後のさらなる機能追加、改善などのPDCAサイクルを回すべく、
エンジニアを募集しております。
https://www.wantedly.com/projects/341182

Kubernetes、Vue.js(Javascript)、Django(Python)といったモダンな技術を使って、
開発しておりますので、もしご興味がある方はぜひ、ご応募お待ちしております。

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

【Vue初心者向け】Vue.jsのシンプルなTwitterのシェアボタンの実装

Vue.jsで実装する、Twitterのシェアボタンのサンプルコードです。
シェアボタンの実装方法はいくつかありますが、その中でも単純な実装方法です。

シェアボタンだけの実装なので、初心者の方でもわかりやすいと思います。

実際の動作はこちらで確認できます。

シンプルなTwitterのシェアボタン

サンプルコード

<template>
    <div class="twitter_share">
        <button @click="twitterShare">ツイッターでシェアする</button>
    </div>
</template>

<script>
export default {
    methods:{
        twitterShare(){
           //シェアする画面を設定
            var shareURL = 'https://twitter.com/intent/tweet?text=' + "ツイッターシェアボタンのサンプルコード" + "%20%23あめねこサンプルコード集" + '&url=' + "https://code.ameneko.com/twitter-share";  
           //シェア用の画面へ移行
            location.href = shareURL
        }
    }
}
</script>

<style scoped>
.twitter_share{
    max-width: 1000px;
    margin: auto;
}
</style>

ポイント

ポイントは、ツイッターでシェアする方法を把握することです。
twitterにシェアする場合、「https://twitter.com/intent/tweet 」でシェアするページにいけます。コメントを載せるときは「?text=」の後にコメントを書きます。ハッシュタグをつける時は「%20%23」の後にコメントを書きます。URLをつける時は「&url=」の後にURLを書きます。
「shareURL」でシェアする用のデータを設定したら、次にリンクに飛ぶようにします。そこで、「location.href」でシェア用画面に遷移します。

参考:
twitterのツイートボタンを作るためのリンクshareとintent/tweet

宣伝:ブログ書いてます!→ブログ

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