- 投稿日:2021-03-29T21:35:51+09:00
【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 storefirebaseの環境設定を別ファイルに切り出す
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/>' })参考
- 投稿日:2021-03-29T16:51:42+09:00
【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>
- 投稿日:2021-03-29T11:25:09+09:00
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を投げてあげる必要がある。
- 投稿日:2021-03-29T10:00:55+09:00
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.pyfrom django.urls import path from . import views app_name= 'app' urlpatterns = [ path('list/', views.ListData, name= 'list'), ]models.pyimport 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.pyimport 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の方は敬遠します)
- 投稿日:2021-03-29T09:44:03+09:00
【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.jsconst 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.jsimport './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.jstry { window.Popper = require('popper.js').default; window.$ = window.jQuery = require('jquery'); require('bootstrap'); } catch (e) {} 以降省略上記箇所でも、jQueryを呼んでいたので、
app.blade.php
とダブルで呼び出していたことが原因でした!
- 投稿日:2021-03-29T08:40:51+09:00
【環境構築】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の使用方法は こちらの記事 で紹介しています。
node_addon_apiを使って、C++ファイルをコンパイルする
- コンパイルに成功すると、プロジェクトのルートディレクトリ内に
build/Release
フォルダが生成され、そこに.nodeファイルが生成される- ※ もし、コンパイルしたC++ファイルがOpenCVなどのDLLに依存している場合、
build/Release
内に .dllファイルを設置しないといけません。以降、node-addon-apiでビルドしたC++ライブラリを
.nodeモジュール
と呼ぶことにします。
- 以下に .nodeモジュールを使用するための手順を示します。
vue.config.jsの作成
- はじめに、ルートディレクトリ(package.jsonと同階層)に
vue.config.js
を手動で作成するnodeIntegrationの有効化
vue.config.js内の
pluginOptinons
セクション内に下記の記述を追加するvue.config.jsmodule.exports = { pluginOptions: { electronBuilder: { pluginOptions: { nodeIntegration: true } } } }
- 注) nodeIntegration: true はブラウザ側でのネイティブアプリの実行が可能となるが、セキュリティリスクが高まる
builderOptionsセクションの作成
作成したvue.config.js内に"builderOptions"セクションを追加し、package.json内の "build" セクション内の項目を移動する
※ package.json 内に "build" セクションがあると、下記のようなエラーとなるため
errorInvalidConfigurationError: '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セクションの設定項目一覧
- vue.config.js内の builderOptions 内で設定できるセクション名は下記を参照のこと
node-loaderをインストールする
node-addon-apiでビルドした.nodeファイルを読み込むために使用する(node-loader)
- 初めに npm installを行う
npm install node-loader
vue.config.js内の
pluginOptinons
セクション内に下記の記述を追加するvue.config.jspluginOptions: { // ---- ここから↓ ---- // 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.jsconst 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.jspluginOptions: { nodeIntegration: true, preload: 'src/preload.js' // 追加 }
- background.jsのcreateWindow()関数内で下記を追加する
src/background.jsfunction 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.jsconst 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.Vuevar obj = window.obj; // windowオブジェクトから参照する obj.funcA();
- ※ ゆくゆくは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 を使う方法
npm install --save-dev sass-loader node-sass
- npm install 時にエラーが出たら... 古いバージョンを指定して再度インストールする
- 例:
npm install --save-dev sass-loader@10.1.1
- こちらが参考になる -> StackOverflow
レンダラープロセスから、dialogを利用する方法
background.js で画面を生成する際に、
enableRemoteModule: true
オプションを追加するbackground.jsnew BrowserWindow({ webPreferences: { enableRemoteModule: true, // 追加 } });リンク集
- ElectronでcontextBridgeによる安全なIPC通信
- __ non_webpack_require__ は、レンダラプロセスで使用できない
- electron + Reactでの開発も可能なようだ