20200209のvue.jsに関する記事は10件です。

export defaultについて

Vue.jsを扱っていて、export defaultがよくわからなかったので調べてみました。

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

単一ファイルコンポーネントとは、コンポーネントを構成するtemplate、style、scriptを1つのVueファイルでまとめて管理することを言います。
機能ごとに「HTML」「CSS」と切り出すのではなく、部品ごとに切り出して管理し、それをだし分けることでUIを作成することができます。
単一ファイルコンポーネントの思想で作られたのがVueCLIです。

他のコンポーネントで利用できるようにするためには

それでは、単一ファイルコンポーネントの思想で、他のコンポーネントでも利用できるようにするためにはどうすればよいのでしょうか。
それは、 export default でメンバーを囲むことで、外部からも参照できるようにします。
単一ファイルコンポーネントでは外部から参照されることが前提の仕組みになるので、基本的にscriptの部分は export default で囲むことが前提となります。

<script>
export default {
    name: "Header",
    data() {
        return{
            msg2: "はじめまして"
        }
    } 
}
</script>

使う側(親となる)コンポーネントでは、インポートした上で、使うコンポーネントをまた export default で囲んで templateの中で使えるモジュールとします。

<script>
import Header from '@/components/Header.vue'

export default {
  name: 'home',
  components: {
    Header
  }
}

</script>

scriptで export default で囲んでいるので、テンプレートでは Header を使うことが可能となります。

<template>
  <div class="home">
    <Header/>
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="こんにちは"/>
    <h1>This is an about page <fa icon="user" /></h1>
  </div>
</template>

単一ファイルコンポーネントでは、関連するどちらのvueファイルでも export default が必要となります。

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

自分好みのdocker image を作る。(vue.cli編)

はじめに

自分用メモ
Dockerでimageを作成するには、以下の2通りがある。

  • Dockerfileから作る
  • 適当なOSのイメージをpullして、コンテナを作った後、bashにより自分好みのパッケージ等をインストールしてimage化する

今回は後者の方法でdocker imageを作成したのでそれをメモする。

好みのOSをえらんでコンテナ作成

今回はubuntuにしました。

$ docker run --name containerName -it ubuntu:18.04 /bin/bash

runコマンドでimageのpullとコンテナの作成をまとめてやってくれる。/bin/bashでシェルに接続。--name containerName でコンテナ名決めれる。

好みのパッケージ等を入れてく。

今回は

  • curl
  • yarn
  • node.js
  • npm
  • vue.cli
  • webpack

などを入れた。

image化

以下のコマンドを打ち込むだけ。

//まずはコンテナを止めましょう。
docker stop containerName
//そしてイメージ化
docker commit containerName imageName:version 

imageを起動

作ったイメージを起動してみよう。
以下のコマンドで入れる。今回はオプションとしてポート番号をつけている。

docker run --name containerName -p 1234:8080 -it imageName:version /bin/bash  

おわりに

分かれば簡単だけど、dockerのネットワークの仕組みとかが分からないとオプションとかの設定に悩みことになる。(なった)この記事は自分用なので他の方には分かり辛いと思う。そんな人には以下のyoutubeが分かりやすい。

https://www.youtube.com/watch?v=DS5HBTMG1RI&t=3s
https://www.youtube.com/watch?v=h6uw5c5GB_U

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

FirebaseをWebアプリに導入する準備をした【備忘録】

自分用の備忘録です。
Firebaseを自作Webアプリに導入する準備をしました。
Firebaseの公式サイト

0. 概要

  1. Firebase上で準備をする
  2. 便利なパッケージをインストールする
  3. 設定ファイルを作成する

1. Firebase上で準備をする

1-1. アカウントを作成する

Sign in ボタンをクリックして、アカウントを作成します。
ログインしたら Go to console ボタンをクリックします。

1-2. プロジェクトを作成する

名前を付けて、プロジェクトを作成します。
アナリティクスは入れても入れなくても問題ありません。

1-3. アプリを追加する

iOS Android Web の3つの選択肢があると思います。
Webアプリなら Web をクリックして追加します。

2. 便利なパッケージをインストールする

Firebaseを便利に設定できるパッケージがあるので、それを導入します。

$ npm install --save firebase

3. 設定ファイルを作成する

Firebaseを使うための設定ファイルを作成します。

