20200722のvue.jsに関する記事は8件です。

【第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>は削除すると画面にエラーは出なくても何も表示されなくなりました。
image.png

App.vueから読み込んでいる

importしているのは9行目の記述と教わりました。
image.png

動画でやりたかった事を実践してみる

13行目から17行目の実践をしたかったのです。
image.png

動画では、以下のコードでした。

vue.js
var app = new Vue({
  el: '#app',
  data: {
    product: 'Socks'
  }
})

実装するのが、chromeのconsoleだったから、この記述になっていたようです。
難しいですね。

とりあえず、Socksというもじに変更しました。
あとは画像が欲しかったので、「V」マークは残しておきました。

image.png

今日はここまでにしました。
引き続き、頑張ります.....

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

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ライブラリと合わせて提供すればコンポーネントおよびその状態管理も合わせて提供可能になりそうですね。

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

Vue.jsのコンポーネント設計に滅茶苦茶悩んだ話

はじめに

この度Vue.js(2系) + Vuetifyの構成(Laravelを使ったMPA)で社内で初めてVueを導入しての開発を行う事になったのですが、フロントエンドエンジニアが私一人ということもあり、コンポーネント設計で結構悩んだ話です。

そこで一応自分なりの結論が出たので、共有いたします。
まだまだ粗削りな部分はあるかと思いますが、少しでも皆さんの参考になれば幸いです。

詳細設計

まずVueに限らずコンポーネント志向のフレームワークでは基本的にAtomic Designをベースに設計すると思います。
そのため初めはそれに則り設計していたのですが、コンポーネントの粒度をどうするかの部分がイマイチ決まらず一度設計を見直す事になりました。

そもそも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は親のBasebase-以降の文字を受け継ぎます。
例: base-header > header-bar, header-drawer
またCommonPresentationalは頭にcommon-を付ける事としました。
例: common-breadcrumbs

コード

ではコードの面で具体的にはどうなっているかですが、以下のサンプルページでの例をご覧ください。

-サンプルページ-

sampleapp.png

まずは全体の構成。
(※本来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つで、画面とともに色分けしたものが以下です。

sampleapp2.png

  • Base
    • base-header
    • base-contact
  • Presentational
    • header-bar
    • header-drawer
    • contact-form
  • CommonPresentational
    • common-breadcrumbs

※コード量が少なく再利用もしない場合は、更にcontact-form内をパーツ単位でPresentationalに切り出すことはせず、コンポーネントに直接記述する。

このような感じで、機能単位でコンポーネントを分けています。

まとめ

いかがでしたでしょうか。

言ってしまえばAtomic Designの縛りを緩くして、「通信・storeアクセス・state保持用のコンポーネント」・「表示用のコンポーネント」・「表示用の共通コンポーネント」の3つに分けただけなのですが、今のところうまくハマっているのでやり直してよかったです。

それでは。

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

実践で覚える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公式サイトクリックスタート

次回は、Vuetify公式にあるレイアウトを使用していきたいと思います。

Vuetify公式サイトレイアウト

実践で覚えるVue.js(Vuetify) その2

以上

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

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 --save

pluginsの設定

ここの設定を調整した。
pluginsのディレクトリにvue-awesome-swiper.jsを新規作成。

plugins/vue-awesome-swiper.js
import 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.js
plugins: [
    { 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は便利だけど、バージョンごとに若干使い方が変わってくるので毎回ハマってしまい苦手意識がある。。

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

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 hello
cd 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>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 hello
cd 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>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VeeValidate3で別フィールドの値をvalidation時に参照する

概要

Vue.jsで入力項目のvalidationを行う際、VeeValidateのライブラリを使うケースが多いと思います。今回はそのVeeValidate3系のバージョンで、パスワードの再入力時の同一チェックのように、別フィールドを参照してvalidationしたい場合の実装方法について書いてみます。

前提など

実装サンプル

  • pluginに設定しているvee-validate.jsの内容は以下です。今回はパスワードの再入力欄のほうにカスタムのvalidationを設定しています。必要箇所のみ抜粋して記載しています。
vee-validate.js
extend("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>

  • 表示はこんな風になるイメージです。(エラーメッセージ部分の表示はbootstrapを使用) スクリーンショット 2020-07-21 5.01.31.png
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む