#前置き
以前の記事を役割で切り分けて
Vuex版にしたコードです。
この2つが
一緒になっていて
分かりにくかったので
切り分けてみました✂︎
・選択した画像を送信する
・url化してプレビューする
Vuexに移行する必要があるのは
送信と取得の部分です。
#Step1: 送信するコードを考える
##Vuexに移行する前のコード
選択した画像を
そのままstorageに
putすればOK🙆♀️
putするため
引数にFileを使用します💫
e.target.files
FileListオブジェクトは
配列のように管理されていて
0番目に画像データが入っています。
それをそのまま送信📤
<template>
<div class="page">
<form
class="form"
@submit.prevent="submitImg()"
>
<input
type="file"
accept="img/*"
@change="changeImg"
>
<button
type="submit"
class="button"
>
click
</button>
<div>
<p>{{ thumbnail }}</p>
</div>
</form>
</div>
</template>
<script>
import firebase from '@/plugins/firebase'
export default {
data () {
return {
thumbnail: '',
}
},
methods: {
changeImg (e) {
this.thumbnail = e.target.files[0]
console.log(this.thumbnail)
if (this.thumbnail) {
this.submitImg(this.thumbnail)
}
},
submitImg (thumbnail) {
let storage = firebase.storage()
let storageRef = storage.ref().child('file.png')
storageRef.put(thumbnail)
.then(res => console.log(res))
.catch(error => console.log(error))
},
},
}
</script>
<style lang="scss" scoped>
</style>
##Vuex移行後のコード
<template>
<div class="page">
<form
class="form"
@submit.prevent="submitImg()"
>
<input
type="file"
accept="img/*"
@change="changeImg"
>
<button
type="submit"
class="button"
>
click
</button>
<div>
<p>{{ thumbnail }}</p>
</div>
</form>
</div>
</template>
<script>
export default {
data () {
return {
thumbnail: '',
}
},
methods: {
changeImg (e) {
this.thumbnail = e.target.files[0]
},
submitImg (thumbnail) {
this.$store.dispatch('submit', this.thumbnail)
},
}
</script>
<style lang="scss" scoped>
</style>
import firebase from '@/plugins/firebase'
export const actions = {
submit ({ context }, image) {
let storage = firebase.storage()
let storageRef = storage.ref().child('file.png')
storageRef.put(image)
.then(res => console.log(res))
.catch(error => console.log(error))
},
}
#Step2: プレビューするコードを書き足す
Vuexに移行する必要がないので
付け足します✍️
画像を読み込み
Fileオブジェクトを
readAsDataURLでurlにします💫
readAsDataURLでの
読み込みが完了したら
onloadで結果を
postData.thumbnailに入れます。
MDN: FileReader.onload
<template>
<div class="page">
<form
class="form"
@submit.prevent="submitImg()"
>
<input
type="file"
accept="img/*"
@change="changeImg"
>
<button
type="submit"
class="button"
>
click
</button>
<div>
<p>{{ thumbnail }}</p>
<img :src="postData.thumbnail" alt="">
</div>
</form>
</div>
</template>
<script>
export default {
data () {
return {
thumbnail: '',
postData: {
thumbnail: '',
},
}
},
methods: {
changeImg (e) {
this.thumbnail = e.target.files[0]
if (this.thumbnail) {
const reader = new FileReader()
reader.readAsDataURL(this.thumbnail)
reader.onload = () => {
this.postData.thumbnail = reader.result + ''
}
}
},
submitImg (thumbnail) {
this.$store.dispatch('submit', this.thumbnail)
},
}
</script>
<style lang="scss" scoped>
</style>
storeの変更はありません。
#Step3: 取得するコードを考える
これで完成です🎶👏
取得の場合は
firestorageで取得した画像を
getDownloadURLで
url化できるので
それをそのままstateに入れます。
computedで
urlをgettersで呼び出して
img srcにバインドさせればOKです✨
<template>
<div class="page">
<form
class="form"
@submit.prevent="submitImg"
>
<input
type="file"
accept="img/*"
@change="changeImg"
>
<button
type="submit"
class="button"
>
click
</button>
<div>
<img :src="postData.thumbnail" alt="">
</div>
</form>
<div>
<button
class="button"
@click="getImg"
>
取得
</button>
<img :src="getThumbnail" alt="">
</div>
</div>
</template>
<script>
export default {
data () {
return {
thumbnail: '',
postData: {
thumbnail: '',
},
}
},
computed: {
getThumbnail () {
return this.$store.getters['thumbnail']
},
},
methods: {
changeImg (e) {
this.thumbnail = e.target.files[0]
if (this.thumbnail) {
const reader = new FileReader()
reader.readAsDataURL(this.thumbnail)
reader.onload = () => {
this.postData.thumbnail = reader.result + ''
}
}
},
submitImg () {
this.$store.dispatch('submit', this.thumbnail)
},
getImg () {
this.$store.dispatch('getImg')
},
},
}
</script>
<style lang="scss" scoped>
</style>
import firebase from '@/plugins/firebase'
export const state = () => ({
thumbnail: '',
})
export const getters = {
thumbnail: state => {
return state.thumbnail
},
}
export const actions = {
submit ({ context }, image) {
let storage = firebase.storage()
let storageRef = storage.ref().child('file.png')
storageRef.put(image)
.then(res => console.log(res))
.catch(error => console.log(error))
},
getImg ({ commit }) {
let storage = firebase.storage()
let storageRef = storage.ref().child('file.png')
storageRef.getDownloadURL()
.then(res => {
console.log(res)
commit('getData', res)
})
},
}
export const mutations = {
getData (state, image) {
state.thumbnail = image
},
}
<template>
<div class="page">
<form
class="form"
@submit.prevent="submitImg"
>
<label class="label">
<input
type="file"
accept="img/*"
class="input"
@change="changeImg"
>
</label>
<div class="img">
<img
v-show="postData.thumbnail"
:src="postData.thumbnail"
alt="preview"
class="preview"
>
</div>
<button
type="submit"
class="button"
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 12l11 3.1 7-8.1-8.156 5.672-4.312-1.202 15.362-7.68-3.974 14.57-3.75-3.339-2.17 2.925v-.769l-2-.56v7.383l4.473-6.031 4.527 4.031 6-22z"/></svg>
</button>
</form>
<div class="getImg">
<button
class="button"
@click="getImg"
>
getImg!
</button>
<div class="img">
<img
v-show="getThumbnail"
:src="getThumbnail"
alt="getThumbnail"
class="img"
>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
thumbnail: '',
postData: {
thumbnail: '',
},
}
},
computed: {
getThumbnail () {
return this.$store.getters['change/thumbnail']
},
},
methods: {
changeImg (e) {
this.thumbnail = e.target.files[0]
if (this.thumbnail) {
const reader = new FileReader()
reader.readAsDataURL(this.thumbnail)
reader.onload = () => {
this.postData.thumbnail = reader.result + ''
}
}
},
submitImg () {
this.$store.dispatch('change/submit', this.thumbnail)
},
getImg () {
this.$store.dispatch('change/getImg')
},
},
}
</script>
<style lang="scss" scoped>
.page {
padding: 20px;
> .form {
background-color: #FFDCDC;
> .label {
display: block;
width: 32px;
height: 32px;
background-image: url('data:image/svg+xml, <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23000" d="M5 8.5c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5c0 .829-.672 1.5-1.5 1.5s-1.5-.671-1.5-1.5zm9 .5l-2.519 4-2.481-1.96-4 5.96h14l-5-8zm8-4v14h-20v-14h20zm2-2h-24v18h24v-18z"/></svg>');
background-repeat: no-repeat;
background-size: cover;
> .input {
display: none;
}
}
> .img {
width: 100px;
height: 100px;
.preview {
width: 100px;
}
}
}
> .getImg {
margin-top: 100px;
> .img {
width: 100px;
height: 100px;
> .img {
width: 100px;
}
}
}
}
</style>
import firebase from '@/plugins/firebase'
export const state = () => ({
thumbnail: '',
})
export const getters = {
thumbnail: state => {
return state.thumbnail
},
}
export const actions = {
submit ({ context }, image) {
let storage = firebase.storage()
let storageRef = storage.ref().child('file.png')
storageRef.put(image)
.then(res => console.log(res))
.catch(error => console.log(error))
},
getImg ({ commit }) {
let storage = firebase.storage()
let storageRef = storage.ref().child('file.png')
storageRef.getDownloadURL()
.then(res => {
console.log(res)
commit('getData', res)
})
},
}
export const mutations = {
getData (state, image) {
state.thumbnail = image
},
}
#まとめ
役割を分けて
切り離すことができました✂︎
前回はonloadを
readAsDataURLの前に
書いていたため、
役割を分ける際に混乱しました😂
流れをしっかり理解するのは大切ですね。
コードは全てを理屈で理解しようとすると詰む
と言いますが、
理論的に分かるに越したことはないです😂
キャプチャの録画は
GIPHY Captureに
変更してみました💫