20201227のvue.jsに関する記事は16件です。

ページネーション【Vue.js/Vuetify】

概要 ・ ポートフォリオでページネーション機能を実装したので、コメントつきのソースコードを紹介 ・ 使用した技術はRealtimeDatabase(Firebase)とVuetify(Vue.js)   ※ v-pagenation のページは https://vuetifyjs.com/ja/components/paginations/ ・ api経由でデータを取得し、ページネーション付きで表示する ・ 開発環境はVue-Cli template <v-layout> <v-flex> <v-pagination v-model="currentPage" :length="getPageCount"> </v-pagination> </v-flex> </v-layout> <v-layout v-for="list in getLists" :key="list.message"> //以下省略 </v-layout> :length は画面に表示できる最大限のページ数のこと。 script data(){ return { input: '', parPage:3, //1ページごとに表示されるリスト数 currentPage:1 //画面を開いた時に最初にあなたがいるページの場所 } }, computed(){ lists(){// 表示するリストのデータ return this.$store.state.lists }, getLists(){// 表示するリストを1ページ3つにする let current = this.currentPage * this.parPage //全ページlistの合計数 let start = current - this.parPage //1ページ目のlistの数 return this.lists.slice(start, current) //リストの何番目〜何番目を今のページに表示するか }, getPageCount(){ //引数として与えた数以上の最小の整数を返す //ページ数になって、上の:lengthに当てはめる return Math.ceil(this.lists.length / this.parPage) } }, watch:{ search(){//1ページ目以外のページにいる状態で検索欄に文字入力すると、1ページ目に戻って検索 this.currentPage = 1 } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リアルタイム検索【Vue.js/Vuetify/Vuex】

概要 ・ ポートフォリオでリアルタイム検索機能を実装したので、コメントつきのソースコードを紹介 ・ 使用した技術はVue.js,Vuetify,Vuex  ※ v-text-field のページは以下URL内にあり。 https://vuetifyjs.com/en/components/text-fields/#api ・ api経由でデータを取得し、ページネーション付きで表示する ・ 開発環境はVue-Cli template <v-layout> <v-flex>    //入力フォーム <v-text-field label="検索する" v-model="search"> </v-text-field> </v-flex> </v-layout> <v-layout v-for="list in getLists" :key="list.index"> //以下にcomputedの「getLists」がループされて表示される </v-layout> computed内では、stateから取得したリストをgetListsで自分が入力した内容とマッチするリストになるようにフィルタリング。 フィルタリングしたリストをv-forループで表示させる。 script data(){ return : {    //上記入力フォームの初期値 search: " } }, computed(){ //stateの配列listsの中のオブジェクトから、キーtitleがv-modelで入力したsearchと一致するものだけ表示 getLists(){ const lists = this.$store.state.lists return lists.filter((list) => { return list.title.match(this.search) }) } } store(state) lists: [ { id: "akdddgela22nad", title: "FreeTalk in NewYork", date: "2017-09-29", location: "New York"} { id: "akdbbraa5ffggg", title: "FreeTalk in Paris", date: "2017-10-20", location: "Paris" } //以下省略... ], 下記のように" || "を使用すれば、リストの中のあらゆるワードや数字を拾って検索も可能になる。 script return list.title.match(this.search) || list.date.match(this.search) || list.location.match(this.search)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SPA作成の雛形【Vue.js/Vuetify】

概要 ・ Vue.js/VuetifyでSPAを作成時にこの雛形から要素を付け足していくことにすればスムーズにSPAが作成できるかと思い投稿 ・ 使用した技術はVuetify ・ 開発環境はVue-Cli App.vue <template> <v-app> //左に出てくるナビゲーションドローワー <v-navigation-drawer app v-model="drawer" temporary> <v-list-item> <v-list-item-content> <v-avatar> <img src="photoURL"> </v-avatar> </v-list-item-content> <v-list-item-content> <v-list-item-title>ユーザネーム</v-list-item-title> </v-list-item-content> </v-list-item> <v-divider></v-divider> <v-list-item v-for="item in menuItems" :key="item.title" :to="item.link"> <v-list-item-icon> <v-icon>{{ item.icon }}</v-icon> </v-list-item-icon> {{ item.title }} </v-list-item> </v-navigation-drawer>   //画面の上に表示するナビゲーションバー <v-app-bar app> <v-app-bar-nav-icon @click.stop="drawer = !drawer"> </v-app-bar-nav-icon> <v-toolbar-title> <router-link to="/" tag="span" style="cursor: pointer">アプリケーション</router-link> </v-toolbar-title> <v-spacer></v-spacer> <v-toolbar-items class="hidden-xs-only"> <v-btn text v-for="item in menuItems" :key="item.title" :to="item.link"> <v-icon medium left>{{ item.icon }}</v-icon> {{ item.title }} </v-btn> </v-toolbar-items> </v-app-bar>    //routerの画面の表示場所 <v-main> <router-view/> </v-main> </v-app> </template> <script> export default { name: 'app', data: () => ({ drawer : false }), computed: { menuItems(){ let menuItems = [ {icon: "mdi-login", title:"ログイン", link:"/login"}, {icon: "mdi-account-multiple", title:"アイテムを見る", link:"/items"}, {icon: "mdi-google-maps", title:"アイテムを投稿", link:"/item/new"} //以下省略... ] return menuItems } }; </script> ■Vuetifyコンポーネントは下記を使用。バージョンによって変化するので注意が必要。 ・ナビゲーションドローワー: v-navigation-drawer   参考:https://vuetifyjs.com/ja/components/navigation-drawers/ ・ナビデーションバー:   v-app-bar   参考:https://vuetifyjs.com/ja/components/app-bars/ ■menuItemsとして配列にアイテムを保存してv-forループで表示。 ■class="hidden-xs-only" : 画面がXSサイズ(スマホサイズ)で見るときにだけバーのメニューが消える。   参考:https://vuetifyjs.com/ja/styles/display/#visibility ■v-mainの中に遷移していく画面であるrouter-viewを入れる。router-viewのところに、router/index.jsの画面が遷移していく。 router/index.js import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../components/Home.vue' import CreateFreeTalk from '../components/Item/CreateItemc.vue' //以下省略... Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/item/new', name: 'CreateItem', component: CreateItem }, //以下省略... ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MailAddressとPasswordによるユーザー新規登録/認証【Vue.js/Vuetify/Vuex/Firebase】

