<div id="app">
  <v-app>
    <div>
      <v-btn
        color="primary"
        class="text-none"
        round
        depressed
        :loading="isSelecting"
        @click="onButtonClick"
      >
        <v-icon left>
          cloud_upload
        </v-icon>
        {{ buttonText }}
      </v-btn>
      <input
        ref="uploader"
        class="d-none"
        type="file"
        accept="image/*"
        @change="onFileChanged"
      >
    </div>
  </v-app>
</div>
.v-icon--left {
  margin-right: 8px;
}
Vue.prototype.$vuetify = Object.assign(Vue.prototype.$vuetify, {
  theme: {
    primary: '#3f51b5',
    secondary: '#b0bec5'
  },
  options: {
    customProperties: true
  }
})

new Vue({
  el: '#app',
  data: () => ({
    defaultButtonText: '画像をアップロード',
    selectedFile: null,
    isSelecting: false
  }),
  computed: {
    buttonText() {
      return this.selectedFile ? this.selectedFile.name : this.defaultButtonText
    }
  },
  methods: {
    onButtonClick() {
      this.isSelecting = true
      window.addEventListener('focus', () => {
        this.isSelecting = false
      }, { once: true })

      this.$refs.uploader.click()
    },
    onFileChanged(e) {
      this.selectedFile = e.target.files[0]
      
      // do something
    }
  }
})

External CSS

  1. https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons
  2. https://unpkg.com/vuetify@1.5.16/dist/vuetify.min.css

External JavaScript

  1. https://unpkg.com/vue@2.6.10/dist/vue.js
  2. https://unpkg.com/vuetify@1.5.16/dist/vuetify.min.js