We will create a Github file explorer that will allow us to explore files in public Github repos.
All the code for this post can be found on Github.
src/App.vue
<form class="form-inline" @submit.prevent="changeRepo">
<div class="form-group">
<input type="text" v-model="fullRepoName" class="form-control" placeholder="仓库全称">
</div>
<input type="submit" class="btn btn-primary" value="获取">
</form>
Here, we are simply creating a form and marking it up with some basic Bootstrap code. On the form, we have used the @submit.prevent
directive to add a submit listener to the form. The @submit
adds the listener while the .prevent
part will automatically run preventDefault
for us. When we submit the form, Vue will fire the changeRepo
method.
The form itself is pretty basic. It has a text field and a submit button. The input has the v-model
directive on it. This creates a two-way binding between the value of the input and the value of fullRepoName
, which is a piece of data on our Vue instance.
src/components/GithubFileExplorer.vue
export default {
props: {
fullRepoUrl: {
type: String,
required: true
}
}
}
We define the props
this component will accept from its parent. We define props
in the component as objects. This allows us to add validations that the props must pass for the data in the Vue instance to be updated. We define fullRepoUrl
as strings and required.
export default {
computed: {
url() {
return 'https://api.github.com/repos/' + this.fullRepoUrl + '/contents' + this.path
}
}
}
We build the URL by concatenating the base of the Github API with the fullRepoUrl
(we create it as a computed property) and then adding the path to the end. For more information on this endpoint, see the Github documentation.
<template>
<div class="row">
<div class="col-md-12">
<table class="table">
<caption>当前路径:{{ path }}</caption>
<thead>
<tr>
<th>目录结构</th>
<th class="text-right">
<button class="btn btn-default" @click="goBack" v-if="path !== '/'">返回</button>
</th>
</tr>
</thead>
<tbody>
<tr v-for="file in sortedFiles">
<td>
<div class="file" v-if="file.type === 'file'">
<i class="fa fa-file-o"></i> {{ file.name }}
</div>
<div class="directory" v-if="file.type === 'dir'">
<i class="fa fa-folder-o"></i>
<a @click="changePath(file.path)">{{ file.name }}</a>
</div>
</td>
<td class="text-right">
<a :href="file.download_url" download v-if="file.type === 'file'">
<i class="fa fa-cloud-download"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
Files from Github are generally either files (file
) or directories (dir
). Then we display a download link but only if it is of type file
. Notice here I am using the HTML5 attribute download
to tell the browser to download the file and not go to the page pointed to by the href
attribute.
Let’s do one last thing to change the look of our explorer. Right now the files are spit out in whatever order Github returns them. Let’s take back control from Github and reorder them! Let’s put the directories on top in alphabetical order and then the files underneath them in alphabetical order. Put the following in the computed
object in our component.
computed: {
sortedFiles: function () {
return this.files.slice(0).sort(function (a, b) {
if (a.type !== b.type) {
if (a.type === 'dir') {
return -1
} else {
return 1
}
} else {
if (a.name < b.name) {
return -1
} else {
return 1
}
}
})
}
}
This piece of code gives us a sortedFiles
property on our Vue instance that we can use in our template.