概要 ・ ポートフォリオでメールとパスワードでユーザー新規登録/認証機能を実装したので、コメントつきのソースコードを紹介 ・ 使用した技術はRealtimeDatabase(Firebase)・Vuetify・Vue.js・Vuex ・ 開発環境はVue-Cli signup.vue <template>    <div>     <h1>新規登録</h1> <v-divider></v-divider> //下記の「type="submit"」のクリックにより、下記に入力したemailとpasswordを引数としてonSignupメソッドが発動 <form @submit.prevent="onSignup"> <v-layout> <v-flex> <v-text-field name="email" label="Mail" id="email" v-model="email" type="email" required>              </v-text-field> </v-flex> </v-layout> <v-layout> <v-flex> <v-text-field name="password" label="Password" id="password" v-model="password" type="password" required> </v-text-field> </v-flex> </v-layout> <v-layout> <v-flex>              //クリックすると<form></form>間に入力した情報が提出(submit)される <v-btn type="submit"> </v-btn> </v-flex> </v-layout> </form>  </div> </template> <script> export default { data(){ return{ //入力したメールアドレス email: "", //入力したパスワード password: "" } }, computed: { //あなたのユーザー情報を取得 user(){ return this.$store.getters.user } }, watch: {   //あなたのユーザー新規登録処理が成功したらホーム画面へ遷移する user(value){ if(value !== null && value !== undefined){ this.$route.push("/") } } }, methods: {   //v-modelで入力したemailとpasswordを引数にしてactionsの"signUserUp"へデータを渡す onSignup(){ this.$store.dispatch("signUserUp", {email: this.email, password: this.password}) } } } </script> store state: {  //あなたのユーザー情報のstate。ログインするとユーザー情報のオブジェクトがnullに入る user: null }, mutations: { //stateのuserをactionsのユーザーオブジェクトにする。またはnullに戻す setLoginUser(state, payload){ state.user = payload } }, actions: { signUserUp({commit}, payload){     //dispatchで引数にしたemailとpasswordを使って、firebaseのAuthenticationsにユーザーアカウントが作成される。 firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password) .then( user => {       //登録済みユーザーオブジェクト const newUser = { id: user.uid }        //mutationsへ登録済みユーザーオブジェクトを渡す commit("setLoginUser", newUser) }) .catch( error => { console.log(error) }) } }, getters: {   //stateのユーザーオブジェクトをgettersで取得 user(state){ return state.user } } ユーザー新規登録の大まかな処理フロー ① v-modelのアドレスとパスワードを入力し、引数としてonSignupメソッドが動き、actionsのsignUserUpが動く。 ② actionsでのcreateUserWithEmailAndPasswordにてFirebaseのAuthenticationsにアドレスとパスワードを新規登録。登録成功したら、そのユーザーオブジェクトをmutationsへ渡す。 ※ Promise(.then/.catch)を付けないと、ユーザーのアドレスとパスワードがAuthenticationsに登録される前にuser情報がnullのままmuationsへ処理が進んでエラーになるので、Promiseは忘れないように。 Promiseについては、下記の記事がわかりやすく、参考にさせていただきました。   https://qiita.com/saka212/items/9b6cfe06b464580c2ee6  ③ mutationsによって、stateでnullになっているuserにmutationsのユーザーオブジェクトを上書きする。 ④ signup.vue にてgettersでstateのユーザーオブジェクトを引っ張ってきて、watchにて「gettersのuserにユーザーオブジェクトが入ってきてユーザー新規登録が完了したら、ホーム画面に戻る」 ように監視する。 ⑤ 新規ユーザー登録完了した後 、ホーム画面に戻ることで完了 では次に新規登録したユーザー情報のメールアドレスとパスワードでログインするフローについて。 signin.vue <template> <div> <h1>ログイン画面</h1>      //下記の「type="submit"」のクリックにより、下記に入力したemailとpasswordを引数としてonSigninメソッドが発動 <form @submit.prevent="onSignin"> <v-layout> <v-flex xs12> <v-text-field name="email" label="Mail" id="email" v-model="email" type="email" required>        </v-text-field> </v-flex> </v-layout> <v-layout> <v-flex xs12> <v-text-field name="password" label="Password" id="password" v-model="password" type="password" required></v-text-field> </v-flex> </v-layout> <v-layout> <v-flex>       //クリックすると<form></form>間に入力した情報が提出(submit)される <v-btn type="submit"> ログインボタン </v-btn> </v-flex> </v-layout> </form> </div> </template> <script> export default { data(){ return{     //入力したメールアドレス email: "",     //入力したパスワード password: "" } }, computed: {    //あなたのユーザー情報を取得 user(){ return this.$store.getters.user } }, watch: { //あなたのユーザーログイン処理が成功したらホーム画面へ遷移する user(value){ if(value !== null && value !== undefined){ this.$route.push("/") } } }, methods: {   //v-modelで入力したemailとpasswordを引数にしてactionsの"signUserIn"へデータを渡す onSignin(){ this.$store.dispatch("signUserIn", {email: this.email, password: this.password}) } } } </script> store.js state: { //あなたのユーザー情報のstate。ログインするとユーザー情報のオブジェクトがnullに入る user: null }, mutations: { //stateのuserをactionsのユーザーオブジェクトにする。またはnullに戻す setLoginUser(state, payload){ state.user = payload } }, actions: { signUserIn({commit}, payload){ //dispatchで引数にしたemailとpasswordを使って、firebaseのAuthenticationsにて認証 firebase.auth().signInWithEmailAndPassword(payload.email, payload.password) .then(       //ユーザーのオブジェクト user => { const newUser = { id: user.uid }        //mutationsへログインするユーザーオブジェクトを渡す commit("setLoginUser", newUser) }) .catch( error =>{ console.log(error) }) }, } ユーザー認証処理のフロー: 新規登録処理とほぼ同じ流れ ① v-modelのアドレスとパスワードを入力して引数としてonSigninメソッドが動き、actionsのsignUserInが動く。 ② actionsでのsignInWithEmailAndPasswordにてFirebaseのAuthenticationsにアドレスとパスワードを認証。認証成功したら、そのユーザーオブジェクトをmutationsへ渡す。 ③ stateでnullになっているuserにmutationsのユーザーオブジェクトを上書きする。 ④ signin.vue にてgettersでstateのユーザーオブジェクトを引っ張ってきて、watchにて「gettersのuserにユーザーオブジェクト入りユーザー認証が完了したら、ホーム画面に遷移する」 ように監視する。 ⑤ ユーザー認証が完了し、ホーム画面に戻ることで完了 最後に 今回は自分なりに書きやすいPromiseでコードを書きましたが、async/awaiteもそろそろ使用してコードを書くことにもチャレンジしていこうかと思います。 できるだけ端的にまとめましたが、もし上記のフローでの理解に誤りがあったり、より良い表現などあればコメントいただければ幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JSXを使ってラジオボタンの設定をシンプルにする

始めに

Vue.jsでラジオボタンの設定をする時は以下のように書くと思いますが、毎回v-modelの設定をするのが面倒だと感じたことはないでしょうか?

ラジオボタンの設定
<template lang="pug">
div
  label
    input(v-model="$data.value", type="radio", value="A")
    | A
  label
    input(v-model="$data.value", type="radio", value="B")
    | B
</template>

これを以下のようにselectと同じように親だけv-modelを設定するだけで済むようなコンポーネントを作ることができますので、そのやり方を紹介したいと思います。

selectと同じような設定方法
<template lang="pug">
div
  //- 親コンポーネントだけv-modelを設定する
  RadioButtonGroup(v-model="$data.value")
    RadioButton(value="A") A
    RadioButton(value="B") B
