20210329のvue.jsに関する記事は6件です。

【Vue.js】Firebase Authenticationを使用してユーザ名を表示させる改

【Vue.js】Firebase Authenticationを使用してユーザ名を表示させる改

前回の記事から以下の観点で修正した

  • vuexのstoreでメソッド管理
  • firebaseの環境設定を別ファイルに切り出す

ソースコード

vuexのstoreでメソッド管理

vueファイル側でactions呼び出す

<template>
  <div class="signup">
    <h1>新規登録画面</h1>
    <table>
      <tr>
        <td>ユーザ名</td>
        <td><input type="text" placeholder="userName" v-model="username"></td>
      </tr>
      <tr>
        <td>メールアドレス</td>
        <td><input type="text" placeholder="E-mail" v-model="email"></td>
      </tr>
      <tr>
        <td>パスワード</td>
        <td><input type="password" placeholder="Password" v-model="password"></td>
      </tr>
    </table>
    <button class="button" @click="signUp">新規登録</button>
      <router-link to="/signin">ログインはこちらから</router-link>
  </div>
</template>

<script>
/* eslint-disable */

export default {
  name: 'Signup',
  data () {
    return {
      username: '',
      email: '',
      password: ''
    }
  },
  methods: {
    signUp () {
      this.$store.dispatch('signUp', {
        username: this.username,
        email: this.email,
        password: this.password,
      })
    },
  }
}
</script>

action経由でmutatinosを実行し、stateの変更を行う
※非同期処理やstateの変更はaction経由での実装が望ましい
公式より

・アクションは、状態を変更するのではなく、ミューテーションをコミットします。
・アクションは任意の非同期処理を含むことができます。

store/index.js
/* eslint-disable */
"use strict"

import Vue from 'vue'
import Vuex from 'vuex'
import firebase from 'firebase'
import router from '@/router'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        username: '',
        email: '',
        password: ''
    },
    mutations: {
        AddToState: function (state, payload) {
            state.email = payload.email
            state.password = payload.password
            state.username = payload.username
        }
    },
    actions: {
        signUp: function (context, payload) {
            firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
                .then(() => {
                    firebase.auth().currentUser.updateProfile({
                    displayName: payload.username,
                    },)
                .then(() => {
                    context.commit('AddToState', payload)
                })
                .then(() => {
                    router.push('/')
                })
                })
                .catch(error => {
                    alert(error.message)
                })
        },
    },
});

export default store

firebaseの環境設定を別ファイルに切り出す

firebaseの環境設定を別ファイルに切り出す

firebase.config.js
/* eslint-disable */
const config = {
    apiKey: "AIzaSyDeNuzV_lTclsv8iYhfH-K_sV9cNYOHUs4",
    authDomain: "tipping-app-be890.firebaseapp.com",
    projectId: "tipping-app-be890",
    storageBucket: "tipping-app-be890.appspot.com",
    messagingSenderId: "523721486484",
    appId: "1:523721486484:web:0db73f6f5d192b894f8481",
    measurementId: "G-TF5NZJT4LR"
  };

export { config }

環境設定のオブジェクトをmain.jsでimportし、読み込む

main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import firebase from 'firebase'
import store from './store'

Vue.config.productionTip = false

/* eslint-disable */
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
import { config } from '@/utilities/firebase.config';

firebase.initializeApp(config);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

参考

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

【Vue.js + TypeScript】autonakaでフリガナを自動的に別フィールドに入力させる

はじめに

  • Vue.js + TypeScriptを使い、ユーザー名入力フォームなどで日本語入力をした際に、自動で別フィールドにふりがなorフリガナを入力できるようにしました。

実装コード

<template lang="pug">
label 氏名
input#last_name(name='last_name' type="text" placeholder="山田" @input="handleLastNameInput")
input#first_name(name='first_name' type="text" placeholder="一郎" @input="handleFirstNameInput")

label フリガナ
input#last_name_furigana(name='last_name_furigana' type="text" placeholder="ヤマダ")
input#first_name_furigana(name='first_name_furigana' type="text" placeholder="イチロウ")
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import * as AutoKana from 'vanilla-autokana';

let autokanaLastName: any;
let autokanaFirstName: any;

@Component
export default class Hoge extends Vue {
  @Prop() userInfo!: {
    first_name: string,
    last_name: string,
    first_name_furigana: string,
    last_name_furigana: string
  };

  mounted() {
    autokanaLastName = AutoKana.bind('#last_name', '#last_name_furigana', { katakana: true });
    autokanaFirstName = AutoKana.bind('#first_name', '#first_name_furigana', { katakana: true });
  }

