20201121のvue.jsに関する記事は7件です。

【Vue.js】カウンター作成記録

はじめに

vueの練習したいけど何を作ればいいのか。
そうだ、カウンターを作ろう。

とりあえず作った


カウンター (2).png

コード

counter.html
<template>
  <div>
    <b-button v-on:click="countUp" variant="success">カウントアップ</b-button>
    <b-button v-on:click="countDown" variant="primary">カウントダウン</b-button>
    <b-button v-on:click="countClear" variant="danger">カウントクリア</b-button>
    <h1>{{displayCount}}</h1>
    <div v-if="displayCount > 10">
      {{successCount()}}
    </div>
  </div>
</template>
counter.js
<script>
export default {
  data() {
    return {
      displayCount: 0
    };
  },
  methods: {
    countUp() {
      this.displayCount++;
    },
    countDown() {
      this.displayCount--;
    },
    countClear() {
      this.displayCount = 0;
    },
    successCount() {
      alert('great!!')
    }
  }
};
</script>

さいごに

マウスをカチカチするだけでも楽しくなっちゃう自分としては
かなり良い暇つぶしグッズを作ってしまった。
vue.jsで作った意味があるのかわからない感じだけど、記法とかをおぼえる練習としては良かったかな。
ここまで読んでくれた方ありがとうございました!

おまけ

下記のリンクで遊べます。
ちなみにCodeSandboxはかなり優秀な開発環境ですので是非使ってみてほしいです。
https://codesandbox.io/s/counter-practice-xlquf

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

Vuetifyの初期画面を表示するまで

マテリアルデザインフレームワークvuetifyの
半日ぐらいかかったので未来の自分へメモ

Windows版PyCharmでのセットアップ

  • Node.jsインストール

Windows 10へNode.jsをインストールする - Qiita
そのままインストールする

  • PyCharmのVue.jsプラグインのインストール

image.png

  • New Project Locationのプロジェクト名を任意のものに変更してCreateボタン実行

image.png

  • Terminal

ターミナルウィンドウからnpm install --save-dev @vue/cli実行

image.png

ターミナルウィンドウから.\node_modules\.bin\vue add vuetify実行

image.png

WARN There are uncommitted changes in the current repository, it\'s recommended to commit or stash them first.
? Still proceed? (y/N)y ←yでEnter

image.png

Default (recommended)を選択してEnter

image.png

Shift+F10実行してブラウザでアクセス

image.png

Linux上でのセットアップ

$ npm init --yes
$ npm install --save-dev @vue/cli
$ ./node_modules/.bin/vue create --default .
 ? Generate project in current directory? (Y/n)Y ←YでEnter
$ ./node_modules/.bin/vue add vuetify
 WARN  There are uncommitted changes in the current repository, it\'s recommended to commit or stash them first.
 ? Still proceed? (y/N)y  ←yでEnter
 ? Default (recommended)  ←そのままEnter
$ cat vue.config.js
module.exports = {
  "transpileDependencies": [
    "vuetify"
  ],
  devServer: {
    port: 8080,
    disableHostCheck: true,
  },
}
$ npm run serve

$ npm run build

Flaskとの結合は以下参照

Vue.js + FlaskでWebアプリケーション制作 - herokuにデプロイするまで - - Qiita

画面変更は以下参照

Vuetifyに入門する - Qiita

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

vue-routerの戻るボタンを押してback()した時は処理を変えたい

目的

<keep-alive /> やvuexを使った場合、ブラウザのメモリ上にデータが残る
これらの機能を使った一覧画面の場合、

  • 過去データをそのまま表示するか?
  • サーバーに再検索するか?

の判断が必要になるケースが稀にある。

例えば、戻るボタン、backで画面遷移したい場合は過去の検索結果のデータを表示し、
メニュー等、他からの画面遷移なら再検索させたい場合がこれにあたる

vuer-router経由で読み込むPage Componetに対して、
共通でextendsするcomponentとして下記を定義する