</template>

実装方法

タイトルにも書いてありますが、JSXを使用します。JSXを使用することで子コンポーネントに対してプロパティを注入することができるので、RadioButtonコンポーネントを探してv-modelのプロパティを注入する形になります(正確にはv-modelの対象となるprops名を入れます)。
vnodeの操作についてはvee-validateのコードを参考にしました。

またvnodeのプロパティの注入はこちらを参考にしました。

JSXで必要なプロパティ・イベントを注入する
const RADIO_BUTTON_NAME = "RadioButton";

/**
 * リスナーオブジェクトにリスナーを追加する
 * @param {Object} listeners - リスナーオブジェクト
 * @param {string} eventName - イベント名
 * @param {function} listener - コールバック関数
 */
function _addListener(listeners, eventName, listener) {
  // リスナーが未登録の場合は登録して終了
  if (!listeners[eventName]) {
    listeners[eventName] = [listener];
    return;
  }

  // 既に単体でリスナーが登録されている時は配列形式にする
  if (typeof listeners[eventName] === "function") {
    listeners[eventName] = [listeners[eventName]];
  }

  // 配列形式のリスナーは単純に追加する
  listeners[eventName].push(listener);
}

/**
 * vnodeにリスナーを追加する
 * @param {Object} vnode - vnode
 * @param {string} eventName - イベント名
 * @param {function} listener - コールバック関数
 */
function addListener(vnode, eventName, listener) {
  // リスナーのプロパティ自体がない時は初期化する
  if (!vnode.componentOptions.listeners) {
    vnode.componentOptions.listeners = {};
  }

  _addListener(vnode.componentOptions.listeners, eventName, listener);
}

/**
 * componentNameにマッチするvnodeにapplyFuncを適応させる
 * @param {Array} vnodes - vnodeリスト
 * @param {string} componentName - コンポーネント名
 * @param {function} applyFunc - マッチしたvnodeに対しての処理
 */
function applyMatchedNodes(vnodes, componentName, applyFunc) {
  const regex = new RegExp(`${componentName}$`);
  for (let i = 0; i < vnodes.length; i++) {
    const vnode = vnodes[i];
    if (regex.test(vnode.tag)) {
      applyFunc(vnode);
    }
    // 子供がある場合は再帰する
    if (vnode.children) {
      applyMatchedNodes(vnode.children, componentName, applyFunc);
    }
  }
}

export default {
  name: 'RadioButtonGroup',
  model: {
    prop: "selectedValue",
    event: "select",
  },
  props: {
    selectedValue: { type: String },
  },
  render() {
    const vnodes = this.$slots.default;
    // ラジオボタンのコンポーネント全てにプロパティを注入する
    applyMatchedNodes(vnodes, RADIO_BUTTON_NAME, (vnode) => {
      if (!vnode.componentOptions || !vnode.componentOptions.propsData) {
        return;
      }
      // 注入するパラメータを入れる(v-modelの対象となるprops名をselectedValueにしているため、その値を入れる)
      vnode.componentOptions.propsData.selectedValue = this.$props.selectedValue;
      // リスナーを設定する
      addListener(vnode, "select", (value) => {
        this.$emit("select", value);
      });
    });
    return <div>{vnodes}</div>;
  },
};

v-modelの値を注入する処理は子孫まで見てくれるため、以下のようにスタイル調整のためにdivが入ってもきちんと値の連動はしてくれます。

子孫でもv-modelの連携はできる
<template lang="pug">
div
  RadioButtonGroup(v-model="$data.value")
    .list
      .list__item
        //- 途中divタグが入っているが、きちんとv-modelが注入されている
        RadioButton(value="A") A
      .list__item
        RadioButton(value="B") B
      .list__item
        RadioButton(value="C") C
</template>

<style lang="scss" scoped>
.list {
  display: flex;

  &__item {
    width: 50px;
  }
}
</style>

終わりに

以上がJSXを使ってラジオボタンの設定をシンプルにする方法でした。JSXはVue.jsでは普段使わないものですが、一部では使うと書きやすくなることがあるため、これを機会に使ってみるのはいかがでしょうか。
サンプルはCodeSandboxに書きましたので、興味がある方は是非見てください。

https://codesandbox.io/s/jsxwoshituteraziobotannoshedingwosinpurunisuru-s0xz5?file=/src/App.vue

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

MailAddressとPasswordによるユーザー新規登録【Vue.js/Vuetify/Vuex】

概要

・ ポートフォリオでメールでユーザー新規登録機能を実装したので、コメントつきのソースコードを紹介
・ 使用した技術はRealtimeDatabase(Firebase)・Vuetify・Vue.js・Vuex
・ 開発環境はVue-Cli

signup.vue
<template>
      <v-container>
          //v-layoutなど省略
          <h1>新規登録</h1>
               <v-divider></v-divider>
               <form @submit.prevent="onSignup">
                   <v-layout>
                      <v-flex>
                          <v-text-field
                             name="email"
                             label="Mail"
                             id="email"
                             v-model="email"
                             type="email"
                             required></v-text-field>
                        </v-flex>
                    </v-layout>
                    <v-layout>
                       <v-flex>
                          <v-text-field
                              name="password"
                              label="Password"
                              id="password"
                              v-model="password"
                              type="password"
                              required></v-text-field>
                       </v-flex>
                     </v-layout>
                  <v-layout>
                      <v-flex>
                         <v-btn type="submit">//クリックすると<form></form>間に入力した情報が提出(submit)される
                         </v-btn>
                      </v-flex>
                  </v-layout>
             </form>
      </v-container>           
</template>

<script>
export default {
  data(){
      return{
      email: "",
      password: ""
    }
  },
  computed: {
    user(){
      return this.$store.getters.user
    }
  },
  watch: {
    user(value){//signup成功したらホーム画面へ
      if(value !== null && value !== undefined){
        this.$route.push("/")
      }
    }
  },
  methods: {
    onSignup(){  
      this.$store.dispatch("signUserUp", {email: this.email, password: this.password})
    }
  }
}
</script>


store
state: {
  user: null
},
mutations: {
 setLoginUser(state, payload){
     state.user = payload
   }
},
actions: {
  signUserUp({commit}, payload){
      firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
       .then(
         user => {
          const newUser = {
            id: user.uid
           }
           commit("setLoginUser", newUser)
         })
       .catch(
         error => {
           console.log(error)
         })
    }
},
getters: {
   user(state){
     return state.user
  }
}

大まかな処理フロー

① v-modelのアドレスとパスワードを入力して引数としてonSignupメソッドが動き、store内のsignUserUpが動く。
② actionsでのcreateUserWithEmailAndPasswordにてFirebaseのAuthenticationsにアドレスとパスワードを登録。登録成功したら、そのユーザーIDをmutationsへ渡す。
③ mutationsによって、stateでnullになっているuserにsignUpしてきたユーザー情報(オブジェクト)を上書きする。
④ signup.vue にてgettersでstateのユーザー情報(オブジェクト)を引っ張ってきて、watchにて「stateのuser情報が入ってきてユーザー新規登録が完了したら、ホーム画面に戻る」 ように監視する。
⑤ 新規ユーザー登録完了し、ホーム画面に戻ることで完了

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

