【Vue.js】.vueファイルの書き方
はじめに
この記事ではVue.jsやNuxt.jsで使用する.vueファイルの書き方について書いていきます!
Vue.jsを初めて勉強する際は、HTMLファイルにscriptタグで一行追加するだけで利用できるCDN版で書いてみる人が多いと思います。
しかし、プロジェクト方式で開発となるとページの内容を記述する際にはHTMLファイルではなく、.vueファイルを利用していきます。
その際に、HTMLファイルから.vueファイルでの記述の違いで躓かないよう、この記事が少しでも参考になったら幸いです。
.vueファイルとは
.vueファイルはVue.jsのコンポーネントを定義しているファイルです。HTMLファイルに実装する方式ではコンポーネントはVue.componentを使って作成しますが、プロジェクト方式ではこの.vueファイルでコンポーネントを定義します。この.vueファイルという一つのファイルにまとめたコンポーネントを単一ファイルコンポーネントと言います。
.vueファイルでは、HTML、JavaScript、CSSを1ファイルにまとめて書けることが利点として挙げられます。
まとめて書くことで管理がしやすく、大規模なアプリケーションを作る際に大きな恩恵が受けられます。
.vueファイルの構造
.vueファイルは主に <template>タグ、<script>タグ、<style>タグの3つの部分に分けられています。
<template> <div> <div class="example">{{ msg }}</div> <App/> </div> </template> <script> import App from './App.vue' export default { data () { return { msg: 'Hello world!' } }, components:{ App } } </script> <style> .example { color: red; } </style>
<template>タグ
<template> <div> <div class="example">{{ msg }}</div> <App/> </div> </template>
一番最初にある<template>タグの中は、HTMLで記述します。
この<template>タグの中に記述した内容が実際の画面に表示されます。
<script>タグ
<script> import App from './App.vue' export default { data () { return { msg: 'Hello world!' } }, components:{ App } } </script>
scriptタグではHTMLファイルで実装するときと同じように、JavaScriptで処理を記述します。 しかし、見たことがないのが、export default{ }の部分です。このexport default{ }で囲むと書いた中身が外部のファイルからも呼び出せるようになります。 .vueファイルは外部からも呼び出せることが前提の仕組みのため、export default{}が必要なわけです。とりあえず最初はexprot default{}を脳死で書いておきましょう!
そして、もう一つあまり見かけないのが import ~~ from ~~の部分です。
import 好きなコンポーネント名 from 'コンポーネントとして利用したい.vueファイルのパス'
上記のように記述することで他の.vueファイルを読み込んで、コンポーネントとしてそのまま使用することができます!
なお、他のvueファイルを読み込む必要がないのならば、この一文は必要ありません。
<style>タグ
<style> .example { color: red; } </style>
最後はHTMLファイルの時とほとんど変わりありません。
CSSで記述してページを装飾することができます!
また、<style scoped>
という風にscoped属性を付けると、この.vueファイル内のみにスタイルの設定を適用することができます。
参考
npm yarn Gitのproxy(プロキシ)設定・解除方法
はじめに
この記事は、npm・yarn・Gitの3つのプロキシ設定によく引っかかるので、書き留めておこうと思う。
設定・解除・確認のカテゴリで書いていく。
各バージョン
本稿は以下のバージョンで実行している。
$ npm --version 7.11.2 $ yarn --version 1.22.10 $ git --version git version 2.30.0
proxyの設定・解除・確認
本稿はすべてID & Pass なしで記述する。
*以下、プロキシサーバーをhttp://wwwproxyserver:port
又はhttps://wwwproxyserver:port
と記述する
proxyの設定
// npm $ npm -g config set proxy http://wwwproxyserver:port $ npm -g config set https-proxy https://wwwproxyserver:port // yarn $ yarn config set proxy http://wwwproxyserver:port $ yarn config set https-proxy https://wwwproxyserver:port // git $ git config --global http.proxy http://wwwproxyserver:port $ git config --global https.proxy https://wwwproxyserver:port
proxyの解除
// npm $ npm -g config delete proxy $ npm -g config delete https-proxy // yarn $ yarn config delete proxy $ yarn config delete https-proxy // git $ git config --global --unset http.proxy $ git config --global --unset https.proxy
proxyの確認
実行結果を確認するには、以下のコマンドを実行しましょう。
// npm $ npm config list // yarn $ yarn config list // git $ git config --global --list
なぜ我々はコロナに打ち勝てたのか?
はじめに
このブログは ”活動紹介” と ”技術発信” のために作ったものです。
しかし、今回は毛色を変えて Tourism Project がなぜ生まれ、
どうしてコロナ禍を耐え忍んだかという記録をここに残そうと思います。
そのため、今回は 大学などのプロジェクトに関わる人、オンラインプロジェクトを存続させたい人 に向けた内容になることをご容赦いただきたいです。
プロジェクトの遍歴
ここからは、我々のプロジェクトが出来てから今まで、何があったのかを書きます。
※ 結論だけ知りたい場合は読み飛ばしてもらって構いません
2020年1月 誕生
我々は、我々のボスである袖准教授に呼び出され、ホワイトボードの前にいました。
Tourism Project(当時はTravel with us)は、この時に出来たというわけではなく、この一年前には存在していました。
だが、元のメンバーの多くが就職や進学ということで、新たなメンバー体制で心機一転やっていくことになりました。この時のメンバーは全員が全員ほぼ初対面でした。
2020年2月 引き継ぎ
この月は以前のプロジェクトの引き継ぎ作業を行っていました。
以前は、海外からの観光客に向けたWebアプリケーションの作成をしており、これに用いている技術についての勉強や、このサイトの運用方法などを引き継いでいました。
この時にSlackを導入し、チーム内での情報共有を円滑にしました。
2020年3月 心機一転
この時期からボスからの提案で、今までのプロジェクトの内容を終了して新しいプロジェクト内容に変更してみないか、という提案がなされました。
うまくいけば法人化もしてもいいとのことなので、張り切って新しいプロジェクトのアイデアだしを行いまいした。
2020年4月 オンライン
ここで、件の感染症が猛威を振るい始め、集まってプロジェクトを行えなくなりました。
我が校で開催された、情報処理学会第82回全国大会がZoomでの開催になったのを参考に、我々もオンラインでプロジェクトを始めることにしました。
当時のチームリーダーである 中山さん の提案で毎週2回決まった時間にミーティングをすることになりました。
2020年5月〜8月 苦悩の日々
この頃、週2回のミーティングの議題は「プロジェクトで今後何をするか」を決めることでした。
しかし、これを決めるのにかなり揉めたり、振り出しに戻ったりと、もともと1時間を想定していたミーティングも、時には3時間を超える日も出てきてしまいました。
最終的には、「チームメンバーがアニメ好きである」「地元の観光地を発信したい」などという思いから「湯涌で聖地巡礼アプリを作りたい」という意見で決まりました。
2020年9月〜2021年2月 アプリ開発
今年度中に、湯涌温泉観光協会様へアイデアを見せて、最終的にイベントを開催したいという目標が決りました。
そのために、必要なアプリやWebサイトなどを設計して、実装に移りました。
この頃のミーティングは、進捗報告が主な内容だったため、週一回に減っており、
日によっては、5分程度でミーティングが終わる日もありました。
ミーティングのほかに時間を作って ”朝活” と称してZoomに集まって開発をする会や、 ”もくもく会” という作業通話を行ったりしました。
2021年3月 プレゼンと卒業
実際にiOSアプリのモックが完成しました。
プレゼン資料とできたアプリを携えて、湯涌温泉観光協会様へプレゼンをしまして、結果、高評価でした。
もちろん、細部には問題のある箇所はあったが、面白いと言ってもらえました。
この月に前リーダーであった 中山さん が卒業し、Fくん に新たなリーダーに着任ししました。
2021年4月〜2021年9月(現在)
新たな体制になって最初に行ったのは、記録を取れるようにしたことでした。
今までは、口頭での進捗報告だった。しかし、これでは進捗の管理が困難であり、大学側などにプロジェクトをしっかり行なっていたことを示す事ができません。
そこで、進捗報告システムを作りこれを定期ミーティング前に行うことで、話の流れがスムーズになったり、しっかり進捗のログを取れるなど多くのメリットがありました。
また、これまでSwift(プログラミング言語)での開発を行ってきたのですが、これよりもFlutter(iOS, Android双方とも開発できるライブラリ)を用いた方がいいという話になり、こちらを用いた開発に移行しました。
そして現在も、湯涌温泉観光協会様と話し合いながらイベント開催を目標に活動を行っていました。
全リーダー 中山さん への取材からわかったこと
今回、全リーダー 中山さん への取材で分かったことをまとめてみました。
休憩や雑談などを意識して入れる
中山さんによると、Zoomでは常に誰かが喋っていたり、プロジェクトに関係のある話を話しがちなので、対面に比べ疲れてしまいます。
そこで会議の進行をする場合は、議題の合間などに雑談を挟んだり、長時間になる場合は休憩を挟んでいたそうです。
また、その雑談を通してチーム内の仲が良くなるような効果も狙っていたといいます。
他にも、「会議は必要な人のみで短時間で行う事」「定期ミーティングであっても議題がなければすぐに終わらせる」なども気をつけていたそうです。
プロジェクト内部活を作った
オンラインで、普段よりチームの文化が築きにくいです。
そこで中山さんは、Slack内のチャンネルで「アルゴリズムとデータ構造」という、競技プログラミングについて話すチャンネルを作りました。
チームの仲を良くするために作ったといいます。
後になって考えると、これが「好きなものを教え合う」「技術や情報を共有する」というチーム文化につながったと筆者は考えます。
ちなみに、中山さんがこのような考えは、以下の本を読んだのがきっかけだそうです。
リーダーの引き継ぎはみんなに相談した
中山さんが卒業する際に、次のリーダーを選ぶ必要がありました。
リーダーを選ぶにあたって、その人選が原因で蟠りができないように、チーム全員と1人づつ話し合って、決めたといいます。
そして、現在でもその決定によってスムーズなプロジェクト運営ができていると筆者は考えます。
みんなが技術やプロジェクトに興味ややる気があった
みんなの技術に対するモチベーションが高く、情報の共有などができたこと。
全員が同じ目標を持ってプロジェクトを進めていたこと。
これらの理由で、プロジェクトが纏まっていたと中山さんは考えていたようです。
コロナに打ち勝った理由
筆者の考えるコロナに打ち勝った理由を簡単にまとめると以下の通りです。
- オンライン環境づくり
- チーム文化づくり
- みんなの協力
1. オンライン環境づくり
オンラインでプロジェクトを運用するためには、環境づくりが必須です。
SlackやZoomなどのコミュニケーションツールを用いることが大前提となる。
その上で議題がなかったとしても、定期的なミーティングを行う事で、それが習慣化し、存続し続けるプロジェクトになります。(ただし、議題が無い場合はすぐに終わっても良いです)
また、Google フォームを用いた進捗管理システムや、特定の日時になると定期ミーティングのURLが発行・通知される機能を作り、システム面から参加率を上げるように努力しました。
2. チーム文化づくり
ただ、ミーティングを行うだけではチームの結束は弱いです。
そこで、チームに愛着を持ってもらえるようなチーム文化が必要です。
この部分は一般化できる話では無いかもしれないですが、Slackにプロジェクトに必要なチャンネル以外にも、娯楽や勉強会などのチャンネルを増やすことで、Slackが活発化して、自然と和気藹々として雰囲気を作れるのではないかと考えます。
3. みんなの協力
これが最も大切だと感じるのですが、ひとりが努力してもプロジェクトは成功もしなければ存続もしません。
ゆえに、全員がやる気を持ってプロジェクトに参加する必要があるります。
ただ、環境面が整っていない状況では、どうしたってやる気は出ないので、この部分の改善は、問題意識を持った誰かが率先して行う方がいいのではないかと考えています。
終わりに
大学のプロジェクト運営は大変難しいことです、
これは中山さんの言葉ですが
プロジェクトには強制力がなく、学生は自由、やるかやらないかは勝手
とのことです。
しかし、実際プロジェクトを運営するためには、学生の興味を引き出し、やる気を持たせ、プロジェクトに参加してもらう必要があります。
故に、会社でのプロジェクト運営と別の難しさがあります。
しかし、プロジェクトが成功した時の達成感は素晴らしいものなので、ぜひこの記事を参考にみなさんも大学のプロジェクトを存続させ成功させて欲しいです!
ここまで読んで下さり、ありがとうございます。
みなさんも良い、プロジェクトライフを!
初心者が使うMarkdown記法のメモ
こんにちは
今回はMarkdownで記事を書くことになったので、メモ程度に使うものなどを残していきたいと思います。
見出し
「#」を使うことで、見出しを設定することができます。「#」の数が増えるほど見出しの大きさは小さくなっていきます。
使用例
#hoge ##hoge ###hoge ####hoge
表示例
hoge
hoge
hoge
hoge
段落
段落は空行を文章の途中に入れるとできます。
我々TourismProjectは金沢工業大学にある プロジェクトの1つです
表示例
我々TourismProjectは金沢工業大学にある
プロジェクトの一つです
改行
改行は半角スペースを2つ入力し改行を行うことによりブラウザなどでの改行表示がされできます。
最近週1ペースでのブログ更新を はじめました
表示例
最近週1ペースでのブログ更新を
行っています。ぜひ見てください。
リスト
- リストは
- 「-」をつけることで実装できます。
- ちなみに半角スペースを4つつけるとこの様になります。
Todoリスト - プログラムの修正 - ブログを書く
表示例
Todoリスト
- プログラムの修正
- ブログを書く
番号リスト
- 番号リストは
- 1を文章の前につけることでできます。
- 4つの半角スペースを開けることでこの様になります。
- イエーイ
メンバーリスト 1. 吉田 1. 山本 1. 山岡 1. 杉本
表示例
メンバーリスト
- 吉田
- 山本
- 山岡
- 杉本
リンク
リンクは[]に青文字を、()にリンクを貼ることで出来ます。
使用例 [はてなブログ](https://hatenablog.com/)
表示例
引用
引用しました。「>」をつけることで引用ができる。
使用例 >すごい本
表示例
すごい本
脚注
この様に脚注します。1
使用例 日本で一番高い山は富士山である。[^1] [^1]: ソースはwiki
表示例
日本で一番高い山は富士山である。2
打消
打消は本音のように~~を消したい文章の所に前後に入れるとできる。
~~言わなくてもいいこと~~
表示例
言わなくてもいいこと
Tourism Projectの活動概要
Torism Projectの活動概要
はじめまして。Tourism Projectの広報兼研究員Tです。今回は僕がこのプロジェクトの活動内容や雰囲気などをざっくりとお伝えしていきます。
Tourism Projectのはじまり
Tourism Projectはもともと、2年前にコロナ禍で何か自分たちで世の中を盛り上げるためにできることをしようってことで立ち上がったプロジェクトです。最初に何をするか決めるときに、レビュワー同士でおすすめの場所を紹介することで地域のお店のクーポンなどをもらう「わらしべ観光システム」、VRを使って擬似的に旅行をする「VR旅行」、旅行計画などを自動で行うアルゴリズムの開発だったり、より地域の良さを地域のお店や住人に寄り添った形で紹介する聖地巡礼アプリなどの案が出ました。そして最終的に、せきやん(@sekiyan372)の案の聖地巡礼アプリを作ることに決まりました。
Tourism Projectの活動
1. 湯涌デジタルスタンプラリー
Tourism Projectは、花咲くいろはの舞台でもある湯涌をベースにデジタルスタンプラリーをするアプリケーションを作っています。観光客が湯涌に来たときに、そのアプリを使って、各観光スポットで写真を撮ることで位置情報をもとにスタンプがマップに押され、その写真をアプリ内のフォトコンテストに投稿することで、湯涌の魅力を宣伝することが目的です。湯涌観光協会の方々の協力を得ながら、実際に温泉に入ったり、湯涌を観光して自分たちも湯涌の良さを、生で感じたことを発信できるように頑張ってます。他にも自分たちのプロジェクトのHPを作成して活動を発信しています。
2. 作業風景
僕たちは毎週土曜の20:00のzoomミーティングで進捗報告、今後の方針とタスクの確認をして、自分のタスクを各自進めています。定期的に勉強会を行ったり、焼肉に行ったり親睦会も行ってます!興味のある方は是非Tourism Projectへ!!
NuxtのVuexについて
はじめに
この記事は Vue や Nuxt を触ったことがある前提で書いてあります。 Vue や Nuxt が何かについて書いて欲しいという声があれば、いずれ(誰かが)記事を書くでしょう(たぶん)。
Vuexとは?
簡単にいうと Nuxt の状態管理ライブラリです。
と言われても???っていう人もいると思いますが、ざっくり説明するとログイン状態の情報や取得した API のデータなどを保存・管理できるようなイメージでいいと思います。
Nuxt では様々なコンポーネントを作成すると思いますが、それぞれに何度も同じ処理を書かずとも良くなるのでコードが見やすくなったり、データの管理がしやすくなり複雑化によるミスなども防げるかと思います。さらに、データへのアクセスの流れを一方向にすることができる(詳しくは後述)ため安定した管理がしやすくなります。
特に大規模な開発ではこういったことは必須になってくるので、ぜひ使ってみましょう。
データの流れ
まずは Vuex でのデータの流れをざっと理解しましょう。
以下はよく見るVuex公式ページの図です。
Vuex ではデータは基本的に Action → Mutation → State → Vue Components という流れになります。
ちなみに Vue Components は State を直接参照せずに Getter を経由することが推奨されています。
初めての場合、これだけを読んでも何を言ってるのかさっぱりわからないと思いますが、まずは
- Action → Mutation → State → Vue Components の流れ
- State を参照するときはGetterを経由
ということを覚えておきましょう。
次にそれぞれについて詳しく見ていきましょう。
Action
Action は Mutation を介することでStateを更新する役割を持ちます。
大切なのはAction が直接 State を変更することはなく、必ず Mutation を介するということです。これによりデータの流れが一方向に守られます。
バックエンドから API を叩くような処理はここで書きます。
また、非同期での処理を記述することも可能です。
以下は id と name を持つnewData
を取得した仮のデータとして、それをStateにMutationを介して更新するようにしています。
const actions = { fetchData({ commit }) { // これが取得したデータだとする const newData = { id: 1, name: 'data1' } // commitの引数は(Mutationの関数名, 更新データ)となる commit('addData', newData) } }
Mutation
State を更新することができる唯一の手段が Mutation です。
また、Mutation の関数を直接呼ぶことはできず、Action で書いたようにcommit()
を使用して呼び出します。
状態変化を予測可能なものにするため、Mutation は必ず同期的でなければなりません。
以下は配列である State のdata
に新しく更新したデータを追加する処理です。
const mutations = { addData(state, newData) state.data.push(newData) }
State
Stateはデータの入れ物で、ユーザーのログイン情報など複数のコンポーネントでを跨ぎたい情報を管理します。
以下ではdata
という State を定義しています。
const state = () => ({ data: [] })
Getter
GetterはStateの値から算出される値を返します。
先ほども書いた通りコンポーネントから State を参照する場合は必ずこの Getter を経由します。
以下では State のData
を参照しています。
const getters = { getData(state) { return state.data } }
コードまとめ
先程まではデータの流れの順に紹介しましたが、実際にコードにすると読みにくいので以下のような順で書くことが多いです。
export const state = () => ({ data: [] }) export const mutations = { addData(state, newData) state.data.push(newData) } export const actions = { fetchData({ commit }) { // これが取得したデータだとする const newData = { id: 1, name: 'data1' } // commitの引数は(Mutationの関数名, 更新データ)となる commit('addData', newData) } } export const getters = { getData(state) { return state.data } }
component などでの操作
State を取得したいときは以下のように書きます。
this.$store.getters["storeのファイル名/getData"]
State を更新したいときは以下のように書きます。
this.$store.dispatch("storeのファイル名/fetchData")
さいごに
Vuexなかなかとっつきにくいですよね。
個人で小さいアプリを作ったりするだけであれば正直使わなくてもいいと思いますが、それなりの規模のアプリを作るときにはこういった状態管理は必須になってくるので、がんばって勉強しましょう。概念的な部分を理解してしまえば、例えば React での Redux とかの他の状態管理ライブラリも理解しやすくなると思います。
僕自身もまだ完璧に理解しきれているかと言えば自信はないので、これからも勉強を続けていこうと思います。
この記事が少しでも理解の役にたったら幸いです。
執筆者: せきやん(@sekiyan372)
参考
FlutterでAndroid/iOSの機能を使う
Flutterの課題
前回の記事でFlutterの特徴は、クロスプラットフォームが最大の特徴
と伝えましたが、クロスプラットフォームゆえ様々な課題を抱えています。
- プラットフォーム(Android/iOS)の機能を最大限活かすことができない
- 独自のUIでレンダリング(描画)するため、プラットフォーム毎にUIを変更することができない
- Dartで開発するため、学習コストが必要
今回はMethodChannelを活用し、ネイティブの機能を実装する方法をご紹介します。
MethodChannel
MethodChannelとは、Dartからネイティブ(Java,Kotlin,Objective-C,Swift)の機能を呼び出すもしくは、プラットフォームからDartの機能を呼び出すことができる方法です。
iPhoneのバッテリー状況を取得してみる
SwiftのUIDevice classをDartで呼び出し、Flutterで作成したアプリにバッテリー状況を表示するデモアプリをご紹介します。
Flutter(Dart)のプログラム
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/cupertino.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const platform = const MethodChannel('samples.flutter.dev/battery'); String _batteryLevel = 'Battery Level'; Future<void> _getBatteryLevel() async { String batteryLevel; try { final int result = await platform.invokeMethod('getBatteryLevel'); batteryLevel = 'Battery level at $result % .'; } on PlatformException catch (e) { batteryLevel = "Failed to get battery level: '${e.message}'."; } setState(() { _batteryLevel = batteryLevel; }); } @override Widget build(BuildContext context) { return Material( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( child: Text('Get Battery Level'), onPressed: _getBatteryLevel, ), Text(_batteryLevel), ], ), ), ); } }
Swiftのプログラム
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery", binaryMessenger: controller.binaryMessenger) batteryChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in // Note: this method is invoked on the UI thread. guard call.method == "getBatteryLevel" else { result(FlutterMethodNotImplemented) return } self?.receiveBatteryLevel(result: result) }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func receiveBatteryLevel(result: FlutterResult) { let device = UIDevice.current device.isBatteryMonitoringEnabled = true if device.batteryState == UIDevice.BatteryState.unknown { result(FlutterError(code: "UNAVAILABLE", message: "Battery info unavailable", details: nil)) } else { result(Int(device.batteryLevel * 100)) } } }
実行結果
まとめ
MethodChannelを活用することにより、プラットフォームの機能を活かすことができ、効率よく開発することができます。