export default {
  name: 'base-page',
  beforeRouteLeave(to, from, next) {
    if (this.backing) to.params.isBack = true
    this.backing = false
    next()
  },
  data() {
    return {
      backing: false,
    }
  },
  computed: {
    isBack() {
      return this.$route && this.$route.params.isBack
    },
  },
  methods: {
    backPage() {
      this.backing = true
      this.$router.back()
    },
  },
}

一覧ページなどの戻るボタンで戻るページでは下記のように処理分岐する

<script>
import BasePage from '../base-page.js'

export default {
  extends: BasePage,
  beforeRouteEnter: function () {
    if (this.isBack) {
      // 戻るボタン経由の場合
    } else {
      // それ以外の場合
    }
  },
}
</script>

戻るボタンでは、backPageメソッドを呼び出す。
もしくは、ブラウザのback eventを監視し、backPageメソッドと同様の処理を行わせる

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

vue.js 検索窓

1まずは、検索窓の入力をvalueにして、searchにいれる

Searchi.vue 検索窓見た目
<template>
 <!-- 検索窓 親app.vue-->
  <v-text-field
    :value="$store.state.search"  ●追加
    @input="$store.commit('setSearch',$event)" ●追加

    @focus="searchClosed = false"
    @blur="searchClosed = true"
    class="expanding-search mt-1"
    :class="{ 'closed' : searchClosed && !$store.state.search}"
    placeholder="Search"
    prepend-inner-icon="mdi-magnify"
    filled
    dense
    clearable
  ></v-text-field>