MailAddressとPasswordによるユーザー新規登録【Vue.js/Vuetify/Vuex/Firebase】

概要

・ ポートフォリオでメールでユーザー新規登録機能を実装したので、コメントつきのソースコードを紹介
・ 使用した技術はRealtimeDatabase(Firebase)・Vuetify・Vue.js・Vuex
・ 開発環境はVue-Cli

signup.vue
<template>
      <v-container>
          //v-layoutなど省略
          <h1>新規登録</h1>
               <v-divider></v-divider>
               <form @submit.prevent="onSignup">
                   <v-layout>
                      <v-flex>
                          <v-text-field
                             name="email"
                             label="Mail"
                             id="email"
                             v-model="email"
                             type="email"
                             required></v-text-field>
                        </v-flex>
                    </v-layout>
                    <v-layout>
                       <v-flex>
                          <v-text-field
                              name="password"
                              label="Password"
                              id="password"
                              v-model="password"
                              type="password"
                              required></v-text-field>
                       </v-flex>
                     </v-layout>
                  <v-layout>
                      <v-flex>
                         <v-btn type="submit">//クリックすると<form></form>間に入力した情報が提出(submit)される
                         </v-btn>
                      </v-flex>
                  </v-layout>
             </form>
      </v-container>           
</template>

<script>
export default {
  data(){
      return{
      email: "",
      password: ""
    }
  },
  computed: {
    user(){
      return this.$store.getters.user
    }
  },
  watch: {
    user(value){//signup成功したらホーム画面へ
      if(value !== null && value !== undefined){
        this.$route.push("/")
      }
    }
  },
  methods: {
    onSignup(){  
      this.$store.dispatch("signUserUp", {email: this.email, password: this.password})
    }
  }
}
</script>


store
state: {
  user: null
},
mutations: {
 setLoginUser(state, payload){
     state.user = payload
   }
},
actions: {
  signUserUp({commit}, payload){
      firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
       .then(
         user => {
          const newUser = {
            id: user.uid
           }
           commit("setLoginUser", newUser)
         })
       .catch(
         error => {
           console.log(error)
         })
    }
},
getters: {
   user(state){
     return state.user
  }
}

大まかな処理フロー

① v-modelのアドレスとパスワードを入力して引数としてonSignupメソッドが動き、store内のsignUserUpが動く。

② actionsでのcreateUserWithEmailAndPasswordにてFirebaseのAuthenticationsにアドレスとパスワードを登録。登録成功したら、そのユーザーIDをmutationsへ渡す。
※ Promise(.then/.catch)を付けないと、ユーザーのアドレスとパスワードがAuthenticationsに登録される前にuser情報がnullのままmuationsへ処理が進んでエラーになるので、Promiseは忘れないように。 Promiseについては、下記の記事がわかりやすく、参考にさせていただきました。
  https://qiita.com/saka212/items/9b6cfe06b464580c2ee6 

③ mutationsによって、stateでnullになっているuserにsignUpしてきたユーザー情報(オブジェクト)を上書きする。

④ signup.vue にてgettersでstateのユーザー情報(オブジェクト)を引っ張ってきて、watchにて「stateのuser情報が入ってきてユーザー新規登録が完了したら、ホーム画面に戻る」 ように監視する。

⑤ 新規ユーザー登録完了し、ホーム画面に戻ることで完了

最後に

今回は自分なりに書きやすいPromiseでコードを書きましたが、async/awaiteもそろそろ使用してコードを書くことにもチャレンジしていこうかと思います。
できるだけ端的にまとめましたが、もし上記のフローでの理解に誤りがあったり、より良い表現などあればコメントいただければ幸いです。

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

VSCodeでVue + ESLint + Prettierの環境構築するメモ

概要

VSCodeで、Vue + ESLint + Prettierを導入し、vueファイルやjsファイルの保存時に、自動的にフォーマットがかかるような環境を整えようとしたが、ちゃんと動くまでに時間がかかったのでメモしておく。
(初心者のため間違い等あればご指摘願います。。)

試した環境

  • macOS Catalina (10.15.7)
  • VSCode (1.52.1)

手順

1. Vueプロジェクトの作成

  • vue cliをインストール
    • npm install -g @vue/cli
  • プロジェクト作成(途中でvue 2か3かを聞かれるが、2にしておく。)
    • vue create (プロジェクト名)

2. ESlint, Prettier関連の設定

(https://www.npmjs.com/package/eslint-plugin-prettier-vue を参考にしたら比較的簡単にいった。)

  • 上で作成したプロジェクトのルートディレクトリで、以下を実行

    • yarn add -D eslint-plugin-prettier-vue eslint-plugin-vue eslint-config-prettier eslint prettier
  • プロジェクト作成時に自動で作成された、ルートディレクトリにある.eslintrc.jsを、以下のものに置き換える。なお、rulesのセクションで、色々とセミコロンとかクォーテーションの設定等をしているが、ここは好みのものにする。

.eslintrc.js
module.exports = {
  extends: ['plugin:vue/recommended', 'plugin:prettier-vue/recommended', 'prettier/vue'],
  settings: {
    'prettier-vue': {
      SFCBlocks: {
        template: true,
        script: true,
        style: true,
        customBlocks: {
          docs: { lang: 'markdown' },
          config: { lang: 'json' },
          module: { lang: 'js' },
          comments: false,
        },
      },
      usePrettierrc: true,
      fileInfoOptions: {
        withNodeModules: false,
      },
    },
  },
  rules: {
    'prettier-vue/prettier': [
      'error',
      {
        printWidth: 100,
        singleQuote: true,
        semi: false,
        trailingComma: 'es5',
      },
    ],
  },
}

  • 以下のような.prettierrc.js をプロジェクトのルートディレクトリに作成。このファイルに書く設定は、.eslintrc.jsの、rulesのセクションに書いたものと必ず合わせる。
.prettierrc.js
module.exports = {
  printWidth: 100,
  singleQuote: true,
  semi: false,
  trailingComma: 'es5',
}

  • プロジェクトの作成時に自動で作成された、package.json内のeslintConfigセクションは、不要と思われるので削除しておく。

3. VSCodeの準備

  • 以下のextensionを導入する。(Veturは入れない)

    • ESlint
    • Prettier
    • vue
  • ファイル保存時に自動的にprettierでフォーマットしてくれるように、プロジェクトのルートディレクトリに.vscodeディレクトリを作成し、その配下に、以下のようなsettings.jsonを作成。

.vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
}

  • VSCodeを再起動する。

4. 適当にjsファイルかvueファイルをVSCodeで書いて保存してみる

  • 書いているときにフォーマット違反があったらエラーを出す&保存時に自動フォーマットしてくれるはず
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SPA作成の雛形【Vue.js/Vuetify】