  handleFirstNameInput() {
    this.userInfo.first_name_furigana = autokanaFirstName.getFurigana();
  };
  handleLastNameInput() {
    this.userInfo.last_name_furigana = autokanaLastName.getFurigana();
  };
}
</script>

<style lang="scss">
</style>

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

vuexのgettersでstateをフィルタリングする方法

stateにあるJSONデータ、もしくはactionsで持ってきたデータをフィルタリングする方法。
今回はそもそもバックエンド側でフィルタリングしようねという話になったので、自分の環境では使用しなかった。
でもせっかく組んだし、もったいないので共有します(あんまり使い道は無いだろうけど・・・)

export const getters = {
    getFilteringList: (state) => (query) => {
      // queryの形式を[{key:'',value:''}...]に変換する
      let conversion = Object.entries(query).map(([key, value]) => ({'key': key, 'value': value}))
      // 条件に合致したデータを返す関数を定義(every関数なので、全てに合致する必要がある)
      function isMatchToAllConditions(data, conditions){
        return conditions.every(c => data[c.key] == c.value)
      }
      // null以外の要素を取り出す
      const conditions = conversion.filter(q => q.value && q.key)
      // フィルターをかける
      const searched = state.data.filter(list => {
        return isMatchToAllConditions(list, conditions)
      })
      // 出力
      return searched
    }
  }

getFilteringListにはコンポーネント側でqueryを投げてあげる必要がある。

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

DjangoのQuerySetをJSON形式に変換してVue.jsで受け取る

はじめに

Vue.jsが気に入ってしまったので、DjangoのQuerySetをJSON形式に変換してVue.js内で扱える様にしました。忘れっぽい自分のために、備忘録的に残します。

前提条件

Django: version 3.1.7
Vue.js: version 2.6.12(CDN)
axios等は使用しません

コード

Djangoにアプリ追加したところで各モジュールを書きかえます。

urls.py
from django.urls import path
from . import views

app_name= 'app'

urlpatterns = [
    path('list/', views.ListData, name= 'list'),
]
models.py
import uuid

from django.db import models

class Book(models.Model):

    id= models.UUIDField(primary_key=True, default= uuid.uuid4, editable= False)
    title= models.CharField(verbose_name= 'タイトル', max_length=40)

ここでは、JSONが知らない特別なタイプの型をとるために、idをUUIDにしておきます。

views.py
import json, uuid

class ListDataView(ListView):
    template_name= "app/listdata.html"
    model= Book

    def get_context_data(self, **kwargs):
        def cnvDataToJson(object):
            if(isinstance(object, uuid.UUID)):
                return str(object)

        context= super().get_context_data(**kwargs)
        books= self.object_list.values('id', 'title')
        bookList= json.dumps(list(books), ensure_ascii=False, default=cnvDataToJson)
        context["bookList"]= bookList

        return context

ListData= ListDataView.as_view()

Bookモデルからデータを得る時に、values()クエリを使って「辞書のリスト」に変換しておきます。
その後、この辞書リストをjson.dumps()でJSON形式の配列に変換しますが、default=cnvDataToJsonのところで、jsonが知らない型を文字列に変換してあげるためのコールバックを設定します。
なお、ensure_ascii=Falseは文字バケ対策です。

listdata.html
 <div id="v-app">
        <button @click="get_books()">GetBooks</button>
        <div>
            <table>
                <tr>
                    <th>No.</th>
                    <th>タイトル</th>
                </tr>
                <tr v-for="(book, index) in books">
                    <td>[[index]]</td>
                    <td>[[book.id]]</td>
                    <td>[[book.title]]</td>
                </tr>
            </table>
        </div>
    </div>

    <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
    <script>

        Vue.options.delimiters = ['[[',']]']

        const vm = new Vue({
            el: "#v-app",
            data: function(){
                return{
                    books:[],
                }
            },
            methods:{
                get_books: function(){
                    this.books.splice(0);
                    this.books= {{bookList|safe}};  //Djangoから受け取るデータを配列にセットする。
                },
            },
        })
    </script>

Vue.options.delimiters = ['[[',']]']
DjangoとVue.jsはデフォルトではテンプレート内で使用する{{ }}が衝突してしまうため、Vue.js側でデリミタを再定義してあげます。

this.books= {{bookList|safe}}
JSON配列となったデータをVue.js(javaScript)側の配列に移します。このときsafeでフィルタすることで、エクケープ処理をします。(細かいことは解りませんが、これがないとダメでした。)