</template>
store.js データが保管されるとろ
export default new Vuex.Store({
  state: {
    search:null, ●追加

.....いろいろ...

 mutations: {
    setSearch(state,value){ ●以下追加
      state.search = value
      console.log('value',value)
    },

イメージ
$eventは特殊らしい
ステートの値が、バリューとミューテーションでsetSearchに加工された
プログラミング-22.jpg

2,次は、検索窓に入力したものと、タスクを一致させて呼び出す

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

vue.js vuetify使って検索窓

1まずは、検索窓の入力をvalueにして、searchにいれる

Searchi.vue
検索窓見た目

<template>
 <!-- 検索窓 親app.vue-->
  <v-text-field
    :value="$store.state.search"  ●追加
    @input="$store.commit('setSearch',$event)" ●追加

    @focus="searchClosed = false"
    @blur="searchClosed = true"
    class="expanding-search mt-1"
    :class="{ 'closed' : searchClosed && !$store.state.search}"
    placeholder="Search"
    prepend-inner-icon="mdi-magnify"
    filled
    dense
    clearable
  ></v-text-field>
</template>
store.js
データが保管されるところ

export default new Vuex.Store({
  state: {
    search:null, ●追加

.....いろいろ...

 mutations: {
    setSearch(state,value){ ●以下追加
      state.search = value
      console.log('value',value)
    },

イメージ
$eventは特殊らしい
ステートの値が、バリューとミューテーションでsetSearchに加工された
プログラミング-22.jpg

2,次は、検索窓に入力したものと、タスクを一致させて呼び出す

store.js

export default new Vuex.Store({
  state: {
    search:null,
    tasks:[   入ってるデータ
      {id:1,
        title:'Wake up',
        done:false,
        dueDate:'2020-10-16'
      },
      {id:2,
        title:'get banana',
        done:false,
        dueDate:'2020-10-16'
      },
      {id:3,
        title:'eat banana',
        done:false,
        dueDate:null
      },
    ],
  getters:{ 追加一致してるものを呼び出す
    tasksFiltered(state){ ●作成
      if(!state.search){ ●stateが入っているなら
        return state.tasks ●タスクのデータ全部返す
      }
      return state.tasks ●配列になってるタスクの中から
       .filter(task => 一致するものをループで呼び出して
         task.title ●タスクタイトルの
         .toLowerCase() ●大文字小文字
         .includes(state.search.toLowerCase()) ●検索窓に含んでるやつ
      )
    }
  }
ListTask.vue
タスクの見た目
親のコンポーネントではループ処理をしているのでゲッターで一致してるやつを呼び出すようにする
    <task
        v-for="task in $store.getters.tasksFiltered" ゲッターを適応
        :key="task.id"
        :task="task"
    ></task>

プログラミング-22 3.jpg

これで、データの中身を検索窓から取り出せるようになった。
ムズい!!!
ので、図でまとめないとわからん!!

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

【Vue.js】Vue.jsとcssアニメーションで作るスライドショー

Vue.jsCSSを用いてスライドショーを実装するメモです。

目的

スライド画像.gif
上記のようなシンプルなスライドショーを実装します。

実装

テンプレート

Imageslide.vue
<template>
  <div>
    <transition-group tag="ul" class="images">
      <li
        v-for="(image, index) in demoimages"
        v-show="currentImage == index + 1"
        :key="index"
      >
        <img :src="image.image" alt="" />
      </li>
    </transition-group>
  </div>
</template>

画像をv-forでリストしてv-showで表示を切り替えています。
v-showv-ifとは違い、DOMを消したり追加したりはせず、display:noneを付与して要素を非表示にします。そのため非表示の画像をもう一度表示する場合も、再度画像が読み込まれるわけではありません。

スクリプト

Imageslide.vue
<script>
export default {
  data() {
    return {
      currentImage: 1,
    }
  },
  computed: {
    demoimages() {
      return [
        { image: '/images/1.jpg' },
        { image: '/images/2.jpg' },
        { image: '/images/3.jpg' },
      ]
    },
  },
  watch: {
    currentImage() {
      this.autoSlide()
    },
  },
  mounted() {
    this.autoSlide()
  },
  methods: {
    async autoSlide() {
      const wait = (ms) =>
        new Promise((resolve) => setTimeout(() => resolve(), ms))
      await wait(2000)
      if (this.currentImage > this.images.length - 1) {
        this.currentImage = 1
      } else {
        this.currentImage++
      }
    },
  },
}
</script>

表示されている画像のインデックスを示すcurrentImageをウォッチしてautoSlide()を実行しています。currentImageが画像のリストを超えた場合に初期化することで無限ループになります。

スタイル

Imageslide.vue
<style lang="scss" scoped>
.images {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  position: relative;
  li {
    width: 100%;
    height: 100%;
    max-height: 627px;
    position: absolute;
    top: 0;
    left: 0;
  }
}
img {
  width: 100%;
  height: 100%;
  max-height: 627px;
  margin: auto;
  z-index: 2;
}
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s;
}

.v-enter,
.v-leave-to {
  opacity: 0;
}
</style>

リストの親要素にposition:relativeを指定し、子要素にposition:absolute top:0 left:0を指定することで同じ位置に画像を重ねることができます。
.v-enter-active,.v-leave-active,.v-enter,.v-leave-totransitionによってVueから自動的に付与されるクラスです。

まとめ

Vue.jsとCSSを使用したスライドショーの実装方法について簡単に説明してみました。私はこのように実装しましたが、おそらく別の方法もあるかと思います。いろいろ試してみてください!

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

v-bind:keyは並び替えるためのものじゃない

結論

v-bind:keyはそれぞれの要素に一意なキーを与えるだけ。並べ替えはしません。
並べ替えるなら関数使って新しく作りましょう。

お恥ずかしいことに、下記のようにキーに数字を与えると自動で並べ替えられると思っていました。

<span v-for="num in [3, 2, 1]" :key="num">
    {{ num }}
</span>

<!-- 期待したのは出力はこっち--> 
<!-- 1 2 3 -->

<!-- 実際の出力は以下になる -->
<!-- 3 2 1 -->

具体的な並び替え方は以下が参考になりました。
Vue.jsのv-forでの並び順を指定したキーの値順にしたり、昇順、降順を切り替えたりする

まとめ

keyは一意に定めるものでそれ単体で並び替えに使えるものではありません。並び替えるならcomputedプロパティなどを使って並び替えたデータを用意しましょう。

私のように変な勘違いを起こした方が路頭に迷わないためにここに残しておきます。

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