使用 Vue.js 创建简单的自定义文件选择器

文件选择元素很容易成为网络上最丑陋的输入类型之一. 它们在每个浏览器中都以不同的方式实现,并且通常非常丑陋. 尽管存在一些解决方案,我们在这里将向您展示一种方法,使用标签和一些Vue.js魔法。

设置

如果您尚未设置一个项目,请使用 vue-cli的 webpack-simple 模板启动一个新的项目。

1$ npm install -g vue-cli
2$ vue init webpack-simple ./file-upload # Follow the prompts.
3$ cd ./file-upload
4$ npm install # or yarn

组件 Template & Styles

该组件的目的是简单地将隐藏的输入 type="file" 元素包装到标签中,并显示其中的其他东西。

 1[label FileSelect.vue (template)]
 2<template>
 3  <!--
 4    Everything is wrapped in a label, which acts as a clickable wrapper around a form element.
 5    In this case, the file input.
 6  -->
 7  <label class="file-select">
 8    <!-- We can't use a normal button element here, as it would become the target of the label. -->
 9    <div class="select-button">
10      <!-- Display the filename if a file has been selected. -->
11      <span v-if="value">Selected File: {{value.name}}</span>
12      <span v-else>Select File</span>
13    </div>
14    <!-- Now, the file input that we hide. -->
15    <input type="file" @change="handleFileChange"/>
16  </label>
17</template>
18...

现在,一些漂亮的简单风格给它一个相当的按钮的外观。

 1[label FileSelect.vue (styles)]
 2...
 3<style scoped>
 4.file-select > .select-button {
 5  padding: 1rem;
 6
 7  color: white;
 8  background-color: #2EA169;
 9
10  border-radius: .3rem;
11
12  text-align: center;
13  font-weight: bold;
14}
15
16/* Don't forget to hide the original file input! */
17.file-select > input[type="file"] {
18  display: none;
19}
20</style>

逻辑

文件是浏览器的一个非常特殊的类型,所以有几个特殊的规则,使他们有时有点棘手的工作。 (更多关于这里.)尽管如此,我们实际上可以得到一个非常简单的控制器。

 1[label FileSelect.vue (script)]
 2<script>
 3export default {
 4  props: {
 5    // Using value here allows us to be v-model compatible.
 6    value: File
 7  },
 8
 9  methods: {
10    handleFileChange(e) {
11      // Whenever the file changes, emit the 'input' event with the file data.
12      this.$emit('input', e.target.files[0])
13    }
14  }
15}
16</script>

使用

现在,我们可以将我们的新组件导入我们的应用程序,并像任何其他组件一样使用它,并且完全支持v型号。

 1[label App.vue]
 2<template>
 3  <div>
 4    <p>My File Selector: <file-select v-model="file"></file-select></p>
 5    <p v-if="file">{{file.name}}</p>
 6  </div>
 7</template>
 8
 9<script>
10import FileSelect from './FileSelect.vue'
11
12export default {
13  components: {
14    FileSelect
15  },
16
17  data() {
18    return {
19      file: null
20    }
21  }
22}
23</script>

现在你可以通过组件对用户选择的文件进行完全反动访问,然后可以将其包装到上传组件中,或者通过FileReader API(https://developer.mozilla.org/en-US/docs/Web/API/FileReader)以某种方式处理数据。

完整组件代码

对于那些想要一次的一切的人来说,在这里你去!正如我所承诺的那样,只有41行。

 1[label FileSelect.vue]
 2<template>
 3  <label class="file-select">
 4    <div class="select-button">
 5      <span v-if="value">Selected File: {{value.name}}</span>
 6      <span v-else>Select File</span>
 7    </div>
 8    <input type="file" @change="handleFileChange"/>
 9  </label>
10</template>
11
12<script>
13export default {
14  props: {
15    value: File
16  },
17
18  methods: {
19    handleFileChange(e) {
20      this.$emit('input', e.target.files[0])
21    }
22  }
23}
24</script>
25
26<style scoped>
27.file-select > .select-button {
28  padding: 1rem;
29
30  color: white;
31  background-color: #2EA169;
32
33  border-radius: .3rem;
34
35  text-align: center;
36  font-weight: bold;
37}
38
39.file-select > input[type="file"] {
40  display: none;
41}
42</style>
Published At
Categories with 技术
Tagged with
comments powered by Disqus