概要

・ Vue.js/VuetifyでSPAを作成時にこの雛形から要素を付け足していくことにすればスムーズにSPAが作成できるかと思い投稿
・ 使用した技術はVuetify
・ 開発環境はVue-Cli

App.vue
<template>
  <v-app>
     //左に出てくるナビゲーションドローワー
     <v-navigation-drawer
      app
      v-model="drawer"
      temporary>
        <v-list-item>
            <v-list-item-content>
                <v-avatar>
                   <img src="photoURL">
                </v-avatar>
            </v-list-item-content>
            <v-list-item-content>
                <v-list-item-title>ユーザネーム</v-list-item-title>
            </v-list-item-content>
        </v-list-item>
        <v-divider></v-divider>
        <v-list-item v-for="item in menuItems" 
                     :key="item.title"
                     :to="item.link">
            <v-list-item-icon>
                <v-icon>{{ item.icon }}</v-icon>
            </v-list-item-icon>
             {{ item.title }}
        </v-list-item>
    </v-navigation-drawer>

  //画面の上に表示するナビゲーションバー
    <v-app-bar
      app>
        <v-app-bar-nav-icon
          @click.stop="drawer = !drawer">
        </v-app-bar-nav-icon>
        <v-toolbar-title>
           <router-link to="/" tag="span" style="cursor: pointer">アプリケーション</router-link>
        </v-toolbar-title>
        <v-spacer></v-spacer>
        <v-toolbar-items class="hidden-xs-only">
            <v-btn text v-for="item in menuItems"
                         :key="item.title"
                         :to="item.link">
              <v-icon medium left>{{ item.icon }}</v-icon>
                 {{ item.title }}
            </v-btn>
        </v-toolbar-items>
    </v-app-bar>
  
   //routerの画面の表示場所
    <v-main>
      <router-view/>
    </v-main>
  </v-app>
</template>

<script>
export default {
  name: 'app',
  data: () => ({
    drawer : false
  }),
  computed: {
    menuItems(){
     let menuItems = [
       {icon: "mdi-login", title:"ログイン", link:"/login"},
       {icon: "mdi-account-multiple", title:"アイテムを見る", link:"/items"},
       {icon: "mdi-google-maps", title:"アイテムを投稿", link:"/item/new"}
       //以下省略...
     ]
      return menuItems
    }
};
</script>

■Vuetifyコンポーネントは下記を使用。バージョンによって変化するので注意が必要。
・ナビゲーションドローワー: v-navigation-drawer
  参考:https://vuetifyjs.com/ja/components/navigation-drawers/
・ナビデーションバー:   v-app-bar
  参考:https://vuetifyjs.com/ja/components/app-bars/

■menuItemsとして配列にアイテムを保存してv-forループで表示。

■class="hidden-xs-only" : 画面がXSサイズ(スマホサイズ)で見るときにだけバーのメニューが消える。
  参考:https://vuetifyjs.com/ja/styles/display/#visibility

■v-mainの中に遷移していく画面であるrouter-viewを入れる。router-viewのところに、router/index.jsの画面が遷移していく。

router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../components/Home.vue'
import CreateFreeTalk from '../components/Item/CreateItemc.vue'
//以下省略...

Vue.use(VueRouter)
  const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/item/new',
    name: 'CreateItem',
    component: CreateItem
  },
//以下省略...
]

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


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

【Vue 2.x】Composition API の readonly と shallowReadonly で気を付けること

TL;DR

  • @vue/composition-api v1.0.0-beta.21 から readonly(), shallowReadonly() が提供されるようになった
  • readonly() は引数で受け取ったオブジェクトの型を DeepReadonly 化して返しているだけである
  • shallowReadonly() は Vue 3 のものとほぼ同じように使える

readonly()shallowReadonly() とは?

readonly() は Vue 3 ではリリース時から提供されているリアクティビティ API で、リアクティブな状態を受け取ってリードオンリーなリアクティブな状態を返すことを目的とする関数です。


readonly() のコード例1
// Vue 3
import { reactive, readonly } from 'vue';

const original = reactive({
  countA: 0,
  foo: {
    countB: 0,
  },
});
const copy = readonly(original);

original.countA++;
copy.countA++; // Set operation on key "countA" failed: target is readonly.
original.foo.countB++;
copy.foo.countB++; // Set operation on key "countB" failed: target is readonly.

console.log(original.countA); // 1
console.log(copy.countA); // 1
console.log(original.foo.countB); // 1
console.log(copy.foo.countB); // 1


shallowReadonly() も Vue 3 ではリリース時から提供されているリアクティビティ API で、readonly() との違いはリードオンリーになる範囲がオブジェクトの第1階層の値に限定される点です。


shallowReadonly() のコード例1
// Vue 3
import { reactive, shallowReadonly } from 'vue';

const original = reactive({
  countA: 0,
  foo: {
    countB: 0,
  },
});
const copy = shallowReadonly(original);

original.countA++;
copy.countA++; // Set operation on key "countA" failed: target is readonly.
original.foo.countB++;
copy.foo.countB++; // ブラウザのコンソール上に警告が出ない

console.log(original.countA); // 1
console.log(copy.countA); // 1
console.log(original.foo.countB); // 2
console.log(copy.foo.countB); // 2


ユースケース

readonly() を用いることで provide() や props などによって子コンポーネントに状態を渡す際、子コンポーネント側からの状態の変更を防ぐことができます。
このことは Vue 3 ドキュメントのリアクティブの基礎 - readonly でリアクティブオブジェクトの変更を防ぐにも記載があります:

例えば、provide されたリアクティブオブジェクトがある場合、それが注入された場所からの変更は防ぎたいことがあります。そうするために、元のオブジェクトに対する読み取り専用のプロキシを作成します

Vue 2 の readonly()shallowReadonly() について

Vue 2 では Composition API は @vue/composition-api プラグインとして提供されていますが、@vue/composition-api v1.0.0-beta.21 から Vue 2 向けに readonly(), shallowReadonly() が提供されるようになりました。

readonly() は Vue 3 のものとは全く異なる

@vue/composition-api での readonly() の実装2を確認すると、引数で受け取ったオブジェクトの型を DeepReadonly 化して返しているだけであることがわかります。

そのため TypeScript による型チェックをすり抜けてしまった場合3、Vue 3 の readonly() とは異なり状態の変更ができてしまいます:

// Vue 2
import { reactive, readonly } from '@vue/composition-api';

const original = reactive({
  countA: 0,
  foo: {
    countB: 0,
  },
});
const copy = readonly(original);

original.countA++;
copy.countA++; // ブラウザのコンソール上に警告が出ない
original.foo.countB++;
copy.foo.countB++; // ブラウザのコンソール上に警告が出ない

console.log(original.countA); // 2
console.log(copy.countA); // 2
console.log(original.foo.countB); // 2
console.log(copy.foo.countB); // 2

shallowReadonly() は Vue 3 のものとほぼ同じように使える