あとがき

javaScriptからDjangoの{{ }}を扱う時にずっと" "で囲うことをしていたために欲しい結果が得られずにいました。
Djangoのテンプレートなので" "は要らないことが判りました。
あと、Htmlタグに仕掛けをすることが出きるVue.jsって素晴らしく便利だと思った。(CLIの方は敬遠します)

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

【laravel】vue.jsを導入したら、bootstrap動かなくなったよ

はじめに

laravelにvue.jsを導入が完了し、喜んでいた最中に発生した、boostrapのモーダルが動いていない問題。

これを解決するのに詰まったので、解決策を記録致します!

前提

環境

PHP 7.4.16
Laravel 6.20.17
mysql 8.0.23
nginx 1.18.0

コード

app.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>
    @yield('title')
  </title>
  <!-- Font Awesome -->
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
  <!-- Bootstrap core CSS -->
  <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
  <!-- Material Design Bootstrap -->
  <link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.8.11/css/mdb.min.css" rel="stylesheet">
  <script src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script>
</head>

<body>
  @include('nav')
  <div id="app">
    @yield('content')
  </div>
  <script src="{{ mix('js/app.js') }}"></script>  
  <!-- JQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <!-- Bootstrap tooltips -->
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/umd/popper.min.js"></script>
  <!-- Bootstrap core JavaScript -->
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
  <!-- MDB core JavaScript -->
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.8.11/js/mdb.min.js"></script>
</body>

</html>
webpack.mix.js
const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js').version();

app.js
import './bootstrap'
import Vue from 'vue'
import LocationTagsInput from './components/LocationTagsInput'

const app = new Vue({
  el: '#app',
  components: {
    LocationTagsInput,
  }
})

解決法

app.blade.phpから下記をコメントアウトする

  <!-- JQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

原因

bootstrap.js
try {
    window.Popper = require('popper.js').default;
    window.$ = window.jQuery = require('jquery');

    require('bootstrap');
} catch (e) {}

以降省略

上記箇所でも、jQueryを呼んでいたので、app.blade.phpとダブルで呼び出していたことが原因でした!

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

【環境構築】electron-vue と node_addon_api を連携し、C++とVue.jsを使ってelectronアプリを開発する

この記事の用途

  • electron + vue.jsでモダンなデスクトップアプリ開発を行う
  • C++プログラムと連携する(活用例: 機械学習アプリなど、高速な計算が必要となる場面)
    • この記事では、環境構築に重点を置いて説明しています。

登場人物

  • electron: Webブラウザベースで動くデスクトップアプリ開発フレームワーク
  • Vue.js: フロントエンド開発フレームワーク
  • node_addon_api: javaScriptからC++資産を利用するためのフレームワーク
    • node_addon_apiを使ったことがない方は、こちらの記事 もご覧ください!

バニラelectron と electron-vue の違い

  • はじめに、バニラelectronとの違いを列挙する
    • ※ バニラelectronとは、特に拡張機能をインストールしておらず、画面を html, css, js で作成したものを指す
    • バニラってどういう意味?
バニラelectron electron-vue
メインプロセスファイル main.js src/background.js
レンダラープロセスファイル renderer.js src/main.js
electronBuilderの設定 package.jsonに記述 vue.config.jsに記述
出力先フォルダ dist dist_electron
.nodeファイルの読み込み bindings node-loader

使用するテンプレート

electron-vueのインストール

electron-vueで C++ライブラリを使用するための準備

node-addon-apiをインストールする

  • C++ソースのビルド環境として、node_addon_apiを利用する。

  • node_addon_apiを使って、C++ファイルをコンパイルする

    • コンパイルに成功すると、プロジェクトのルートディレクトリ内に build/Releaseフォルダが生成され、そこに.nodeファイルが生成される
    • ※ もし、コンパイルしたC++ファイルがOpenCVなどのDLLに依存している場合、build/Release内に .dllファイルを設置しないといけません。
  • 以降、node-addon-apiでビルドしたC++ライブラリを .nodeモジュールと呼ぶことにします。

    • 以下に .nodeモジュールを使用するための手順を示します。

vue.config.jsの作成

nodeIntegrationの有効化