firebase.js
import firebase from 'firebase/app';

if (!firebase.apps.length) {
 const config = {
   apiKey: "~~~",
   authDomain: "~~~",
   databaseURL: "~~~",
   projectId: "~~~",
   storageBucket: "~~~",
   messagingSenderId: "~~~"
 };
 firebase.initializeApp(config);
}

~~~ と書いてあるところに、必要な情報を入力します。
Firebase上で、自分のWebアプリの設定で Firebase SDK snippet を見ます。
ここに書かれてある情報をコピペして導入完了です。

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

TypeScript中括弧の型定義方法

エラー箇所

  login: ({ commit }) => {

エラー内容

commitの部分で以下のエラーを吐く

Binding element 'commit' implicitly has an 'any' type.ts

修正方法

  login: ({ commit }: { commit: Function }) => {

参照
TypeScript公式

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

【Nuxt.js】$router.push('/')で異なるURLに遷移する

開発中に学んだ知識のアウトプットとして書いています。

nuxt-linkで遷移する方法

about.vue
<nuxt-link to="/">
  <div>ホームへ戻る</div>
<nuxt-link>

今までは'nuxt-link'タグで遷移する方法のみ使用していました。
*この機能は Nuxt.js v2.4.0 で追加されました。
*'router-link'の拡張版のようです。

$route.push()で遷移する方法

about.vue
<button @click="$route.push('/')">ホームに戻る</button>

'push'メソッドでも遷移できるようです。'click'アクションでホームに戻る処理です。

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

Vueはどこへ消えた?

この物語は、Vue CLIに興味を持ち、Yarnを使ってインストールしてみたものの、パスを見失ってしまった哀れな開発者の奮闘の記録です。

第1話 WindowsにYarnでVue CLIをインストールする

事件編

まずはWindowsにNode.jsとYarnをインストールします。使うのは、Windows用のパッケージマネージャChocolatey

choco install nodejs
choco install yarn

で、Vue CLIの記述の通り、YarnでVue CLIをインストール。

yarn global add @vue/cli

ちゃんとインストールできたかか確認すると……

vue --version

……こんな無慈悲なメッセージが。

'vue' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

Vueはどこへ消えた?

解決編

Yarnでグローバルインストールしたパッケージは、C:\Users\me\AppData\Local\Yarn\bin に隠れています。
なので、このパス(%AppData%\Local\Yarn\binでも可)を手動で環境変数に追加すれば、パスが通ります。
めでたしめでたし。

第2話 ChromebookにYarnでVue CLIをインストールする

事件編

次は、Chromebook(上のLinux)にもVue CLIをインストールしてみます。
Node.js 公式のバイナリディストリビューションを参考にNode.jsと、

curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
sudo apt-get install -y nodejs

Yarn公式サイトを参考にYarnをインストールします。

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn

で、さっきと同じようにYarnでVue CLIをインストールし、確認すると……
……こんな無慈悲なメッセージが。

-bash: vue: command not found

Vueはどこへ消えた?

解決編

Yarnでグローバルインストールしたパッケージは、「Linux ファイル」からアクセスできるホームフォルダ内の.yarn/binに存在します。
同じディレクトリにある.profileファイルをテキストエディタとかで開き、

if [ -d "$HOME/.yarn/bin" ] ; then
    PATH="$HOME/.yarn/bin:$PATH"
fi

と末尾に追記して、ターミナルを再起動すると、無事パスが通ります。
めでたしめでたし。


ちなみに、Angular CLIngコマンドなんかも同じ要領で解決できますよ。

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

初心者によるプログラミング学習ログ 234日目

100日チャレンジの234日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

234日目は

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

SPAのリビジョン管理workbox5 workbox-window

構成

Laravel6
vuex 3.1.2
vue 2.6.11
workbox-webpack-plugin 5.0.0
workbox-window 5.0.0

お品書き

  • workbox-webpack-pluginの導入(GenerateSW)
  • app.jsの編集(サービスワーカーの登録とライフサイクル別にしたいことの記述)
  • vuexで新バージョンがあるかチェック
  • コンポーネントにアラート追加

注意事項

nuxt.jsをご利用の方へ
おそらくindex.htmlのキャッシュをしない戦略だけで対応可能(nuxtで作られるjsは毎回名前が違うため、topHTMLだけよめばそこから最新のjsを引っ張ってこれる、はず)
Nuxt.js(SPA)とFirebaseで強制リビジョン(バージョン)アップするならPWAモジュールを使おう
上記はlaravelMIXを使っていると常に読み込むjsはapp.jsになるためうまくいかず。

その他
サービースワーカーを初めて触ったため、試行錯誤した結果まあ一定動くなというレベル感のコードです。その仕様はまずいなどありましたらご指摘いただけると幸いです。
キャッシュファイルのバージョンを手動で管理するとかのものは別記事にあったのですが、自分が求めた仕様とは異なり、あまり記事も見当たらなかったのでログとして残します。
今回の構成の参考

workbox-webpack-pluginの導入

laravelMixや素のwebpackを利用している場合に使うプラグインです。参照

npm i workbox-webpack-plugin --save-dev

webpack.mix.jsの編集

GenerateSWを利用します。InjectManifestの方はより細かい設定をしたい時やプッシュ通知なども利用したいときに使います。参照

webpack.mix.js
import { GenerateSW } from 'workbox-webpack-plugin'

mix.js('resources/js/app.js', 'public/js')
   .sass('resources/styles/app.sass', 'public/css')


mix.webpackConfig({
  output: {
    publicPath: "",
  },
  // ~中略~
  plugins: [
    new GenerateSW({
      maximumFileSizeToCacheInBytes: 10000000,//jsファイルが5mb以上になっているとデフォルトの設定ではprecacheできないので要件に応じて設定してください。
      clientsClaim: true,
      skipWaiting: true,
      runtimeCaching: [
      //リクエストするURLに応じて、キャッシュ戦略を指定することができます。[参照](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build.html#.RuntimeCachingEntry)
        {
          urlPattern: new RegExp('https:\/\/fonts.(gstatic|googleapis).com.*$'),
          handler: 'CacheFirst',
          options: {
            cacheName: 'google-fonts',
            expiration: {
              maxEntries: 100,
              maxAgeSeconds: 60*60*24
            },
            cacheableResponse: { statuses: [0, 200] },
          }
        }
      ]
    })
  ],
  //~中略~
})

*workbox5からはトランスパイル先のディレクトリや対象ファイルの拡張子での指定などをわざわざしなくても、webpackの基本設定をもとにうまいことやってくれます。がpublicPathを明示的に何も付けないように指定しないと、生成されるservice-wroker.jsのプリキャッシュ指定ファイルのパスが//js/app.jsのようになってしまうため、先頭の二重スラッシュを避けるようpublicPathを明記します。

app.jsの編集

トランスパイルされた、service-worker.jsの登録とライフサイクル時の処理を記載します。
workbox-windowの導入(ライフサイクルのそれぞれの時点でフックして処理をかけるようにしてくれる優れもの)参照

If you do call skipWaiting() then it's best to inform users of the update once the new service worker has activated,
この部分

webpack.mix.jsで書いたようにskipWaiting()ですぐに新しいサービスワーカーを利用する設定にしたため上記で言われているようにactivatedのタイミングでプリキャッシュしたjsの新しいバージョンがあることをユーザーに伝える。

npm i workbox-window --save-dev
app.js
import {Workbox} from 'workbox-window'
import store from '~/store/index'
import cron from 'node-cron'

const wb = new Workbox('/service-worker.js');
if ('serviceWorker' in navigator) {
  wb.addEventListener('activated', (event) => {
    if (event.isUpdate) {
      //更新が確認された場合には、最新のバージョンが使えることをvuexでstoreに保存
      store.dispatch('update/setStatus', true)
    }
  })
  wb.register();
}
Vue.prototype.$wb = wb
cron.schedule('0 0 0,6,12,18 * * *', async () => await wb.update())//updateメソッドで定期的に確認する。promiseが帰ってくるのでasync,awaitを使う

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

activatedのタイミングに対してイベントリスナを追加して、アップデートされたタイミングで、処理を走らせる。
今回は、node-cronを使用して定期的にworkbox-windowのupdate methodを走らせ、更新を確認しにいかせるようにしている。

componentの編集

上記までの処理で、サービスワーカーに変更があった場合には、vuexのstoreにその状態が反映されている。
あとはコンポーネントからゲッターでstateを確認しに行き、最新バージョンがあることが確認できたら、リロードを促すアラートを表示する。

wrapper.vue
<template>
  <div class="fill-height">
    <v-content>
      <v-container fluid>
        <v-alert
          v-model="update"
          v-if="update"
          type="warning"
          icon="mdi-cloud-alert"
          dense
          prominent
        >
          <v-row align="center">
            <v-col class="grow">新しいバージョンがリリースされています。右のボタンから更新してください。</v-col>
            <v-col class="shrink">
              <v-btn v-on:click="reload">更新する</v-btn>
            </v-col>
          </v-row>
        </v-alert>
        <transition name="fade" mode="out-in">
          <router-view></router-view>
        </transition>
      </v-container>
    </v-content>
  </div>
</template>

<script>
  import {mapGetters} from 'vuex'

  export default {
    computed: {
      ...mapGetters({
        update: 'update/status' //stateの取得
      })
    },
    reload() {
        location.reload()
        this.$store.dispatch('update/setStatus', false)
      },
    }
  }
</script>

まとめ

サービスワーカーの挙動が全部把握できているわけではなく、いったん動くものをという形でやってみたが、ちゃんと制御しないと思わぬ事故になりそう。

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

vue css-loader エラー:Module build failed: TypeError: this.getResolve is not a functionでコケる

症状

ERROR in ./node_modules/css-loader?sourceMap!./node_modules/vue-loader/lib/style-compiler?{"vue":true,"id":"data-v-39e2d1f7","scoped":true,"hasInlineConfig":false}!./node_modules/sass-loader/dist/cjs.js!./src/pages/About/About.scss
Module build failed: TypeError: this.getResolve is not a function
    at Object.loader (/Users/MyUserName/MyDirectory/node_modules/sass-loader/dist/index.js:52:26)
...
..
.

解決策

sass-loaderで似たようなエラーが出たとき、一旦uninstall(remove)して、古いバージョンをistall(add)してみると直った、という記事を見て、同じことをcss-loaderでも試したら直った。

npmの場合

$ npm uninstall css-loader
$ npm install css-loader@2.0.0

yarnの場合

$ yarn remove css-loader
$ yarn add css-loader@2.0.0

備考:css-loaderのverについて

npmのcss-loaderのページを見て適当に@2.0.0としたが、もうちょい新しいverでもいけるのかもしれないものの、試してない。

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

【Vue CLI】プロジェクトを作成した時につくられる[src/components]フォルダと[src/view]フォルダの違いって?

実行環境

@vue/cli 4.1.2

1.vue createでプロジェクトを作成

vue create my-project

Routerを選択します。

? 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

とりあえずプロジェクトの作成は完了しました。

作成したプロジェクトのフォルダを確認

srcフォルダ内の構成は次のようになっています。

└── src
    ├── App.vue
    ├── assets
    │   └── logo.png
    ├── components
    │   └── HelloWorld.vue
    ├── main.js
    ├── routersr
    │   └── index.js
    └── views
        ├── About.vue
        └── Home.vue

ここで気になるのがcomponentsフォルダとviewsフォルダ。

.vue拡張子からもわかるように、中身のファイルをみるとどちらも単一ファイルコンポーネントで構成されています。

src/views/Hello.vue
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  }
}
</script>
src/components/HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <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>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

これらのフォルダの違いはなんでしょうか?

viewsフォルダはルーティングに登録されるコンポーネント

viewsフォルダに置かれているコンポーネントはルーティングを構成します。

つまり、src/router/index.jsimportされるコンポーネントです。

src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

確かに、ルーター定義において、viesフォルダから呼び出されていることが確認できます。

componentsフォルダは再利用可能で、ページを構成する部品

対して、componentsフォルダのコンポーネントはルートとして使用されません。

コンポーネントは再利用可能な部品として扱われます。

さいごに

viewsフォルダとcomponentsフォルダの役割の違いを見てきました。
しかし、この指針に必ずしも従う必要はありません。

例えば、次のようなことが考えられます。

  • viewsフォルダをsrc/routerの下に配置する
  • viewsフォルダをpagesフォルダと呼ぶ
  • `すべてのコンポーネントを同じフォルダの中に配置する

結局、そのフォルダ構成はプロジェクトの好みによる部分が大きいでしょう。

vue/createで作り出されるフォルダ構成は、一つの指針にすぎません。

参考

vue.js - What is the difference between the views and components folders in a Vue project?

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