shallowReadonly() は Vue 3 のものと同様にリードオンリーになる範囲がオブジェクトの第1階層の値に限定されますが、Vue 3 のものとほぼ同じように使うことができます。

Vue 2 では場合によっては readonly() よりも shallowReadonly() を使った方が良いことがあります。
例えば、各プロパティの値がすべてプリミティブ型であるようなオブジェクトには shallowReadonly() を用いることで readonly() よりも確実に状態の変更を防ぐことができます:

// Vue 2
import { reactive, readonly, shallowReadonly } from '@vue/composition-api';

// 各プロパティの値がすべてプリミティブ型(string | number | boolean)である
const original = reactive({
  text1: '',
  text2: '',
  text3: '',
  number1: 0,
  number2: 0,
});

// Not good
const copy1 = readonly(original);

// Better
const copy2 = shallowReadonly(original);


Vue 2 の shallowReadonly() にはできないことについて

@vue/composition-api での shallowReadonly() の実装4を確認すると、引数で受け取ったオブジェクトの(第1階層の)キーでループを回し5、別途定義したオブジェクトに対して同じキーを持つプロパティを定義する6実装となっていることがわかります。


そのため shallowReadonly(obj) 実行時に obj が持っているプロパティの値に限ってリードオンリーとすることができます。
// Vue 2
import { reactive, shallowReadonly } from '@vue/composition-api';

const original = reactive({
  countA: 100,
});
const copy = shallowReadonly(original);

original.countB = 200;

console.log(copy.countA); // 100
console.log(copy.countB); // undefined
// Vue 3
import { reactive, shallowReadonly } from 'vue';

const original = reactive({
  countA: 100,
});
const copy = shallowReadonly(original);

original.countB = 200;

console.log(copy.countA); // 100
console.log(copy.countB); // 200



  1. 2020/12/27 時点でリリースされていない Vue 3 の IE11 互換ビルドを利用すると Vue 3 の readonly(), shallowReadonly() の挙動が本記事で想定しているものと異なるものとなる可能性があります 

  2. @vue/composition-api v1.0.0-beta.22 での readonly() の実装: https://github.com/vuejs/composition-api/blob/v1.0.0-beta.22/src/reactivity/readonly.ts#L42-L46 

  3. 特に Vue では <template> 上の v-model など型チェックが効きにくい場所があったりします 

  4. @vue/composition-api v1.0.0-beta.22 での shallowReadonly() の実装: https://github.com/vuejs/composition-api/blob/v1.0.0-beta.22/src/reactivity/readonly.ts#L48-L97 

  5. for (const key of Object.keys(obj)) { ... } の部分 

  6. Object.defineProperty(readonlyObj, key, { ... }) の部分 

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

[Vue.js]Storeの値がcommit以外で変わっちゃった時の話

前書き

業務でNuxt.jsアプリの改修をしていて、

なんかバグ出てるやん
→ どうやらStoreの値中の配列の値がおかしいぞ
→ 変な値がcommitされているんだな
→ commit値は正常だな・・
→ あ、変なところでまたcommitが呼ばれちゃってるんだな!
→ commitは(正常時の)1回しかされていないぞ・・
→ 

なことがあったので、これを解決した時の話を書いてみます。

体験談

今回のポイントは、異常値を示した値の型が配列と言う点。

最初はVue初級者が故に、
storeの値はcommitから以外で変わり得ない、と言う前提はあったため、
VueXの仕様的に誤った使い方しているんじゃ、、と的外れなあたりをつけてVue周りを調べてました。

そんな時、ふと配列で思い出したのが、
配列は参照型やん、です。

なので、storeから取り出した配列を直接いじってる部分がないかと言う方針で調査を進めました。

そして見つけました。

lodash(JSライブラリ)の_.remove()メソッド

※removeメソッドについてはこちらの記事がとても参考になります。

この処理の前後のstoreの値を確認し、確信しました。

この処理周りを改善し、無事バグ解決。

参照型とは

超ざっくり言うと、値が置いてある場所、のこと。
Java習いたてでよく注意点として出て来ます。

ありがちな事象は以下

ある変数を別の変数にコピーして、値2個できたやん、とか思って片方を変更する。
でも参照型の場合は実際には場所を指しているので、コピーされたのは場所情報だけ、変更されたのはその場所にある値である。
つまり同じ場所を指しているもう一方の変数も、一緒に値が変わってしまう。

文面で起こすの辛いので実例↓

// JSの場合

var a = [1,2,3,4,5]; // 配列定義。

var b = a; // 変数をコピー。実際は配列のある場所だけコピーされる。

b.pop(); // bの末尾削除

console.log(a); // [1,2,3,4]
console.log(b); // [1,2,3,4]

// aも削除されちゃった

まとめ

配列が参照型、と言うのは実際にその類のバグに遭遇しないと意識しないと思うので、
体験談を書き記してみました。

これがあってから改めて意識するようになったのが、

  • Vuexのstoreの中身がcommit以外から変更されるパターンもある(ReactのReduxなどでも同様だと思う)
  • storeなど固定値として保持されている配列を直接いじらない
  • 配列の中身に関するバグがあったら、直接操作を行っていないかを疑う

です。

ちなみにどうしてもいじる必要がある場合は、
例えばlodashの_.cloneDeep()と言うメソッドを使うことで、
配列を完全複製し、それを使用する方法などが回避策になるかなと思います。

この記事を見て、
うわ、こんなバグもありえるのか!、と感心していただけたり、
自分もあったわw、と共感していただける人がいたら幸いです。

参考

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

vue cli, Netlify, Functionsの初期設定