builderOptionsセクションの作成

  • 作成したvue.config.js内に"builderOptions"セクションを追加し、package.json内の "build" セクション内の項目を移動する

    • ※ package.json 内に "build" セクションがあると、下記のようなエラーとなるため

      error
      InvalidConfigurationError: 'build' in the application package.json (\package.json) is not supported since 3.0 anymore. Please move 'build' into the development package.json
      
  • "builderOptions"内に、"extraResources"セクションを設けて、node_addon_apiでビルドした.dllと.node拡張子を登録する

    • これにより、dist-electron/win-unpacked/resources フォルダ内(※ windowsの場合)にビルドしたファイルが転送され、electron側で読み込めるようになる

      vue.config.js
      "extraResources": [
          "./build/Release/*.node",
          "./build/Release/*.dll"
      ],
      

builderOptionsセクションの設定項目一覧

node-loaderをインストールする

  • node-addon-apiでビルドした.nodeファイルを読み込むために使用する(node-loader)

    • 初めに npm installを行う
      • npm install node-loader
  • vue.config.js内の pluginOptinonsセクション内に下記の記述を追加する

    vue.config.js
        pluginOptions: {
            // ---- ここから↓ ---- //
            target: 'node',
            node: {
                __dirname: false,
            },
            module: {
                rules: [
                    {
                        test: /\.node$/,
                        loader: 'node-loader',
                    },
                ],
            },
            // ---- ↑ここまで ---- //
            electronBuilder: {
                ...中略
            }
        }
    
  • ここまでの準備で、electron側から.nodeアプリを呼び出す準備ができた。

メインプロセスで .nodeモジュールを使用する

  • src/background.jsで以下のように読み込む。

    • __non_webpack_require__ 関数を使用し、.nodeファイルのパスを直接指定する
    • ※ バニラelectron で使用していた require("bindings")("addon")コマンドは使用できない

      background.js
          const path = require('path'); // pathモジュールインポート
          console.log("__dirname",__dirname); // Debug: ルートパスの表示
          // .nodeファイルのパスを直接指定
          var nodePath = path.dirname(__dirname) + '/build/Release/○○○.node';
          var addon = __non_webpack_require__(nodePath);
          var obj = new addon.○○○(); // nodeモジュールのインスタンス化
      
    • ※ ここでモジュールを読み込むことができるのは、vue.config.js内の "extraResourcesFiles" セクションで .nodeファイルと、.dllファイルを登録しているから。

レンダラープロセスで .nodeモジュールを使用する

  • preload.jsを経由して .nodeファイルを読み込む必要がある

preload.jsの作成

  • src/preload.jsを手動で作成する
  • vue.config.jsに以下の項目を追加する
vue.config.js
    pluginOptions: {
        nodeIntegration: true,
        preload: 'src/preload.js' // 追加
    }
  • background.jsのcreateWindow()関数内で下記を追加する
src/background.js
function createWindow() {
  // Create the browser window.
  const win = new BrowserWindow({
      webPreferences: {
          nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
          preload: path.join(__dirname, 'preload.js'), // 追加
      }
  })

preload.js内で .nodeモジュールを呼び出す

  • 呼び出し方は、 background.jsとほぼ同じ

    • 相違点は最後の1行。window.変数名 として登録することで、レンダラープロセスから利用できる
    preload.js
        const path = require('path'); // pathモジュールインポート
        console.log("__dirname", __dirname); // Debug: ルートパス
        var nodePath = path.dirname(__dirname) + '/build/Release/○○○.node';
        var addon = __non_webpack_require__(nodePath);
        var obj = new addon.○○○();
        window.obj = obj; // !重要: windowオブジェクトに紐付けることで、app.Vueから呼び出せる
    
  • App.vueから、preload.jsで呼び出したモジュールを利用する

    • windowオブジェクトから変数を参照する
    App.Vue
      var obj = window.obj; // windowオブジェクトから参照する 
      obj.funcA(); 
    
  • 参考にしたStackOverflow

    • ※ ゆくゆくはcontext-bridgeを使った方がセキュアだと思います。

その他Tips

よくあるミス

  • 関連するDLLを build/Releaseフォルダに置いていない
    • " build/Release/○○.node が見つからない" とのエラーが出たときは、DLLも確認すること

electron + vue で複数ページのアプリを作る方法

静的ファイル(assets, images)をコピーする方法

  • vue.config.js の builderOptions内に、extraFilesセクションを追加する

    vue.config.js
        "extraFiles": [
                    "images/*.png",
                    "config/**/.txt"
        ]
    

electron-vueで sass, scss を使う方法

レンダラープロセスから、dialogを利用する方法

  • background.js で画面を生成する際に、enableRemoteModule: trueオプションを追加する

    background.js
    new BrowserWindow({
        webPreferences: {
            enableRemoteModule: true, // 追加
         }
     });
    

リンク集

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