- 投稿日:2020-10-25T22:03:02+09:00
Vue.jsとDjangoでWebアプリケーションを作ってみる (Mac編) - (1) 環境構築、アプリケーション作成
はじめに
サーバーサイドをPythonのDjango、クライアントサイトをVue.jsで組んでみます。
Djangoアプリケーションは、cookiecutterで作成します。
環境構築
Python
pyenvインストール
- Mac : ローカルPCにPython環境をインストールする(pyenv, venv on Mac)
- WSL : すみません、まだ作成していません。作成したらリンクを貼ります。
Python3.9.0インストール
pyenv versionsでインストール済みのバージョン一覧を表示し、
3.9.0
がない場合はインストールします。pyenv install 3.9.0
cookiecutter実行用仮想環境作成
pyenv shell 3.9.0 python -m venv ~/.venv/3.9.0/cookiecutter-3.9 pyenv shell --unset # pyenvのshellを終了する。Djangoアプリケーション実行用仮想環境作成
pyenv shell 3.9.0 python -m venv ~/.venv/3.9.0/django-sample-3.9 pyenv shell --unset # pyenvのshellを終了する。nodenv
nodenvインストール
node.js 13.11.0インストール
nodenv versionsでインストール済みのバージョン一覧を表示し、
13.11.0
がない場合はインストールします。nodenv install 13.11.0
バージョン確認
nodenv versionscookiecutterアプリケーション作成、実行
cookiecutterの環境を作成
mkdir cookiecutter cd cookiecutter/ source ~/.venv/3.9.0/cookiecutter-3.9/bin/activate pip install --upgrade pip pip install cookiecuttercookiecutter実行
cookiecutter https://github.com/pydanny/cookiecutter-django対話式で色々聞かれるので、答えながら先へ進みます。
【注意】
Select cloud_provider
で「3」(None)を選択し、use_whitenoise
で「n」とすると、下記のようなエラーになるので、Select cloud_provider
で「1」か「2」を選択するか、あるいは、use_whitenoise
で「y」と答えます。You should either use Whitenoise or select a Cloud Provider to serve static files ERROR: Stopping generation because pre_gen_project hook script didn't exit successfully Hook script failed (exit status: 1)project_name [My Awesome Project]: django-sample project_slug [django_sample]: app description [Behold My Awesome Project!]: Django Sample Application author_name [Daniel Roy Greenfeld]: ***** domain_name [example.com]: email [daniel-roy-greenfeld@example.com]: *****@*****.*** version [0.1.0]: Select open_source_license: 1 - MIT 2 - BSD 3 - GPLv3 4 - Apache Software License 2.0 5 - Not open source Choose from 1, 2, 3, 4, 5 [1]: 5 timezone [UTC]: Asia/Tokyo windows [n]: use_pycharm [n]: use_docker [n]: Select postgresql_version: 1 - 12.3 2 - 11.8 3 - 10.8 4 - 9.6 5 - 9.5 Choose from 1, 2, 3, 4, 5 [1]: Select js_task_runner: 1 - None 2 - Gulp Choose from 1, 2 [1]: Select cloud_provider: 1 - AWS 2 - GCP 3 - None Choose from 1, 2, 3 [1]: 3 Select mail_service: 1 - Mailgun 2 - Amazon SES 3 - Mailjet 4 - Mandrill 5 - Postmark 6 - Sendgrid 7 - SendinBlue 8 - SparkPost 9 - Other SMTP Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]: 9 use_async [n]: use_drf [n]: custom_bootstrap_compilation [n]: use_compressor [n]: use_celery [n]: use_mailhog [n]: use_sentry [n]: use_whitenoise [n]: y use_heroku [n]: Select ci_tool: 1 - None 2 - Travis 3 - Gitlab 4 - Github Choose from 1, 2, 3, 4 [1]: keep_local_envs_in_vcs [y]: debug [n]: [INFO]: .env(s) are only utilized when Docker Compose and/or Heroku support is enabled so keeping them does not make sense given your current setup. [WARNING]: You chose not to use a cloud provider, media files won't be served in production. [SUCCESS]: Project initialized, keep up the good work!
質問 デフォルト 設定 備考 project_name My Awesome Project django-sample project_slug django_sample app description Behold My Awesome Project! Django Sample Application そのままでも問題ないです author_name Daniel Roy Greenfeld ***** 自分の名前を入れます domain_name example.com (デフォルト) 後から変えることになると思いますが、 とりあえずそのままで大丈夫です daniel-roy-greenfeld@example.com 自分のメールアドレスを入れます ~ version 0.1.0 (デフォルト) Select open_source_license
1 - MIT
2 - BSD
3 - GPLv3
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 51 5 オープンソースにする場合はライセンスを選択します timezone UTC Asia/Tokyo windows n (デフォルト) use_pycharm n (デフォルト) PyCharmを使う場合はyにしてもいいと思います use_docker n (デフォルト) Select postgresql_version:
1 - 12.3
2 - 11.8
3 - 10.8
4 - 9.6
5 - 9.5
Choose from 1, 2, 3, 4, 51 (デフォルト) 私の場合、MySQLやMariaDBを使う事が多いので、後で変更することになるため、ここでは適当にデフォルトで先へ進めます Select js_task_runner:
1 - None
2 - Gulp
Choose from 1, 21 (デフォルト) Select cloud_provider:
1 - AWS
2 - GCP
3 - None
Choose from 1, 2, 31 3 クラウドプロバイダが決まっていないので3にします。すでに決まっている場合は1〜2でも大丈夫だと思います。 Select mail_service:
1 - Mailgun
2 - Amazon SES
3 - Mailjet
4 - Mandrill
5 - Postmark
6 - Sendgrid
7 - SendinBlue
8 - SparkPost
9 - Other SMTP
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 91 9 メール送信のサービスで使うものが決まっている場合は選択します。 use_async n (デフォルト) use_drf n (デフォルト) custom_bootstrap_compilation n (デフォルト) use_compressor n (デフォルト) use_celery n (デフォルト) use_mailhog n (デフォルト) use_sentry n (デフォルト) use_whitenoise n y クラウドプロバイダでNoneを指定した場合、ここでyを選ぶ必要があるようです use_heroku n (デフォルト) Select ci_tool:
1 - None
2 - Travis
3 - Gitlab
4 - Github
Choose from 1, 2, 3, 41 (デフォルト) keep_local_envs_in_vcs y (デフォルト) debug n (デフォルト) cookiecutterの実行が完了すると、
project_slug
で回答したスラグ名のディレクトリが作成されます。
そのディレクトリを、ホームディレクトリ直下にdjango-sample
として移動します。/bin/cp -Ra app ~/django-sample
Vue.jsアプリケーション作成
mkdir ~/vue-sample/ cd ~/vue-sample/ nodenv local 13.11.0 node -v # nodeのバージョンがv13.11.0であることを確認 npm init --yes npm install npm # npmを最新化 npm install @vue/cli npm install @vue/cli-init次に、Pathを通すため、以下を実行します。
npm binMacの場合、
/Users/*****/vue-sample/node_modules/.binのように表示されるので、そのパスをPATHに追加します。
export PATH="/Users/*****/vue-sample/node_modules/.bin:$PATH"プロジェクトを作成します。
vue init webpack vue-sample? Project name vue-sample ? Project description A Vue.js project ? Author ? Vue build standalone ? Install vue-router? No ? Use ESLint to lint your code? No ? Set up unit tests No ? Setup e2e tests with Nightwatch? No ? Should we run `npm install` for you after the project has been created? (recommended) npmアプリケーションの作成に成功すると、
# Project initialization finished! # ======================== To get started: cd vue-sample npm run devのように表示されるので、以下のコマンドを実行し、アプリケーションを実行します。
cd vue-sample npm run dev
Your application is running here: http://localhost:8080と表示されるので、http://localhost:8080へアクセスします。
- 投稿日:2020-10-25T20:15:49+09:00
Vue3の基本構文③
Vueの構文についてコードベースで簡単にまとめます。
ちなみにシリーズ最終回です。
基本構文①
基本構文②今回は以下の2つです。
- コンポーネントとProps
- コミュニケーティングevent
コンポーネントとProps
コンポーネントとは構成要素を意味し、再利用可能なVueインスタンス要素のことです。
Webページ構成する様々な要素、例えばヘッダーやサイドバーなどを分割し、コンポーネント化することで、設計・開発・テストがコンポーネント単位で行えるようになったりというメリットがあります。
そして、コンポーネントには親コンポーネントと子コンポーネントがあり、親コンポーネントから子コンポーネントに値を渡す際に使用されるのがpropsです。main.jsconst app = Vue.createApp({}) app.component('programming', { props: ['title'], template: `<h4>{{ title }}</h4>` }) app.mount('#component-demo') }Vueコンポーネントを作成し、その中でprops(
title
)をVueインスタンスのdata
の様に定義します。上のコードから分かる様に、テンプレートからprops
で定義した値にアクセスすることができます。index.html<div id="component-demo" class="demo"> <programming title="Angular"></programming> <programming title="React"></programming> <programming title="Vue"></programming> </div>コンポーネント側で
props
が登録されたので、引数としてdata(title
)をコンポーネントに送ることができます。実践的な使われ方
main.jsconst App = { data() { return { languages: [ { id: 1, title: 'Angular' }, { id: 2, title: 'React' }, { id: 3, title: 'Vue' } ] } } } const app = Vue.createApp(App) app.component('programming', { props: ['title'], template: `<h4>{{ title }}</h4>` }) app.mount('#component-demo')index.html<div id="component-demo"> <programming v-for="language in languages" :key="language.id" :title="language.title" ></programming> </div>上記のようにVueインスタンスの
data
の中で配列で定義し、htmlでv-for
を使いレンダリングする方法が実際のアプリケーションでよく見られます。また、v-bind
を使用することでprops
をダイナミックに渡すことができます。コミュニケーティングevent
コミュニケーションは親コンポーネント->子コンポーネントだけではなく、子->親でもできます。
試しに子コンポーネントのボタンクリックから親にあるメソッドを走らせて、color
プロパティーを変更します。main.jsconst App = { data() { return { languages: [ { id: 1, title: 'Angular' }, { id: 2, title: 'React' }, { id: 3, title: 'Vue' } ], languageColor: "black" } } }Vueインスタンスの
data
にlanguageColor
プロパティーを追加。index.html<div :style="{ color: languageColor }"> <programming v-for="language in languages" :key="language.id" :title="language.title" > </programming> </div>htmlでスタイルの
color
を追加main.jsapp.component('programming', { props: ['title'], template: ` <h4>{{ title }}</h4> <button> 赤色に変更 </button> ` })テンプレートにボタンを追加。現状はまだボタンが機能しない。
index.html<programming v-for="language in languages" :key="language.id" :title="language.title" @change-color="languageColor = 'red'" > </programming> </div>html側で
v-on
もしくは@
を使うことで子コンポーネントのイベントをリッスンすることができます。@
を使用してchange-color
メソッドの実装する。main.js<button @click="$emit('change-color')"> 赤色に変更 </button>子コンポーネントから親にイベントを発行してくれる
$emit
を使います。すると、親であるhtmlでイベントを受け取りリスナーのchange-color
メソッドを実行し、以下の様にtitle
が赤くなりました。おわりに
シリーズ三回に分けてVue3の基本構文を紹介してきました。Vue2とほとんど変わらないものばかり紹介してきましたが、これからもVue3を勉強してアウトプットしていきたいと思います。
- 投稿日:2020-10-25T17:18:32+09:00
Vueでtransition-groupの再利用とscoped CSSを組み合わせるにはdeepする必要がある
こんにちは、猫チーズです。
Vue公式ドキュメント「Enter/Leave とトランジション一覧 - Vue.js」の「トランジションの再利用」を参考にしながら、transition-groupを再利用するコンポーネントを作っていたら、リスト移動トランジションが適用されなくてハマりました。
海外系の質問サイトを漁ってもそもそも同様の問題にぶつかってる人が見当たらなかったので、transition-groupの再利用とscoped CSSを組み合わせること自体レアケースなんでしょうか。
何時間か試行錯誤した結果、タイトルの通り原因が分かったのでここに記しておきます。動作環境:Vue 2.6.12
問題のコード
問題の部分を簡潔に切り出すと以下のような単一ファイルコンポーネントです。
<template> <transition-group> <slot></slot> </transition-group> </template> <script> // 略 </script> <style lang='scss' scoped> .v-move { transition: transform 400ms; } </style>slotの部分には、呼び出し側でv-forを使って要素たちを並べます。
その要素たちの順番が入れ替わった時には、入れ替わりのトランジションが自動で付く想定です。
ところがこのコードだと、どうしてもトランジションされませんでした。解決法を探る
❶ slotの代わりに適当な要素を配置して、動的に順番入れ替えしてみる。
→ トランジションされた。単一ファイルコンポーネントだからうまくいかない、という訳ではない。原因はslot周りにある。❷ 一つのslotに複数要素を読み込ませるのではなくて、要素数分だけslotを動的に用意して、それらをtransition-groupで囲ってみる。
→ トランジションされない。templateの段階でtransition-groupの子要素が複数あればいい、という訳ではない。❸ templateの代わりにrenderオプションを使い、slotの中身を要素ごとにバラし、それぞれの要素を新しいdivで囲ってtransition-groupの子要素として配置する。
→ トランジションされた。このコンポーネント内で生成された要素がtransition-groupの子要素なら、トランジションされる?❹ ふと、CSSをカプセル化するためのカスタム属性(data-v-abcd1234みたいなもの)によってtransition-groupの子要素を選別してしまってるのでは?と思い、cssからscopedを除いてみる。
→ トランジションされた。これが原因ぽい。❺ このコンポーネントに割り当てられたカスタム属性を手動でコピーして、呼び出し元のslotへ読み込む要素たちに手動でカスタム属性を貼り付けてみる。
→ トランジションされた。やっぱりScoped CSS用のカスタム属性がtransition-groupの子要素たちにもつけられていないと、トランジションが適用されない。❻ scopedを取り除く代わりに、トランジション指定用のCSSのセレクタ
.v-move
に/deep/を付ける。
→ トランジションされた。カスタム属性がマッチしてようがマッチしてなかろうが、トランジション中にはtransition-groupの子要素に.v-move
クラスが付けられるらしい。トランジションが適用されてなかったのは、scopedしてるが故にCSSのセレクタ側で暗黙的にカスタム属性.v-move[data-v-abcd1234]
によって選別してしまっていたからだった。ということで解決法
コンポーネントのCSSをscopedで安全にカプセル化しつつ、問題の箇所だけ限定的にカプセル化を解くと、下のようなコードになった。
<template> <transition-group class='items'> <slot></slot> </transition-group> </template> <script> // 略 </script> <style lang='scss' scoped> .items > /deep/ .v-move { transition: transform 400ms; } </style>変更したのは2箇所。
1. transition-groupにクラス名を付ける。
2..v-move
に/deep/を付けてカプセル化を解きつつ、完全に解いてしまうと影響範囲が広いので、.items >
によってtransition-groupの子要素のみに縛っている。私が実際に作っているコンポーネントはもう少し複雑なので、影響範囲が最小限となるようにこのようにdeepや子要素縛りなどをしているけど、もっと緩めの環境の人は単にscopedを取るだけでもいいかも。
- 投稿日:2020-10-25T15:53:50+09:00
脳死でアップデートは危険!Vue3.0の破壊的変更点を要チェック!!
はじめに
Vue3.0がリリースされましたが、Vue2系からアップデートしましたか?
実は破壊的な変更点があり、脳死でアップデートすると危険です。
今回は破壊的変更点の中で特に影響が大きそうな部分を抽出して解説します!!動画でも解説してるので、動画が好きな方はそちらを確認してみてください!!
【YouTube動画】 Vue3.0の破壊的変更点
Global API
実際のコードの変更をみていきましょう!
以前は以下のように使っていた部分がimport Vue from 'vue' import App from './App.vue' Vue.use(/* ... */) Vue.mixin(/* ... */) Vue.component(/* ... */) Vue.directive(/* ... */) new Vue({ render: h => h(App) }).$mount('#app')こうなります!
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.use(/* ... */) app.mixin(/* ... */) app.component(/* ... */) app.directive(/* ... */) app.mount(App, '#app')createAppでインスタンスを作成した後に、Vueの設定を追加していきます。
Vue.xxxxと書いていた部分は修正しないといけませんね。Global API Tree Shaking
Tree Shakingは使われないコードを除去する仕組みです。
webpackではサポートされてますね。以前のバージョンでは使わないメソッドもバンドルされていましたが、新しいバージョンでは明示的に書かないとバンドルされないようになりました。
これのおかげで、ファイルサイズがより小さくなります!影響を受けるのは以下のAPIなので、使ってる方は修正が必要です。
Vue.nextTick Vue.observable Vue.version Vue.compile Vue.set Vue.delete修正するときはimportで使うAPIを指定します。
// Before import Vue from 'vue' Vue.nextTick(() => { // something DOM-related }) // After import { nextTick } from 'vue' nextTick(() => { // something DOM-related })v-model
v-modelの書き方も変わりました。
例えば、以下のように書いていた場合<Comp :value='pageTitle' @input='pageTitle=$event'/>このように変更する必要があります。
<Comp :modelValue='pageTitle' @update:modelValue='pageTitle=$event'/>Functional Component
Functional Componentを使っていた方は書き方が簡単になりました。
以下のようにhをインポートして使います。import { h } from 'vue'まとめ
いかがでしたか?
間違ってる部分やもっと解説して欲しい部分があれば、コメントいただけると嬉しいです!
- 投稿日:2020-10-25T15:33:45+09:00
【Vue.js】動的なデータの反映まとめ
Vue.jsの十八番である
リアクティブなデータの反映
の種類をまとめてみました
ディレクティブ等 紐付け先 どうしたいか 実例 v-model data 入力内容や選択内容を動的にしたい input(type="text", v-model="todo.message") v-bind data htmlタグの属性を動的にしたい img(:src="todo.image) {{ }} data 表示させる文字を動的にしたい p{{ todo.message }} {{ }} computed dataの値を変化させたものを動的にしたい p{{ remaining }} v-model
<template> <input type="text" v-model="todo.title"> </template> <script> let vm = new Vue({ el: '#app', data: { todo: { { title: '' }, } }, }) </script>v-bind
<template> <img :src="todo.image"> </template> <script> let vm = new Vue({ el: '#app', data: { newItem: '', todo: { { title: 'task1', image: "" }, } }, }) </script>{{ }}
dataオプションと連動
<template> <span>{{ todos[0].title }}</span> </template> <script> let vm = new Vue({ el: '#app', data: { todo: { { title: 'task1', isDone: false }, } }, }) </script>computedオプションと連動
<template> <span>{{ remaining }}</span> </template> <script> let vm = new Vue({ el: '#app', data: { todos: [ { title: 'task1', isDone: true }, { title: 'task2', isDone: false }, { title: 'task3', isDone: false }, ] }, computed: { remaining: function(){ let remainItems = this.todos.filter(function(todo){ return !todo.isDone; }); return remainItems.length; } } }) </script>
- 投稿日:2020-10-25T13:39:21+09:00
Require self-closing on Vue.js custom components (<〇〇>).の解決方法
ESLintを導入後にRequire self-closing on Vue.js custom componentsという警告が出たので解決方法を記載しておきます。
app.vue<template> <v-app id="app"> <Header></Header> <Todolist></Todolist> </v-app> </template>上記のコードで以下のような警告出ました。
警告Require self-closing on Vue.js custom components (<Header>). Require self-closing on Vue.js custom components (<Todolist>).原因は開始タグと終了タグの間に何も記載がないのが理由ですが、
今回はタグの間に何も書く必要が無いので別の解決方法を使います。app.vue<template> <v-app id="app"> <Header /> <Todolist /> </v-app> </template>このように自己終了タグを使うと警告が出なくなります。