- 投稿日:2021-01-15T23:47:17+09:00
難しく考えずに、簡単にfirebaseに画像をアップロードしよう!
今回は、firebaseのStorageを利用して、firebase上に画像をアップロードしていきます。
また、その画像を使ってユーザーのプロフィール画像(photoURL)に変更を反映させます。
内容的には、そこまで難しくないのでぜひご覧ください!
流れとしては以下のようになります。
1, 画像をアップロードするinputタグを作成
2, 画像をアップロードした際に、firebaseのStorageに保管(この時、userごとにフォルダを作成していきます)し、firebaseのユーザー情報を更新
3, アップロードする前の画像を破棄
4, firebaseのルール設定
5, Web上に反映このような流れになっております。
全部を理解しなくてもいいと思います。
しっかり流れを把握しつつ、一緒に説明を見ていきましょう!
1, 画像をアップロードするinputタグを作成
今回は、
<input type="file">
としてやっても良いのですが、僕の大好きなBuefyを用いて使っていきます。Buefyの使い方が分からないという方は、こちらの記事初心者必見!サイト制作は楽してなんぼ。CSSフレームワークBuefyの紹介!!に書いてあるので、ぜひ時間がある方は目を通してください。
App.vue<b-upload type="file" style="margin-top: 1rem" @change.native="uploadImage"> <a class="button is-info"> <b-icon pack="fas" icon="upload" size="medium" style="margin-right: 0.5rem; margin-bottom: 0.05rem; vertical-align: middle" ></b-icon> プロフィール画像を変更する </a> </b-upload>
@change.native
で画像がアップロードされたかを検知しています。inputの場合は
<input type="file" @change="uploadImage" />
でOKです。2, firebaseのストレージに保管し、firebaseのユーザー情報を更新
methodsにて
uploadImage
という関数を定義し、以下のように記述します。また、画像ファイルは、imagesフォルダにユーザーID(uid)ごとにファルダを作成し、そこに画像ファイルを格納します。
images/
├ uid/
│ └ image.jpgイメージとしてはこんな感じです。
ユーザー情報を更新するのには
updateProfile
を使用します。ここで、注意なのですがupdateProfileは
firebase.auth().currentUser
で取得したuserで行わないと更新されません。firebase.auth().onAuthStateChanged()
でやらないようにお願いします。ちなみに理由は分かりません!これらを踏まえて、以下の記述を参考に書いてください。
App.vue<script> methods: { async uploadImage(event) { event.preventDefault() //要素のデフォルトのイベントを無効 event.stopPropagation() //子要素のイベントが親要素にも伝播することを防ぐ const userStorageRef = firebase.app().storage().ref() // type="file"を指定されたinput要素のchangeイベントは「ファイルのリスト」を返す const file = event.target.files[0] // ファイルが存在しないか、ファイル形式が"image/*"ではないとき if (!file || !file.type.match(/image\/*/)) { alert('不適切なファイル形式です') return false } await userStorageRef // images/uid/に画像ファイルを保管 .child(`images/${this.user.uid}/${file.name}`) .put(file) .then(() => { // 保管した画像ファイルのURLを取得 userStorageRef .child(`images/${this.user.uid}/${file.name}`) .getDownloadURL() .then(async imageURL => { // ユーザーを取得 // 注意: firebase.auth().onAuthStateChangedでやらないように! const user = firebase.auth().currentUser await user .updateProfile({ photoURL: imageURL }) .then(async () => { // vuex store state userの情報更新 this.$store.dispatch('changeUserPhotoURL', imageURL) // これを行わいと変更内容が反映されない // また、一番最後に行う user.reload() }) }) }) } } </script>3, アップロードする前の画像を破棄
次に、変更する前の画像はもう使わないので、これを消去します。
firebaseのStorageには、ファルダにあるファイルを一括で消去する機能が携わっていません。なので、
listAll()
という関数を用いて、ファイルの配列を取得し、1個1個消去していきます。
また、新しい画像をアップロードする前に行うということにも注意してください!
※これよりも良いやり方を知っている方は、ぜひコメント欄にて教えて頂くと幸いです。App.vue<script> methods: { async uploadImage(event) { event.preventDefault() //要素のデフォルトのイベントを無効 event.stopPropagation() //子要素のイベントが親要素にも伝播することを防ぐ const userStorageRef = firebase.app().storage().ref() // type="file"を指定されたinput要素のchangeイベントは「ファイルのリスト」を返す const file = event.target.files[0] // ファイルが存在しないか、ファイル形式が"image/*"ではないとき if (!file || !file.type.match(/image\/*/)) { alert('不適切なファイル形式です') return false } // 追加 await userStorageRef .child(`images/${this.user.uid}`) .listAll() .then(result => { for (let i = 0; result.items.length; i++) { userStorageRef.child(`images/${this.user.uid}/${result.items[i].name}`).delete() } }) // ファイルがない場合はスルー(初期値はstorageに保存していないため) .catch(() => {}) } //ここまで await userStorageRef // images/uid/に画像ファイルを保管 .child(`images/${this.user.uid}/${file.name}`) .put(file) .then(() => { // 保管した画像ファイルのURLを取得 userStorageRef .child(`images/${this.user.uid}/${file.name}`) .getDownloadURL() .then(async imageURL => { // ユーザーを取得 // 注意: firebase.auth().onAuthStateChangedでやらないように! const user = firebase.auth().currentUser await user .updateProfile({ photoURL: imageURL }) .then(async () => { // vuex store state userの情報更新 this.$store.dispatch('changeUserPhotoURL', imageURL) // これを行わいと変更内容が反映されない // また、一番最後に行う user.reload() }) }) }) } </script>4, firebaseのルール設定
次に、Firebase Consoleの画面を開き、左側の「Storage」という項目を開いてください。
そして、「Rules」を開いてください。
今回のルール設定は、ユーザー本人かつ認証済みかつ画像ファイルであれば変更を行えるというルール設定を行います。
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /images/{uid}/{allPaths=**} { allow read, write: if request.auth.uid == uid && request.auth != null && request.resource.contentType.matches('image/.*') } } }
request.auth.uid == uid
:ユーザー本人かの確認
request.auth != null
:認証済みかの判断
request.resource.contentType.matches('image/.*')
:画像ファイルであるかの確認5, Web上に反映
後は、user情報を取得してWeb上に反映するだけです!
一応、書いておきますね。
App.vuefirebase.auth().onAuthStateChanged((user)) => { console.log(user.photoURL) })このようにしてユーザーの画像ファイルを更新できると思います!
最近、毎日知らないことだらけの連続で頭がパンクしそうです(笑)
でもめげずに頑張りたいと思います!
ぜひ皆さんも一緒に頑張りましょう!!
以上、「難しく考えずに、簡単にfirebaseに画像をアップロードしよう!」でした!
良かったら、LGTM、コメントお願いします。
また、何か間違っていることがあればご指摘頂けると幸いです。
他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!
Thank you for reading
- 投稿日:2021-01-15T23:31:31+09:00
【Vue.js】初めてのコンポーネント。Vueインスタンスを再利用。
index.html<div id="app"> <hello-component></hello-component> <hello-component></hello-component> <hello-component></hello-component> <hello-component></hello-component> <hello-component></hello-component> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <script> Vue.component('hello-component', { data: function() { return { number: 13 } }, template: '<p>Hello{{ number }}</p>' }) var app = new Vue({ el: '#app', }) </script>コンポーネントの中では、dataは関数である必要があるらしい。
Hello13 Hello13 Hello13 Hello13 Hello13
- 投稿日:2021-01-15T22:32:28+09:00
【Vue 3】vue-composableのuseVModelを利用して複数の値のv-modelの煩雑さを回避する
Vue 3の機能変更の一つとして、コンポーネントに対するv-modelが複数の値に対応するになりました。
機能的には、3.xから削除された.sync修飾子と同様のものです。親コンポーネントでの利用は、次のように直感的に理解できます。
App.vue<template> <app-form v-model.title="title" v-model.description="description" /> </template> <script lang="ts"> import { defineComponent } from 'vue' import AppForm from '@/components/AppForm.vue' export default defineComponent({ components: { AppForm, } }) </script>子コンポーネント側の記述は次のようになります。
AppForm.vue<template> <label>タイトル</label> <input :value="title" @input="$emit('update:title', $event.target.value)" /> <label>概要</label> <input :value="description" @input="$emit('update:description', $event.target.value)" /> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ props: { title: { type: String, required: false, default: '' }, description: { type: String, required: false, default: '' } } }) </script>何が煩雑か
子コンポーネント側から、親コンポーネントに対して値の変更を伝える必要があるのですが、
props
の値は直接変更することができないので子コンポーネントでは便利なv-model
ディレクディブを使うことができず、:value
と@input
に分けて記述する必要があります。さらに、親に変更を通知する手段として
$emit('update:title', $event.target.value)
のようにupdate:{v-modelの引数で渡した名前}
というイベント名をemitする必要があります。
似たような記述を何回も書く必要がありますし、update:{v-modelの引数で渡した名前}
というイベント名を使う構文はなかなか覚えられません・・・
機能として提供されているわけではなく、emitのイベント名での提供なのでインテリヘンスが効かないですし、タイポにも気が付きにくです。Composition APIでロジックを外だしできるようになったので共通関数にできないのか・・・と思ったらすでにありました。
vue-composableを使う
vue-composableは、Composition APIで使える便利な関数群をまとめらライブラリです。今回利用する
useVModel
以外にも、バリデーション・フォーマット・マウスイベントなど汎用性の高い機能が利用できます。まずはインストールしましょう。
# install with yarn yarn add @vue/composition-api vue-composable # install with npm npm install @vue/composition-api vue-composableuseVModel
useVModelは第一引数にpropsオブジェクト、第二引数にpropsのキーを受け取り、リアクティブなpropsのキーのコピーを返します。
const _title = useVModel(props, 'title')
useVModel()
で返された値をv-model
で利用すれば、それだけで親コンポーネントに変更を通知してくれます!AppFrom.vue<template> <label>タイトル</label> <input v-model="_title"/> <label>概要</label> <input v-model="_description"/> </template> <script lang="ts"> import { defineComponent } from 'vue' import { useVModel } from 'vue-composable' export default defineComponent({ props: { title: { type: String, required: false, default: '' }, description: { type: String, required: false, default: '' } }, setup (props) { const _title = useVModel(props, 'title') const _description = useVModel(props, 'description') return { _title, _description } } }) </script>
- 投稿日:2021-01-15T18:25:05+09:00
Nuxt.js(Vue)でイベントの構造化データ マークアップの書き方と例
Nuxt.js(vue)でイベントの構造化データ マークアップの書き方と例になります。
JSON-JDやmicrodataと言った書き方がありますが、本記事では、JSON-JDの例になります。Nuxt.js(Vue)でイベントの構造化データ マークアップの書き方
<script> export default { head() { return { __dangerouslyDisableSanitizers: ['script'], script: [ { innerHTML: `{ "@context": "http://schema.org", "@type": "Event", }`, type: 'application/ld+json' } ] } } } </script>headの中に記載していきます。
Nuxt.js(vue)でイベントの構造化データ マークアップの例
<script> export default { data() { return { name: 'demo', description: 'demo', img: 'https://demo.jp/demo.jpg' } }, head() { return { __dangerouslyDisableSanitizers: ['script'], script: [ { innerHTML: `{ "@context": "http://schema.org", "@type": "Event", "name": "${this.name}", "description": "${this.description}", "startDate": "2021-01-28T15:00+09:00", "endDate": "2021-01-28T18:00+09:00", "eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode", "eventStatus": "https://schema.org/EventScheduled" "location": { "@type": "VirtualLocation", "url": "https://demo.jp" }, "offers": { "@type": "Offer", "price": "0", "priceCurrency": "yen", "url": "https://demo.jp", "availability": "http://schema.org/InStock" }, "performer": { "@type": "PerformingGroup", "name": "${this.name}" }, "organizer": { "@type": "Organization", "name": "demo", "url": "https://demo.jp" }, "image": "${this.image}" }`, type: 'application/ld+json' } ] } } } </script>上記がNuxt.js(Vue)イベントの構造化データ マークアップの例になります。
構造化データについては、下記が参考になります。
https://developers.google.com/search/docs/data-types/event?hl=ja
- 投稿日:2021-01-15T14:57:47+09:00
Jestで同一ファイル内で異なる振る舞いのモックを使用したい場合(axios)
初めに
メモ書きようです。
ざっくりと書いていますのでご了承ください。同一ファイル内で異なる振る舞いのモックを使用したい場合
例えば以下のようなAPIがあったとします。
test.tsasync hoge(): Promise<Hoge> { const res = await $axios.$get('/hoge'); } async fuga(): Promise<Fuga> { const res = await $axios.$get('/fuga'); }異なる振る舞いのモックを作成する場合は以下のように書けます。
test.spec.tsimport { $axios } from '@/store/utils/api.ts'; jest.mock('@/store/utils/api.ts', () => ({ $axios: { $get: jest.fn(), } })); describe('Test', () => { test('hoge', async () => { ($axios.$get as jest.Mock).mockImplementation(() => Promise.resolve({ ~ })); }); await hoge() }); describe('Test', () => { test('fuga', async () => { ($axios.$get as jest.Mock).mockImplementation(() => Promise.resolve({ ~ })); }); await fuga() });
- 投稿日:2021-01-15T14:33:47+09:00
pageとcomponentのやりとり
$emit
componentからpageへ値を渡す
pages/index.vue<template> <div> <div> {{ count }} </div> <child @eventName="parentMethod" /> </div> </template> <script> import Child from '@/components/child' export default { components: { Child }, data: () => ({ count: 0 }), methods: { parentMethod(count) { this.count = count } } } </script>components/child.vue<template> <div> <button @click="sendParent">送信</button> </div> </template> <script> export default { data: () => ({ clickCount: 0 }), methods: { sendParent() { this.$emit('eventName', ++this.clickCount) } } } </script>$refs
pageでcomponentの関数を呼ぶ
pages/index.vue<template> <div> <div> <button @click="doChildMethod">実行</button> </div> <child ref="child" /> </div> </template> <script> import Child from '@/components/child' export default { components: { Child }, methods: { doChildMethod() { this.$refs.child.countUp() } } } </script>components/child.vue<template> <div> {{ clickCount }} </div> </template> <script> export default { data: () => ({ clickCount: 0 }), methods: { countUp() { this.clickCount++ } } } </script>
- 投稿日:2021-01-15T10:01:49+09:00
なぜだ!?actionsの引数で、どうしてもundefiendになってしまった時の話
皆さんこんにちは!
今回は、エラー備忘録として書いていきます。
同じエラーに苦しんでいる方の参考になればなと思います。
まず、初めに以下の二つのコードを見ていただきたいと思います。
sotre/index.jschangeUserPhotoURL({ commit }, {updatePhotoURL}) { commit('changeUserPhotoURL', updatePhotoURL) },sotre/index.jschangeUserPhotoURL({ commit }, updatePhotoURL) { commit('changeUserPhotoURL', updatePhotoURL) },実行結果は
{updatePhotoURL}
はundefiend
updatePhotoURL
にはしっかりと値は受け取れてます。なぜ、このような結果になるのかは分かりません。。。
分かる方がいたら、ぜひコメント欄にて教えて頂くと幸いです。
- 投稿日:2021-01-15T10:01:23+09:00
webpack Vue.js TypeScript を使った環境構築まで (WSL)
概要
サービスを作るにあたって、Vue.js+TypeScriptでさくっと作れないか模索する準備として、環境構築したので
まとめてみました。調べながらやっており、手順としては冗長。やりたいこと
JavaScriptとWebサーバーだけで良い感じに開発する アプリサーバーは無し
前提環境
- Ubuntu 18.04.2 LTS
- node v12.13.1
- yarn 1.19.2
- Apache/2.4.29 (Ubuntu)
リポジトリ
ディレクトリ構成
この記事時点での最終は下記になる。
Apacheのルートディレクトリを public 配下としておく nginxでも何でもいいが. ├── .babelrc ├── .browserslistrc ├── .gitignore ├── package.json ├── public │ ├── index.html │ └── js │ └── app.js ├── src │ ├── Hello.vue │ └── app.ts ├── tsconfig.json ├── webpack.config.js └── yarn.lock
HTML作成
こんな感じで作成し、ブラウザで表示させる jsはまだない
public/index.html<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>TEST</title> <script src="js/app.js"></script> </head> <body> <div id="app">test app</div> </body> </html>yarn初期化
yarn init -y
package.jsonが自動で作成される。
package.json{ "name": "test5", "version": "1.0.0", "main": "index.js", "license": "MIT" }webpack準備
yarnによるwebpackのインストール
yarn add --dev webpack webpack-clipackage.json{ "name": "test4", "version": "1.0.0", "main": "index.js", "license": "MIT", "devDependencies": { "webpack": "^5.13.0", "webpack-cli": "^4.3.1" } }node_modules というディレクトリが作られ、webpack利用に必要なパッケージがインストールされる。
これらの詳細の情報は、同時に作成されたyarn.lockに記録される。テスト用のjsの準備
src/app.jslet test = ()=> {alert("webpack test");}; test();webpackの設定ファイル準備
webpack.config.jsconst path = require('path'); const env = process.env.NODE_ENV || 'development'; module.exports = { entry: './src/app.js', output: { filename: 'app.js', path: path.resolve(__dirname, 'public/js'), }, mode: env, }webpack実行
npxとは、パッケージ管理しているnodeモジュールを簡単に実行できる仕組み
node_modules/.bin 以下の実行ファイルを実行できる。npx webpack --mode=development asset app.js 802 bytes [emitted] (name: main) ./src/app.js 49 bytes [built] [code generated] webpack 5.14.0 compiled successfully in 137 mssrc/js/app.js/* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ /******/ (() => { // webpackBootstrap /*!********************!*\ !*** ./src/app.js ***! \********************/ eval("let test = ()=> {alert(\"webpack test\");};\ntest();\n\n//# sourceURL=webpack://test5/./src/app.js?"); /******/ })() ;【参考】webpackのmodeオプション
下記のようにproductionモードで実行すると、出力結果が異なる 不要な記述が省略されていることが分かる
npx webpack --mode=production # もしくはmodeを付けない場合はproductionで実行されるdist/app.jsconsole.log("webpack test");https://webpack.js.org/configuration/mode/
babelの導入
yarn add --dev @babel/core @babel/preset-env babel-loader core-jswebpackの設定に、jsファイルはbabelを通すように設定
webpack.config.jsmodule: { rules: [ { test: /\.js$/, loader: 'babel-loader', } ] },babelの設定用にファイルを2つ追加する
.babelrc{ "presets": [[ "@babel/env", { "modules": false } ]], "env": { "test": { "presets": [[ "@babel/env", { "targets": { "node": "current" } } ]] } } }.browserslistrc> 1%再び、webpackを実行すると、ES5に対応した書き方に変換されていることがわかる。
public/js/app.js/* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ /******/ (function() { // webpackBootstrap /*!********************!*\ !*** ./src/app.js ***! \********************/ eval("var test = function test() {\n alert(\"webpack test\");\n};\n\ntest();\n\n//# sourceURL=webpack://test5/./src/app.js?"); /******/ })() ;IEでエラーが出ないことを確認
jsをVueのものに書き換えていく
src/app.jsimport Vue from 'vue'; import Hello from './Hello.vue'; document.addEventListener('DOMContentLoaded', () => { new Vue(Hello).$mount('#app'); });vueの単一コンポーネントファイルを追加
src/Hello.vue<template> <div> <p>{{ greeting }} World!</p> </div> </template> <script> export default { data() { return { greeting: '' }; }, created() { this.greeting = 'hello'; } } </script>webpack 実行
npx webpack --mode="development" asset app.js 239 KiB [emitted] (name: main) runtime modules 916 bytes 4 modules cacheable modules 223 KiB modules by path ./src/ 2.13 KiB ./src/app.js 152 bytes [built] [code generated] ./src/Hello.vue 1.04 KiB [built] [code generated] ./src/Hello.vue?vue&type=template&id=184cbba9& 197 bytes [built] [code generated] ./src/Hello.vue?vue&type=script&lang=js& 336 bytes [built] [code generated] ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/Hello.vue?vue&type=template&id=184cbba9& 267 bytes [built] [code generated] ./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/Hello.vue?vue&type=script&lang=js& 172 bytes [built] [code generated] modules by path ./node_modules/ 221 KiB ./node_modules/vue/dist/vue.runtime.esm.js 218 KiB [built] [code generated] ./node_modules/vue-loader/lib/runtime/componentNormalizer.js 2.71 KiB [built] [code generated] webpack 5.14.0 compiled successfully in 2064 msブラウザで問題なく表示されていることを確認
単一コンポ―ネント CSS対応
yarn add --dev style-loader css-loader
webpackにcss用の設定を追加
webpack.config.jsmodule: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.js$/, loader: 'babel-loader', }, { test: /\.css$/, loader: 'vue-style-loader', loader: 'css-loader', } ] },npx webpack --mode="development" asset app.js 257 KiB [compared for emit] (name: main) runtime modules 1.19 KiB 5 modules cacheable modules 232 KiB modules by path ./src/ 3.39 KiB 9 modules modules by path ./node_modules/ 229 KiB ./node_modules/vue/dist/vue.runtime.esm.js 218 KiB [built] [code generated] ./node_modules/vue-loader/lib/runtime/componentNormalizer.js 2.71 KiB [built] [code generated] ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 6.67 KiB [built] [code generated] ./node_modules/css-loader/dist/runtime/api.js 1.57 KiB [built] [code generated] webpack 5.14.0 compiled successfully in 2071 msCSSが app.js に埋め込まれ、適用されるようになった。
Typescript対応
yarn add --dev typescript ts-loader
app.js → app.tsへ
内容はとくにいじらず
Hello.vueをts対応
Hello.vue<script lang="ts">webpack設定
webpack.config.js-略- entry: './src/app.ts', -略- { test: /\.tsx?$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/] } } ] } -略-[参考]
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
の2行が無いと、import Vue from 'vue' のようなインポートができなかった。Typescript初心者なのであとで調べる。TypeScript設定ファイルの準備
tsconfig.json{ "compilerOptions": { "target": "es5", "module": "es2015", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, "sourceMap": true, "baseUrl": "./", "moduleResolution": "node", "allowSyntheticDefaultImports": true }, "include": [ "./src/*.vue", "./src/*.ts" ], "exclude": [ "node_modules" ] }試しに、型をつけてみる
Hello.vue-略- <script lang="ts"> export default { data() { return { greeting: '' }; }, created() { this.greeting = 'hello'; }, computed:{ computed_greeting():string{ return this.greeting; } } } </script> -略-これでwebpackが通り、TypeScriptが扱えている
npx webpack --mode="development" asset app.js 257 KiB [compared for emit] (name: main) runtime modules 1.19 KiB 5 modules cacheable modules 233 KiB modules by path ./src/ 3.57 KiB 9 modules modules by path ./node_modules/ 229 KiB ./node_modules/vue/dist/vue.runtime.esm.js 218 KiB [built] [code generated] ./node_modules/vue-loader/lib/runtime/componentNormalizer.js 2.71 KiB [built] [code generated] ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 6.67 KiB [built] [code generated] ./node_modules/css-loader/dist/runtime/api.js 1.57 KiB [built] [code generated] webpack 5.14.0 compiled successfully in 4685 msためしに型に合っていない値を返すと、こける
src/Hello.vue-略- computed:{ computed_greeting():string{ return 1; } } -略-npx webpack --mode="development" asset app.js 257 KiB [emitted] (name: main) runtime modules 1.19 KiB 5 modules cacheable modules 232 KiB modules by path ./src/ 3.56 KiB 9 modules modules by path ./node_modules/ 229 KiB ./node_modules/vue/dist/vue.runtime.esm.js 218 KiB [built] [code generated] ./node_modules/vue-loader/lib/runtime/componentNormalizer.js 2.71 KiB [built] [code generated] ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 6.67 KiB [built] [code generated] ./node_modules/css-loader/dist/runtime/api.js 1.57 KiB [built] [code generated] ERROR in /home/obana/js/vue/test5/src/Hello.vue.ts [tsl] ERROR in /home/obana/js/vue/test5/src/Hello.vue.ts(19,11) TS2322: Type 'number' is not assignable to type 'string'..gitignore
git管理にあたり、作成 とりあえずnodeモジュール除外すれば良いか。
node_modules/ここまでで、一応開発できるようになったものの、
まだまだ準備したいところなので、続きは別でまとめていく。
- 投稿日:2021-01-15T01:56:17+09:00
Vuexでオブジェクトのプロパティの値の変更を検知したいときの対処法!!
今日は、Vuexについての記事を書いていこうかなと思います。
Vuexでオブジェクトのプロパティの値を変更しても、値の変更は検知されません。(これで3,4時間くらい時間食われた)
これは、Vue本来の仕様にになっておりどうしようもすることはできません。
では、どうやってプロパティの変更を検知してくれるのでしょうか?
結論から言うと、オブジェクト自体を書き換えるという動作をします。
めんどくさいですよね。
でも大丈夫!
同じようなことで頭を抱える人に、とっておき解決策をご用意しております。
ぜひ皆さんのお力になれればなと思います!!
それでは、順を追って説明していきます。
オブジェクトのコピーを作成
今回は、
user
というオブジェクトを例に挙げて説明していきます。store/index.jsstate: { user: {}, // user情報 }, changeUserPhotoURL(state, payload) { let user = Vue.util.extend({}, state.user) },
Vue.util.extend
でコピーを作成し、第一引数には肩を定義します。第二引数には、コピーする対象を選択します。プロパティの値を変更し、元のオブジェクトに代入
今回は、ユーザーのプロフィール画像(photoURL)を変更します。
store/index.jsstate: { user: [], // user情報 }, changeUserPhotoURL(state, payload) { let user = Vue.util.extend({}, state.user) user.photoURL = payload state.user = user },
state.user = user
この部分は、元のオブジェクト(state.user)にコピー、編集したオブジェクト(user)を代入しています。ページの読み込み
this.$router.go()最後に、routerなどを使ってページのリロードを行いましょう!
このようにして、オブジェクトのプロパティの値の変更を検知してくれます。
いかがだったでしょうか?
これで時間を潰すなんてもったいないですよね??
なので、この記事を参考にしてぜひ学習を進めていってください!
以上、「Vuexでオブジェクトのプロパティを変更したいときの対処法!!」でした!
良ければ、LGTM、コメントお願いします。
また、何か間違っていることがあればご指摘頂けると幸いです。
他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!
Thank you for reading