vue-cliでアプリ作ってNetlifyに上げる。Fuctionsも使いたい。そんな備忘録。
環境はWin10上でWSL2(Ubuntu)です。

  1. $ sudo npm install -g --force @vue/cli
    1. いつのだかわからないvue-cliが入ってたので、--forceで上書き
  2. $ vue create my-application
  3. $ cd my-application
  4. $ git init
  5. ブラウザでGitHubにリポジトリ作成(README.mdの自動生成とかはしなかった。vue cliのと被るし。)
  6. my-applicationディレクトリ直下で以下を実施(GitHubの画面に表示されいる通りに実施。mainブランチにするような手順になってたがmasterのままにした。)
    1. $ git remote add origin git@github.com:<アカウント名>/<リポジトリ名>.git
    2. $ git push -u origin master
  7. ブラウザでNetlifyでNew site from Gitとかそんな感じのボタンから当該リポジトリを追加
    1. Can’t see your repo here? Configure the Netlify app on GitHub.とか書いてあってリンクになってるのでそこから結び付けたいリポジトリを許可する手順も必要。
    2. あとはよしなに
  8. 完了的なのがでるので、以下の場所の矢印のとこをクリックするとVueのサンプル画面がでる。ここまででサイトのデプロイはOK。 image.png
  9. Functionsも設定していきましょう。
  10. コンソールに戻って、$ cd my-application
  11. $ vue add netlify-lambda
  12. package.jsonbrowserslistから"not dead"の行を削除。←後述のエラーが出たので。
  13. $ npm run build && npm run serve
  14. ブラウザでhttp://localhost:9000/helloにアクセスするといい感じに見える image.png
  15. コンソールに戻って、serveをCtrl+cで止める
  16. .gitignore/lambdaを加える
  17. netlify.tomlcommandyarn buildからnpm run buildにする←デプロイしたときにyarnがないというエラーになったので(汗
  18. $ git add . && git commit -m "add functions" && git push
  19. ブラウザでNetlifyを確認しデプロイ状況を確認。https://app.netlify.com/sites/Netlify上のアプリ名/deploys
  20. publishedになったらhttps://Netlify上のアプリ名.netlify.app/.netlify/functions/helloにアクセスしてみる。ローカルでみたハロワ的なメッセージでたら完了、おつかれさんでした。

よくわからん現象ズ

ビルドエラー

BrowserslistError: [BABEL] /opt/build/repo/src/lambda/hello.js: Unknown browser query `dead` (While processing: "/opt/build/repo/node_modules/babel-preset-env/lib/index.js")

ローカルでのビルド時に発生したのでpackage.jsonbrowserslistから"not dead"の行を削除。
それで再実行するとエラーはなくなった。
その後もう一度"not dead"を追加したらエラーでなくなった。
それでpushしたところ、Netlify側でも同様のエラーが出た。(functionsのデプロイが失敗してた)
なのでやっぱり"not dead"を削除してpush。
そしたらNetlify側でもビルド成功した。functionsにもアクセスできるようになりました。

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

そうだ、firebaseで、自動でログイン、ログアウトを実行してみよう!

最近、ユーザー認証でfirebaseを使用しているのですが、何と言っても凄いなと感じました。

例えば、Facebookとの連携を取る際に、ユーザーが重複しているかの確認も自動でしてくれますし、メール送信機能もGmailを使って送信することができるんですよ。

これを全て1から実装するとなると手間はかかりますよね。。。

話は変わりますが、firebaseでupdateEmail(),upadatePassword()という関数があるのをご存じでしょうか?

firebaseに触れたことがある方は恐らくご存じかと思います。

ふと、この関数を実行したところ、firebase側では変更されているのですが、Webサイト上では更新されていない!!!

これは困ったなと思い色々調べたところ、updateした後はログアウトをし、再度ログインしなきゃいけないらしい。

でもこれをユーザーにわざわざ操作させるなんてことはできない。

そこで、今回は、upadateした後に、自動でログアウトとログインを実行する方法を説明していきます!!!

また、メールアドレスやパスワードを変更する時、ユーザーの再認証が必要なのでこれも説明します。

そんなに難しくないので、是非学習の参考にしてください!

それでは順を追って説明します。(メールアドレス変更での実装となります。パスワードを変更する時でも同じく使えます。)

パスワードの入力

下記のように、ユーザーにパスワードの入力をしてもらいます。

reAuth.vue
<template>
    <div class="reauth">
        <div class="form-wrapper">
        <h1>不正防止のためパスワードの入力をお願いします。</h1>
        <form>
            <div class="form-item">
            <label for="email">現在のメールアドレス</label>
            <input type="email" name="email" required="required" :value="beforeEmail" disabled="true">
            </div>
            <div class="form-item">
            <label for="email2">変更後メールアドレス</label>
            <input type="email" name="email2" required="required" :value="updateEmail" disabled="true">
            </div>
            <div class="form-item">
            <label for="password">パスワード</label>
            <input type="password" name="password" required="required" placeholder="パスワードを入力してください" v-model="password">
            </div>
            <div class="button-panel">
            <input type="button" class="button" value="変更する" @click="update">
            </div>
        </form>
        </div>
    </div>
</template>

<script>
import firebase from "firebase/app";
export default{
    props: ["updateEmail"],  //変更するメールアドレス
    name: "reAuth",
    data() {
        return {
            beforeEmail: this.$store.state.user.email,  //変更する前のメールアドレス
            password: "",                               //パスワード
        }
    },
}
</script>

再認証→ログアウト→ログインの実行

reAuth.vue
<script>
methods: {
        update() {
            let vm = this;
            const user = firebase.auth().currentUser;  //現在のユーザーを取得
            const credential = firebase.auth.EmailAuthProvider.credential(this.beforeEmail, this.password);
            //メールアドレスとパスワードでユーザーの確認
                user.reauthenticateWithCredential(credential)   //再認証
                .then(() => {
                    user.updateEmail(vm.updateEmail)                  //メールアドレスの更新
                    .then(() => {
                      firebase.auth().signOut()                 //変更し終えたら、ログアウトを実行
                      .then(() => {
                        firebase.auth().signInWithEmailAndPassword(vm.updateEmail, vm.password)  //ログアウトし終えたら、ログインの実行
                              .then((user) => {
                                  vm.$store.dispatch("login", user);  //Vuexのストア内のuserの書き換え
                                  vm.$router.replace({  //ページ遷移
                                    name: "User",
                                  })
                                  }
                              )
                      })
                    })
                    .catch((error) => {
                        alert(error);
                    })
                })
                .catch((error) => {
                  alert(error);
                })
        }
    },
</script>

このような流れで変更内容を反映することができます!!!

それぞれの処理が終わったら、.then(() => {})の中で実行することで、一連の動作を行えます。

この.then(() => {})で行わないと、例えばログアウトをし終えてないのにログインしてしまうという流れになるので、くれぐれも気を付けてください!

何かご不明な点がございましたら、コメントにてご報告ください。

以上、「firebaseで、自動でログイン、ログアウトを実行する方法」でした!!

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!

Thank you for reading

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

【Vue.js/Vuetify/Vuex】リアルタイム検索

概要

・ ポートフォリオでリアルタイム検索機能を実装したので、コメントつきのソースコードを紹介
・ 使用した技術はVue.js,Vuetify,Vuex
 ※ v-text-field のページは以下URL内にあり。
https://vuetifyjs.com/en/components/text-fields/#api
・ api経由でデータを取得し、ページネーション付きで表示する
・ 開発環境はVue-Cli

template
<v-layout>
      <v-flex2>
          <v-card>
              <v-card-title>
                  <v-text-field
                     label="検索する"
                     v-model="search">
                  </v-text-field>
              </v-card-title>
           </v-card>
      </v-flex>
</v-layout>
<v-layout v-for="list in getLists" :key="list.index">
//以下リストの内容が表示される
</v-layout>

computed内では、stateから取得したリストをgetListsで自分が入力した内容とマッチするリストになるようにフィルタリング。
フィルタリングしたリストをv-forループで表示させる。

script
data(){
 return : {
     search: "
  }
},
computed(){
  getLists(){
    const lists = this.$store.state.lists
      return lists.filter((list) => {
        return list.title.match(this.search)
      //search:検索欄に入力した内容
     })
   }
}

以下がgetListsから引き出したstateのリストの内容。

store(state)
lists:
[
    {
     id: "akdddgela22nad", 
     title: "FreeTalk in NewYork",
     date: "2017-09-29",
     location: "New York"},
    { 
     id: "akdbbraa5ffggg", 
     title: "FreeTalk in Paris",
     date: "2017-10-20",
     location: "Paris",
    }
//以下省略...
],

下記のように" || "を使用すれば、リストの中のあらゆるワードや数字を拾って検索も可能になる。

script
return list.title.match(this.search) || list.date.match(this.search) || 
list.location.match(this.search) 


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

リアルタイム検索【Vue.js/Vuetify/Vuex】

概要

・ ポートフォリオでリアルタイム検索機能を実装したので、コメントつきのソースコードを紹介
・ 使用した技術はVue.js,Vuetify,Vuex
 ※ v-text-field のページは以下URL内にあり。
https://vuetifyjs.com/en/components/text-fields/#api
・ api経由でデータを取得し、ページネーション付きで表示する
・ 開発環境はVue-Cli

template
<v-layout>
      <v-flex2>
          <v-card>
              <v-card-title>
                  <v-text-field
                     label="検索する"
                     v-model="search">
                  </v-text-field>
              </v-card-title>
           </v-card>
      </v-flex>
</v-layout>
<v-layout v-for="list in getLists" :key="list.index">
//以下リストの内容が表示される
</v-layout>

computed内では、stateから取得したリストをgetListsで自分が入力した内容とマッチするリストになるようにフィルタリング。
フィルタリングしたリストをv-forループで表示させる。

script
data(){
 return : {
     search: "
  }
},
computed(){
  getLists(){
    const lists = this.$store.state.lists
      return lists.filter((list) => {
        return list.title.match(this.search)
      //search:検索欄に入力した内容
     })
   }
}

以下がgetListsから引き出したstateのリストの内容。

store(state)
lists:
[
    {
     id: "akdddgela22nad", 
     title: "FreeTalk in NewYork",
     date: "2017-09-29",
     location: "New York"},
    { 
     id: "akdbbraa5ffggg", 
     title: "FreeTalk in Paris",
     date: "2017-10-20",
     location: "Paris",
    }
//以下省略...
],

下記のように" || "を使用すれば、リストの中のあらゆるワードや数字を拾って検索も可能になる。

script
return list.title.match(this.search) || list.date.match(this.search) || 
list.location.match(this.search) 


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

【解決!】Vue-Cliをインストール...できない!

状況

・Vue-Cliを使った本格的なアプリ開発をするためにVue-Cliをインストールしようとした
・過去にもVue-Cliをインストールして使った経験あり!
・コマンドプロンプトを開いて「いざ!やるぞ!」と思っていた矢先、早速出鼻をくじかれた...という話です。

起こったこと①

・コマンドプロンプトで下のようにVue-Cliをインストール

npm -g install vue-cli

・以下エラーが発生

npm WARN deprecated vue-cli@2.9.6: This package has been deprecated in favour of @vue/cli
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm ERR! code EEXIST
npm ERR! path C:\Program Files (x86)\Nodist\bin\node_modules\vue-cli\bin\vue
npm ERR! dest C:\Program Files (x86)\Nodist\bin\*vue.cmd*
npm ERR! EEXIST: file already exists, cmd shim 'C:\Program Files (x86)\Nodist\bin\node_modules\vue-cli\bin\vue' ->'C:\Program Files (x86)\Nodist\bin\vue.cmd'
npm ERR! File exists: C:\Program Files (x86)\Nodist\bin\vue.cmd
npm ERR! Remove the existing file and try again, or run npm
npm ERR! with --force to overwrite files recklessly.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Owner\AppData\Roaming\npm-cache\_logs\2020-12-24T15_55_11_169Z-debug.log

対策①

ポイントは5行目~11行目。
要約すると
「既にインストールしているデータがある時のエラーだよ!」(5行目)
「具体的にはProgram Files (x86)\Nodist\bin\vue.cmdのことだよ!」(8~9行目)
「このfileを消してもう一回やってみて!」(10行目)
とある。
・冒頭書いた通り、一度Vue-Cliはインストールしたことあるので、その時インストールしたファイルたちが残っていた。
 どうもそのファイルが今回のインストールを邪魔している、らしい。
・なので、一旦Program Files (x86)\Nodist\binにあるvue.cmdを消して再度npm -g install vue-cliを実行

起こったこと②

・開発へ進める!と思ったら、またしても以下エラー発生

npm WARN deprecated vue-cli@2.9.6: This package has been deprecated in favour of @vue/cli
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm ERR! code EEXIST
npm ERR! path C:\Program Files (x86)\Nodist\bin\node_modules\vue-cli\bin\vue
npm ERR! dest C:\Program Files (x86)\Nodist\bin\vue
npm ERR! EEXIST: file already exists, cmd shim 'C:\Program Files (x86)\Nodist\bin\node_modules\vue-cli\bin\vue' -> 'C:\Program Files (x86)\Nodist\bin\*vue*'
npm ERR! File exists: C:\Program Files (x86)\Nodist\bin\vue
npm ERR! Remove the existing file and try again, or run npm
npm ERR! with --force to overwrite files recklessly.

・さっきと同じようなエラー。よくよく見ると...

npm ERR! EEXIST: file already exists, cmd shim 'C:\Program Files (x86)\Nodist\bin\node_modules\vue-cli\bin\vue' -> 'C:\Program Files (x86)\Nodist\bin\vue'
npm ERR! File exists: C:\Program Files (x86)\Nodist\bin\vue

・消すべきファイルの名前が変わっている。

対策②

・なるほど。過去インストールしたいくつかのファイルが邪魔して今回インストールできないわけだ、と悟り/同じく今回もvueファイルを消す。
・結局、「消す⇒npm -g install vue-cli実行⇒エラー(○○を消してね!)⇒消す⇒...」を10回ほど繰り返した
 ○○に指定されて消したファイルは以下の通り
vue-cli.png
・こんなに何回もエラーを頻発した理由は、これらのファイルたちはnpm -g install vue-cliを実行するとまた最新verが生まれてくるということ。
で、その生まれたファイルたちがエラーの原因となってしまうこともあった。
・結論、上図のファイルたちを一気に消してnpm -g install vue-cliで正常にインストール完了!

エラーの原因

・今回のエラーの原因はどうも先ほどお見せしたファイルたちのインストールした日時らしい。
・元々インストールしたファイルたちは2020/12/20にインストールしたモノだったので、これがある限りエラーを発生しまくった。
・そこで上記のようにファイルたちを一気に消してnpm -g install vue-cliを実行し最新版のファイルが作成され、うまくいった!という流れ。

最後に

大したことではないですが、ググって同じようなエラーコード出ている方々はいらっしゃいましたが、ほとんどの方はMacユーザーの方でした。
そういった方の対策案を参考にした自分はこのエラーも出していました。

スクリーンショット 2020-12-26 205610.png

ここで初めてWindowユーザーである自分は"sudo"や"rm"などのLinuxが使えない、ということを学びました。
参考までに。

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