- 投稿日:2020-07-22T23:40:21+09:00
【第2回_もくもく会_超初心者】Vue.jsを学習する_公式サイト参照
本日も隔週水曜に実施される「もくもく会」でした!
今日はvue.js実装の経験がある人も一緒にもくもくしてくれました ヾ(´∀`)ノキャッキャ公式サイトから学習する
公式サイトにいくと、「Vue Masteryで無料の動画コースを見る」という無料で学べるようなので、ここからやってみる。
(1)動画を進める
chromeの拡張機能"Vue.js devtools"をインストール
Vue.js devtoolsをインストール
そして....すぐに学習を続けられなくなった.....|ω·`)(2)index.htmlが読み込まれず調査を開始する
index.htmlのファイルをいじっても何も変わらなかった。
どうやらHelloWorld.vueのtemplateから読み込まれていると知った。とりあえずVSCodeの拡張機能"Vue VSCode Extension Pack"をインストール
Vue VSCode Extension Packをインストール
とりあえずsassを使えるようにする
npm install sass-loader node-sass --save-dev調べるのが止まって、救いを求めることにしました。
経験者に助けを求める(涙)
index.htmlの中身が、App.vueの中身を読んでる事がわかったけど、どういう作りなのでしょう。と、経験者に聞くことにしました。
構成について気にし始める
先輩「CLIを使っているんですね? 」と言われて、私は「はっ」としました。
使っていますけれど、どういうものか分かっていない.....各々が部分テンプレートみたいにして作成してるんだよ。という事を言っていただいて、今後はそこらへんを深堀りしていきたいと思いますが、そもそも作りについてとか、実装しているものについてを振り返りたいと考えました。
Vue CLI では何をしているのでしょう?
vue.jsアプリ向けのCLIベースの開発ツール
ということでした。[参照したページ:Vue.jsの開発体験を次の次元へ CLIが苦手でも使える「Vue CLI」のすすめ]
この、コマンドを入力するだけでVue.jsの環境やプロジェクトのテンプレートファイルが一式で揃えられる「vue-cli」を"どうやら便利らしい"という理由で、私はインストールしています。生成されたファイルの構成について考える
どう紐づいているのだろうか
最初に
create vue
した時に、連動していたのは"index.html","components/HelloWold.vue","App.vue"あたりを最初にいじると練習が出来そうだとは認識をしました。
以下の14行目にある
<div id="app"></div>
は削除すると画面にエラーは出なくても何も表示されなくなりました。
App.vueから読み込んでいる
動画でやりたかった事を実践してみる
動画では、以下のコードでした。
vue.jsvar app = new Vue({ el: '#app', data: { product: 'Socks' } })実装するのが、chromeのconsoleだったから、この記述になっていたようです。
難しいですね。とりあえず、Socksというもじに変更しました。
あとは画像が欲しかったので、「V」マークは残しておきました。今日はここまでにしました。
引き続き、頑張ります.....
- 投稿日:2020-07-22T22:39:09+09:00
Vuexでシステム日時をリアクティブに + Vuexプラグイン自作時の注意点
Vueを使っていて、画面上で日時を出したい場合や日時をもとに比較したい場合があったが、それに対してベストなプラグインが無かったので自作しました。
vuex-systime npm
vuex-systime github日付をシンプルにリアクティブにできない理由
JavaSriptでローカルの日時を取得する方法は以下のように実装します。
const currentDate = new Date() // 日付型を取得 const currentTime = Date.now() // エポックタイムからの経過ミリ秒を取得これをVueのcomputedに書いたとします
computed: { currentDate() { const d = new Date() return d } }ただ、これではリアクティブにはならないです。理由はここらへんとか見て欲しいですが、VueのリアクティブはVueで管理されているプロパティが変わったら、依存しているプロパティを再計算しに行く形で実装しています。そこでこの日付はnew Date()を実行すれば変わるのですが、実行するまでは変わらないので変わったことを検知されないので、初期化時に計算された値がキャッシュされ、そのまま保持されます。
日付をリアクティブにするやり方
よくあるやり方はsetInterva()で都度書き換えて上げれば良いです。
data: { currentDate:null }, mounted() { setInterval(() => { this.currentDate = new Date() }, 1000) }1秒毎にcurrentDateが変わります。そのためそれをもとに画面描画しているとその値が常に再描画されていきます。
vuex-nowというライブラリがあり、vuexのプラグインとして設定しておくと良い感じに1秒毎に描画してくれます。自作した理由
vuex-nowでだいたい事足りそうなのですが、以下の理由から自作しました。
- 1秒毎の書き換えだと書き換わりすぎる(1分毎とかが良い)
- 現在時刻と比較して、何かするといのがあるが、現在時刻との比較する量が多く性能が懸念された
- 1分毎なんだけど、1分のインターバルではなく、00秒で切り替えたい
- サーバの時間に基づいていて欲しい。サーバの時間とクライアントの時間がずれていた場合にはその差分を考慮して計算して欲しい。
- vuexのプラグインを作ってみたかった
1つ目の理由は、秒を切り捨てたプロパティを別途保持しておき、そいつと比較すれば良さそう。
2つ目の理由も、vuex-nowを使って、それとサーバ時間との差分を計算した別のプロパティを持てば良さそう。
結局3つ目の理由なのかもしれない。Vuexプラグイン作成
以下の機能を保持したVuexプラグインを作りました
- リアクティブにシステム日時を保持
- 更新タイミングを指定可能
- 1分ごとに更新といった場合には、00秒が経過したタイミングで書き換わる
- サーバ時刻とクライアント時刻の差分(オフセット時間)を保持し、オフセット時間とクライアント時間をもとにシステム日時を算出する
Vuexで任意の機能を持ったStoreを登録する場合には、対象のstoreをimportして登録するでも良いのですが、プラグインを使っても登録できます。
以下はVuexのプラグインでRegisterModuleでstoreを登録する際の記載です。import {systemDatetimeStore} from './vuex-systime-store' export default function VuexSystemDatetime (param) { return store => { 〜省略〜 // モジュールの登録 store.registerModule(moduleName, systemDatetimeStore) // 登録後に、必要に応じて初期化処理等を走らせる store.dispatch(moduleName + '/updateTime', null, { root: true }) } }モジュール名は任意にプラグインの中で任意に決めても良いのですが、paramから上書きできるようにした方が良いと思います。
また、再利用性を求めてStoreの中で、どのモジュール名が与えられているか取得しようとしたのですが、現在はできないようですね。仕方ないので、モジュール名をstateに持ってしまいました。そして、モジュール名は、プラグインからの初期化時に設定という形です。
何か良い案があれば良いのですが。。。export const systemDatetimeStore = { namespaced: true, state: { moduleName: null, // モジュール名を持たせてしまっている1分ごとに更新といった場合には、00秒が経過したタイミングで書き換わる
という処理については、以下のアクションで実装しました。
updateTime: function ({state, commit, dispatch}, param) { const now = Date.now() const calcTime = now + state.offsetTime // cutoffTimeに60*1000を持たせておき、差異を算出 const timeoutTime = calcTime % state.cutoffTime // setTimeoutで差異時間経過後に再度自身を再帰的に呼び出す const oldTimeoutId = moduleParameter[state.moduleName].timeoutID moduleParameter[state.moduleName].timeoutID = setTimeout(() => { dispatch('updateTime') }, state.cutoffTime - timeoutTime) // もし別のsetTimeoutが呼び出されているならば、リセット clearTimeout(oldTimeoutId) commit('setLocalTime', now) commit('setSystemTime', calcTime) }感想
Vuexのプラグインって、stateも含めて再利用したい場合にも応用できるみたいですね。Vueライブラリと合わせて提供すればコンポーネントおよびその状態管理も合わせて提供可能になりそうですね。
- 投稿日:2020-07-22T17:44:30+09:00
Vue.jsのコンポーネント設計に滅茶苦茶悩んだ話
はじめに
この度Vue.js(2系) + Vuetifyの構成(Laravelを使ったMPA)で社内で初めてVueを導入しての開発を行う事になったのですが、フロントエンドエンジニアが私一人ということもあり、コンポーネント設計で結構悩んだ話です。
そこで一応自分なりの結論が出たので、共有いたします。
まだまだ粗削りな部分はあるかと思いますが、少しでも皆さんの参考になれば幸いです。詳細設計
まずVueに限らずコンポーネント志向のフレームワークでは基本的にAtomic Designをベースに設計すると思います。
そのため初めはそれに則り設計していたのですが、コンポーネントの粒度をどうするかの部分がイマイチ決まらず一度設計を見直す事になりました。そこで、他の設計手法はないかと色々な企業様やエンジニアの方の記事を参考にさせていただきました。
※参考にさせていただいた記事
①Atomic Designが刺さる現場・刺さらない現場
②BASEのVue.jsコンポーネントの設計
③ワイ「何でそんな小っさいコンポーネント作ってるん?wコンポーネント設計の概要については①、③の記事で勉強させていただき、詳しい設計は主に②のBASE様のコンポーネント設計を参考にさせていただきました。
まず上記②を参考にコンポーネントの種類は、
- 唯一http通信とstoreへのアクセスを行え、機能単位でのstateを持つベースとなるコンポーネント(Base)
- 表示にのみ責務をもつコンポーネント(Presentational)
- 様々なコンポーネントで再利用される、Presentationalコンポーネント(CommonPresentational)
の三種類としました。
5つに分かれているAtomic Designと比べると大分少ないと思います。
ただ根本的な思想の部分は同じで、まず「Pages」と「Templates」に相当するのがBaseです。
上記の通り機能単位の比較的大きなstateを持ち、唯一http通信とstoreへのアクセスが行えます。次に「Organisms」と「Molecules」と「Atoms」に相当する、表示にのみ責務を持つのがPresentationalになります。
その中から再利用するものはCommonPresentationalに切り出し、あとは「Atoms」や「Molecules」単位で切り出す事を強制せず、必要に応じて新たなPresentationalを作るか、コンポーネントに直接記述します。そしてコンポーネントの命名規則ですが、Baseには頭に
base-
をつけ、Presentationalは親のBaseのbase-
以降の文字を受け継ぎます。
例:base-header
>header-bar
,header-drawer
またCommonPresentationalは頭にcommon-
を付ける事としました。
例:common-breadcrumbs
コード
ではコードの面で具体的にはどうなっているかですが、以下のサンプルページでの例をご覧ください。
-サンプルページ-
まずは全体の構成。
(※本来base-header
は全ページ共通なのでapp.blade.php
に記述し、base-contact
はルーティングで切り替える部分なので実際の構成とは異なっており、レイアウトやデータの受け渡し部分も分かりやすくするためにあえて端折っています。)app<template> <div id="app"> <base-header /> <base-contact /> </div> </template>次に
base-header
の中身は、base-header<template> <header class="header"> <header-bar /> <header-drawer /> </header> </template>最後に
base-contact
の中身は、base-contact<template> <div class="contact"> <common-breadcumbs /> <contact-form /> <div> </template>のようになっています。
ここで登場するコンポーネントは全部で6つで、画面とともに色分けしたものが以下です。
- Base
- base-header
- base-contact
- Presentational
- header-bar
- header-drawer
- contact-form
- CommonPresentational
- common-breadcrumbs
※コード量が少なく再利用もしない場合は、更に
contact-form
内をパーツ単位でPresentationalに切り出すことはせず、コンポーネントに直接記述する。このような感じで、機能単位でコンポーネントを分けています。
まとめ
いかがでしたでしょうか。
言ってしまえばAtomic Designの縛りを緩くして、「通信・storeアクセス・state保持用のコンポーネント」・「表示用のコンポーネント」・「表示用の共通コンポーネント」の3つに分けただけなのですが、今のところうまくハマっているのでやり直してよかったです。
それでは。
- 投稿日:2020-07-22T16:27:42+09:00
実践で覚えるVue.js(Vuetify) その1
概要
私は、考えるより手を動かすタイプだ
という方向けにチュートリアルなどを使用しながら、
Webアプリケーション開発していく方法を書いていきたいと思います。ターゲット層
- 考えるより感じたいという方
- JavaScriptを始めてみようかなと考えている方
- 開発業務に携わったことがない方
使用エディタ
Visual Studio Code
これからVisual Studio Codeを使用していきたいが、
インストールしていないという方は、
インストール手順をググってみてください。
※スクリーンショットがあるサイトが見やすいと思います。※事前にVSCodeにお好みで拡張機能を入れておくと楽になります。
VSCode+Vue.jsを使用するならインストールするべき拡張機能と設定
Vueの開発におすすめなVSCodeの拡張機能を紹介!!事前準備
- Node.jsのインストール
以下の記事を参考にしてみてください。
windows10にNode.jsをインストールする
- VSCodeでGit Bashをターミナルに設定する※私がLinuxコマンド使い慣れているため
以下の記事を参考にしてみてください。
WindowsのVSCodeでGit Bashをターミナルに設定する実践その1(Vue.js・Vuetifyのインストール)
バージョン確認
ターミナルnode -v v12.16.2 ※これは私が使用しているNode.jsのバージョンです。 npm -v 6.14.4 ※これは私が使用しているNode.jsのバージョンです。Vue.jsインストール
以下を参考にさせていただいております。
Vue.jsについての基礎(インストール)ターミナル#インストール npm install -g vue-cli #バージョン確認 vue -V →バージョン情報が表示されること実践その2(プロジェクト作成)
以下を参考にさせていただいております。
Vuetifyをインストールして使ってみるターミナル#プロジェクトを作成するディレクトリにcdしてから実行してください #作成に時間がかかります。。 vue create vue-project ? Please pick a preset: Manually select features ? Check the features needed for your project: >(*) Babel ( ) TypeScript ( ) Progressive Web App (PWA) Support (*) Router (*) Vuex ( ) CSS Pre-processors (*) Linter / Formatter ( ) Unit Testing ( ) E2E Testing ? Check the features needed for your project: Babel, Router, Vuex, Linter ? Use history mode for router? (Requires proper server setup for index fallback in production) No ? Pick a linter / formatter config: Basic ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, ESLint, etc.? In package.json ? Save this as a preset for future projects? (y/N) N #作成したプロジェクトディレクトリへ移動 cd vue-project #プロジェクト実行 npm run serve #以下URLへアクセス http://localhost:8080/ →Vueのロゴページが表示されていることVuetifyインストール
ターミナル#現在位置確認 pwd →vue-projectにいること #Vuetifyインストール vue add vuetify ? Choose a preset: Default (recommended) #Vuetify反映確認 npm run serve #以下、URLにアクセス http://localhost:8080/ →Vuetifyロゴページが表示されていることまとめ
Vue.js・Vuetifyの記事は、ググれば色々と出てきます。
個人的には、公式サイトがおすすめです。次回は、Vuetify公式にあるレイアウトを使用していきたいと思います。
以上
- 投稿日:2020-07-22T14:38:03+09:00
vue-awesome-swiperが動かなくてハマった
Nuxt.jsでSwiperを使ってみたが、うまく動かなくてハマったけどなんとか解決。
環境
- Nuxt.js v2.4.0
- vue-awesome-swiper v4.1.1
- swiper v6.0.4
現象
配布サイトや他の記事参考にインストール・設置するも、スワイプやドラッグでのスライド以外できない。
autoplayやfade、pagenationなど動かず。参考にした記事等
- vue-awesome-swiper
- Nuxt.jsで高機能スライダーSwiperを使ってみた
- Nuxt.js + Swiper スライダーの作り方結論
Global Registrationの設定をいじったらできるようになった。
以下のページが解決のきっかけになった。
https://github.com/surmon-china/vue-awesome-swiper/issues/688よくみたら配布サイトにも書いてった。(Custom Build with Swiperの項目)
インストール
配布サイトと同様。
swiperとvue-awesome-swiperの両方必要。npm install swiper vue-awesome-swiper --savepluginsの設定
ここの設定を調整した。
pluginsのディレクトリにvue-awesome-swiper.jsを新規作成。plugins/vue-awesome-swiper.jsimport Vue from 'vue' import Swiper from 'swiper/swiper-bundle.esm' import getAwesomeSwiper from 'vue-awesome-swiper/dist/exporter' Vue.use(getAwesomeSwiper(Swiper)) import 'swiper/swiper-bundle.css'配布サイトでは
swiper/swiper.esm
を読み込んで、使うcomponentを指定していたが、
面倒なのでswiper/swiper-bundle.esm
を読み込んで指定なしで全component使えるようにした。これがベストなのかは正直わからないが、必要な機能だけ読み込たい場合は配布サイトのCustom Build with Swiperの項目を参考にしてみたら良いだろう。
nuxt.config.jsでの読み込み
nuxt.config.jsplugins: [ { src: '@/plugins/vue-awesome-swiper.js', ssr: false } ], ... build{ vendor: [ 'vue-awesome-swiper', ], }Swiperの設定
pages/index.vue<div class="swiper-container" v-swiper="swiperOption"> <div class="swiper-wrapper"> <div class="swiper-slide">Slide1</div> <div class="swiper-slide">Slide2</div> <div class="swiper-slide">Slide3</div> </div> <div class="swiper-pagination"></div> </div> ... export default { data () { return { swiperOption: { effect: 'fade', loop: true, autoplay: { delay: 5000, }, pagination: { el: '.swiper-pagination', clickable: true }, } } } }これで動くはず。
swiperは便利だけど、バージョンごとに若干使い方が変わってくるので毎回ハマってしまい苦手意識がある。。
- 投稿日:2020-07-22T11:02:35+09:00
vue.jsの勉強をしてみた
前提知識
vue.jsとは
vue.jsは、Webアプリケーションのユーザインターフェースを効率的に構築するのに適したjavaScriptのフレームワークです。
Vue CLI
Vue CLIは、大規模なVueアプリケーションを効率的に作成するためのツールです。
Node.jsやVueRouterなどと連携していくことにより、シングルページアプリケーション(SPA)を効率的に開発できます。SPA
SPAは、基本部分が単一のページで構成されるWebアプリケーションです。
JavaScriptでサーバと通信してDOMを操作することでコンテンツを切り替えます。DOM(Document Object Model)
JavaScriptからHTML文書やXML文書の要素を操作する仕組みです。
Vue.jsはリアクティブなフレームワークであり、JavaScript側のVueインスタンス内のデータとHTMLを基本としてテンプレート構文に記述した内容がバインドされデータを変更すると、それがすぐDOMツリーに反映されWEBブラウザの表示が更新されます。vue-cliでプロジェクト作ってみた
vue create hellocd helloシングルファイルコンポーネント
拡張子が「.vue」で、javascript,html,cssがひとまとまりになったもの。
(ES2015のモジュール機能を使用している)Helloしてみた
Hello.vue<template> <div> <h1>{{ msg }}</h1> </div> </template> <script> name: "Hello", props: { msg: String }; </script> <style scoped> h1 { color: red; } </style>
- 投稿日:2020-07-22T11:02:35+09:00
Vue CLI
おさらい
vue.jsとは
vue.jsは、Webアプリケーションのユーザインターフェースを効率的に構築するのに適したjavaScriptのフレームワークです。
SPA
SPAは、基本部分が単一のページで構成されるWebアプリケーションです。
JavaScriptでサーバと通信してDOMを操作することでコンテンツを切り替えます。DOM(Document Object Model)
JavaScriptからHTML文書やXML文書の要素を操作する仕組みです。
Vue.jsはリアクティブなフレームワークであり、JavaScript側のVueインスタンス内のデータとHTMLを基本としてテンプレート構文に記述した内容がバインドされデータを変更すると、それがすぐDOMツリーに反映されWEBブラウザの表示が更新されます。Vue CLI
Vue CLIは、大規模なVueアプリケーションを効率的に作成するためのツールです。
Node.jsやVueRouterなどと連携していくことにより、シングルページアプリケーション(SPA)を効率的に開発できます。vue-cliでプロジェクト作ってみた
vue create hellocd helloシングルファイルコンポーネント
拡張子が「.vue」で、javascript,html,cssがひとまとまりになったもの。
(ES2015のモジュール機能を使用している)Helloしてみた
Hello.vue<template> <div> <h1>{{ msg }}</h1> </div> </template> <script> name: "Hello", props: { msg: String }; </script> <style scoped> h1 { color: red; } </style>
- 投稿日:2020-07-22T00:14:32+09:00
VeeValidate3で別フィールドの値をvalidation時に参照する
概要
Vue.jsで入力項目のvalidationを行う際、VeeValidateのライブラリを使うケースが多いと思います。今回はそのVeeValidate3系のバージョンで、パスワードの再入力時の同一チェックのように、別フィールドを参照してvalidationしたい場合の実装方法について書いてみます。
前提など
- 下記の項で紹介する実装サンプルは、Nuxt.js前提とします(Vue.jsで使うのと大差ないとは思いますが念のため・・)。Nuxt.jsでのVeeValidateの使用方法については、【Nuxt.js】vee-validate を使って、フォームのバリデーション実装をするを参照してください。
- 実装サンプルは、よくあるパスワード再入力の例で記載しています。
- 公式ドキュメントについてCross Field Validationを参照しています。ただ、このページはバージョンが変わったら更新されると思うので、あくまで2020年7月時点での内容を参考にしている、という前提でご認識ください。
- VeeValidate2系のバージョンについては、VeeValidateで複数のフィールドにバリデーションをかけるやり方の内容が参考になると思います。
実装サンプル
- pluginに設定している
vee-validate.js
の内容は以下です。今回はパスワードの再入力欄のほうにカスタムのvalidationを設定しています。必要箇所のみ抜粋して記載しています。vee-validate.jsextend("passwordReInput", { params: ["target"], validate(value, { target }) { return value === target; }, message: "上のパスワード欄と同様のものを入力して下さい" });
- component側での実装例は以下です。rulesで参照するフィールドのValidationProviderのnameに頭に「@」を付与して、別フィールドを参照しています。なお、以下のサンプルはtemplate部分のみとし、エラーメッセージの表示部分についてのロジックは記載を割愛してます。(errorsを別componentに渡して表示しています)
PasswordSample.vue<template> <div> <validation-observer v-slot="{ invalid }"> <div class="form-group"> <label for="password">パスワード</label> <validation-provider v-slot="{ errors }" rules="required|min:6" name="password"> <input type="password" class="form-control" v-model="password" /> <ErrorMessageComponent :errors="errors" /> </validation-provider> </div> <div class="form-group"> <label for="passwordReInput">パスワード再入力</label> <validation-provider v-slot="{ errors }" rules="passwordReInput:@password" name="passwordReInput"> <input type="password" class="form-control" v-model="passwordReInput" /> <ErrorMessageComponent :errors="errors" /> </validation-provider> </div> </validation-observer> </div> </template>