Javascript 如何从嵌套组件发出,同时保持在函数外部引用变量的能力

Javascript 如何从嵌套组件发出,同时保持在函数外部引用变量的能力,javascript,firebase,vue.js,firebase-storage,eventemitter,Javascript,Firebase,Vue.js,Firebase Storage,Eventemitter,我正在尝试建立一个图像上传应用程序,将图像上传到firebase存储,跟踪上传百分比,并在上传时更新图库,以便显示所有图像,包括新上传的图像 我开始构建用于上传和跟踪上传进度的组件。但是,它不起作用,因为onUpload方法无法更改this.uploadPercentage的值 <template> <v-container style="height: 100%;"> <v-row align-content="center"

我正在尝试建立一个图像上传应用程序,将图像上传到firebase存储,跟踪上传百分比,并在上传时更新图库,以便显示所有图像,包括新上传的图像

我开始构建用于上传和跟踪上传进度的组件。但是,它不起作用,因为onUpload方法无法更改this.uploadPercentage的值

<template>
  <v-container style="height: 100%;">
      <v-row
        align-content="center"
        justify="center"
      >
        <h1>Image Uploader</h1>
      </v-row>
      <v-row
        align-content="center"
        justify="center"
      >
        <v-col cols="6">
          <v-progress-linear
            color="deep-purple accent-4"
            rounded
            height="6"
            :value="uploadPercentage"
            id="uploader"
          ></v-progress-linear>
        </v-col>
      </v-row>
      <v-row
        align-content="center"
        justify="center"
      >
        <v-col
          class="align-content-center"
          cols="4"
        >
          <v-file-input
            v-model="file"
            accept="image/*"
            label="choose an image"
            outlined
            @change="onFileChange"
            ></v-file-input>
        </v-col>
        <v-col
          class="align-content-center mt-2"
          cols="2"
        >
          <v-btn
            @click="onUpload"
          >
            Upload
            <v-icon right dark>mdi-cloud-upload</v-icon>
          </v-btn>
        </v-col>
      </v-row>
    </v-container>
</template>

<script>
import firebase from '@/firebase/init'

export default {
  data: () => ({
    file: null,
    imageURL: null,
    uploadPercentage: 0
  }),
  methods: {
    onFileChange () {
      let reader = new FileReader()
      reader.onload = () => {
        reader.imagUrl = reader.result
      }
      reader.readAsDataURL(this.file)
    },
    onUpload () {
      // create a firebase storage ref
      var storageRef = firebase.storage().ref('public_wall/' + this.file.name)

      // upload file
      var task = storageRef.put(this.file)

      // update progress bar
      task.on('state_changed',
        function (snapshot) {
          console.log('uploading')
          var percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
          this.uploadPercentage = percentage
        },

        function error (err) {
          console.log(err)
        },

        function completed () {
          console.log('upload complete')
        }

      )
    }
  }
}
</script>
但是,我希望该组件是嵌套组件,并在上载完成时发出信号。为此,我已尝试将task.on中已完成的函数更改为以下内容:

function completed () {
          console.log('upload complete function')
          this.$emit('upload-complete', 'hello')
        }
这将抛出错误:TypeError:This.$emit不是函数

通过一些研究,我发现您无法引用此项。$emit来自一个arrow函数,但是,完成的函数不是arrow函数,将snapshot函数更改回non-arrow并不能解决问题,只会停止上载百分比跟踪器的工作

我做错了什么?如何解决这个问题?

这是因为这涉及到已完成函数中的其他内容。你可以这样做

onUpload () {
  let _self = this // saving reference to this
  // create a firebase storage ref
  var storageRef = firebase.storage().ref('public_wall/' + this.file.name)

  // upload file
  var task = storageRef.put(this.file)

  // update progress bar
  task.on('state_changed',
    function (snapshot) {
      console.log('uploading')
      var percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
      this.uploadPercentage = percentage
    },

    function error (err) {
      console.log(err)
    },

    function completed () {
      _self.$emit('upload-complete', 'hello')
      // accessing that reference using closure
    }

  )
}
onUpload () {
  let _self = this // saving reference to this
  // create a firebase storage ref
  var storageRef = firebase.storage().ref('public_wall/' + this.file.name)

  // upload file
  var task = storageRef.put(this.file)

  // update progress bar
  task.on('state_changed',
    function (snapshot) {
      console.log('uploading')
      var percentage = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
      this.uploadPercentage = percentage
    },

    function error (err) {
      console.log(err)
    },

    function completed () {
      _self.$emit('upload-complete', 'hello')
      // accessing that reference using closure
    }

  )
}