四、使用 Dropbox API 获取文件列表
在接下来的几章中,我们将构建一个基于 Vue 的 Dropbox 浏览器。此应用将获取您的 Dropbox API 密钥,并允许您导航到文件夹和下载文件。您将了解如何与 Vue 应用中的 API 交互,Vue 生命周期挂钩,包括created()
方法,最后我们将引入一个名为Vuex
的库来处理应用的缓存和状态。应用将具有可共享的 URL,并检索通过#
URL 参数传入的文件夹的内容。
如果你想让用户在不提供用户名和密码的情况下访问 Dropbox 的内容,这种应用将非常有用。但是,请注意,精通技术的用户可能会在代码中找到您的 API 密钥并加以滥用,因此不要将此代码发布到万维网。
本章将涵盖:
- 加载和查询 Dropbox API
- 列出 Dropbox 帐户中的目录和文件
- 向应用添加加载状态
- 使用 Vue 动画
您将需要一个 Dropbox 帐户来了解接下来的几章。如果你没有,注册并添加一些虚拟文件和文件夹。Dropbox 的内容无关紧要,但有文件夹可供浏览将有助于理解代码。
开始加载库
为要运行的应用创建新的 HTML 页面。创建网页所需的 HTML 结构,并包含应用视图包装:
<!DOCTYPE html>
<html>
<head>
<title>Dropbox App</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
它在这里被称为#app
,但是你可以随意调用它——只要记住更新 JavaScript 即可。
由于我们的应用代码将变得相当粗,所以创建一个单独的 JavaScript 文件并将其包含在文档底部。您还需要包括 Vue 和 Dropbox API SDK
与以前一样,您可以引用远程文件或下载库文件的本地副本。出于速度和兼容性的考虑,下载本地副本。在 HTML 文件底部包含三个 JavaScript 文件:
<script src="js/vue.js"></script>
<script src="js/dropbox.js"></script>
<script src="js/app.js"></script>
创建您的app.js
并初始化一个新的 Vue 实例,使用el
标记将实例装载到视图中的 ID 上。
new Vue({
el: '#app'
});
创建 Dropbox 应用并初始化 SDK
在与 Vue 实例交互之前,我们需要通过 SDK 连接到 Dropbox API。这是通过 Dropbox 自身生成的 API 密钥来完成的,该 API 密钥用于跟踪连接到您的帐户的内容以及 Dropbox 要求您制作自定义 Dropbox 应用的位置。
前往 Dropbox 开发者区,选择创建你的应用。选择 Dropbox API 并选择受限文件夹或完全访问。这取决于您的需要,但对于测试,请选择 FullDropbox。为你的应用命名,然后单击“创建应用”按钮。
生成应用的访问令牌。为此,在查看应用详细信息页面时,单击生成的访问令牌下的生成按钮。这将为您提供一长串数字和字母——将其复制并粘贴到编辑器中,并将其作为变量存储在 JavaScript 顶部。在本书中,API 密钥将被称为XXXX
:
/**
* API Access Token
*/
let accessToken = 'XXXX';
现在我们有了 API 密钥,可以从 Dropbox 访问文件和文件夹了。初始化 API 并将accessToken
变量传递给 Dropbox API 的accessToken
属性:
/**
* Dropbox Client
* @type {Dropbox}
*/
const dbx = new Dropbox({
accessToken: accessToken
});
我们现在可以通过dbx
变量访问 Dropbox。我们可以通过连接并输出根路径的内容来验证与 Dropbox 的连接是否正常:
dbx.filesListFolder({path: ''})
.then(response => {
console.log(response.entries);
})
.catch(error => {
console.log(error);
});
此代码使用 JavaScript 承诺,这是一种向代码中添加操作而不需要回调函数的方法。如果您不熟悉承诺,请查看谷歌的这篇博文(https://developers.google.com/web/fundamentals/primers/promises )。
记下第一行,尤其是path
变量。这允许我们传入文件夹路径,以列出该目录中的文件和文件夹。例如,如果您的 Dropbox 中有一个名为images
的文件夹,您可以将参数值更改为/images
,返回的文件列表将是该目录中的文件和文件夹。
打开 JavaScript 控制台并检查输出;您应该得到一个包含多个对象的数组-Dropbox 根目录中的每个文件或文件夹对应一个对象。
显示数据并使用 Vue 获取数据
现在我们可以使用 Dropbox API 检索数据了,现在是在 Vue 实例中检索数据并显示在视图中的时候了。这个应用将完全使用组件构建,所以我们可以利用划分的数据和方法。如果你想集成到其他应用中,这也意味着代码是模块化和可共享的。
我们还将利用本机 Vuecreated()
函数——我们将在稍后触发时介绍它。
创建组件
首先,在视图中创建自定义 HTML 元素<dropbox-viewer>
。在页面底部为我们的 HTML 布局创建一个<script>
模板块:
<div id="app">
<dropbox-viewer></dropbox-viewer>
</div>
<script type="text/x-template" id="dropbox-viewer-
template">
<h1>Dropbox</h1>
</script>
在app.js
文件中初始化组件,将其指向模板 ID:
Vue.component('dropbox-viewer', {
template: '#dropbox-viewer-template'
});
在浏览器中查看应用时,应显示模板中的标题。下一步是将 Dropbox API 集成到组件中。
检索 Dropbox 数据
创建一个名为dropbox
的新方法。在其中,移动调用 Dropbox 类并返回实例的代码。现在,我们可以通过调用this.dropbox()
通过组件访问 Dropbox API:
Vue.component('dropbox-viewer', {
template: '#dropbox-viewer-template',
methods: {
dropbox() {
return new Dropbox({
accessToken: this.accessToken
});
}
}
});
我们还将把 API 密钥集成到组件中。创建一个返回包含访问令牌的对象的数据函数。更新 Dropbox 方法以使用密钥的本地版本:
Vue.component('dropbox-viewer', {
template: '#dropbox-viewer-template',
data() {
return {
accessToken: 'XXXX'
}
},
methods: {
dropbox() {
return new Dropbox({
accessToken: this.accessToken
});
}
}
});
我们现在需要为组件添加获取目录列表的功能。为此,我们将创建另一个方法,该方法使用单个参数 path。这将使我们能够在需要时请求不同路径或文件夹的结构。
使用前面提供的代码-将dbx
变量更改为this.dropbox()
:
getFolderStructure(path) {
this.dropbox().filesListFolder({path: path})
.then(response => {
console.log(response.entries);
})
.catch(error => {
console.log(error);
});
}
更新 DropboxfilesListFolder
函数以接受传入的 path 参数,而不是固定值。在浏览器中运行此应用将显示 Dropbox 标题,但不会检索任何文件夹,因为尚未调用这些方法。
Vue 生命周期挂钩
这就是created()
函数的作用。一旦 Vue 实例初始化了数据和方法,但尚未将实例装载到 HTML 组件上,就会调用created()
函数。在生命周期的不同阶段,还有一些其他功能可用;更多关于这些的信息可以在 Alligator.io 上阅读。生命周期如下:
使用created()
功能,我们可以访问方法和数据,同时能够在 Vue 安装应用时启动检索过程。这些不同阶段之间的时间是瞬间的,但在性能和创建快速应用方面,每一刻都很重要。如果我们可以提前开始任务,那么在处理数据之前等待应用完全安装是没有意义的。
在组件上创建created()
函数并调用getFolderStructure
方法,为路径传递一个空字符串以获取 Dropbox 的根:
Vue.component('dropbox-viewer', {
template: '#dropbox-viewer-template',
data() {
return {
accessToken: 'XXXX'
}
},
methods: {
...
},
created() {
this.getFolderStructure('');
}
});
现在在浏览器中运行应用将把文件夹列表输出到控制台,控制台将给出与以前相同的结果。
现在我们需要在视图中显示文件列表。为此,我们将在组件中创建一个空数组,并用 Dropbox 查询的结果填充它。这样做的好处是,即使在 Vue 包含任何内容之前,也可以在视图中为其提供一个可循环使用的变量。
显示 Dropbox 数据
在数据对象中创建一个名为structure
的新属性,并将其分配给一个空数组。在文件夹检索的响应功能中,将response.entries
分配给this.structure
。留下console.log
,因为我们需要检查条目以确定在模板中输出什么:
Vue.component('dropbox-viewer', {
template: '#dropbox-viewer-template',
data() {
return {
accessToken: 'XXXX',
structure: []
}
},
methods: {
dropbox() {
return new Dropbox({
accessToken: this.accessToken
});
},
getFolderStructure(path) {
this.dropbox().filesListFolder({path: path})
.then(response => {
console.log(response.entries);
this.structure = response.entries;
})
.catch(error => {
console.log(error);
});
}
},
created() {
this.getFolderStructure('');
}
});
我们现在可以更新视图以显示 Dropbox 中的文件夹和文件。由于结构数组在我们的视图中可用,因此创建一个具有可重复的<li>
循环的<ul>
。
由于我们现在正在添加第二个元素,Vue 要求模板包含该元素,将标题和列表包装在<div>
中:
<script type="text/x-template" id="dropbox-viewer-
template">
<div>
<h1>Dropbox</h1>
<ul>
<li v-for="entry in structure">
</li>
</ul>
</div>
</script>
当数组出现在 JavaScript 控制台中时,在浏览器中查看应用将显示许多空项目符号。要确定可以显示哪些字段和属性,请在 JavaScript 控制台中展开数组,然后进一步展开每个对象。您应该注意到,每个对象都有一个类似属性的集合,其中一些属性在文件夹和文件之间有所不同。
第一个属性.tag
帮助我们识别项目是文件还是文件夹。这两种类型都具有以下共同属性:
id
:Dropbox 的唯一标识符name
:文件或文件夹的名称,无论项目位于何处path_display
:项目的完整路径,其大小写与文件和文件夹的大小写匹配path_lower
:与path_display
相同,但全部小写
带有文件.tag
的项目还包含多个字段供我们显示:
client_modified
:文件添加到 Dropbox 的日期。content_hash
:文件的散列,用于标识文件是否与本地或远程副本不同。更多信息可以在 Dropbox 网站上阅读。rev
:文件版本的唯一标识符。server_modified
:上次在 Dropbox 上修改文件的时间。size
:以字节为单位的文件大小。
首先,我们将显示项目的名称和大小(如果存在)。更新列表项以显示以下属性:
<li v-for="entry in structure">
<strong>{{ entry.name }}</strong>
<span v-if="entry.size"> - {{ entry.size }}</span>
</li>
更多文件元信息
为了使文件和文件夹视图更有用,我们可以向文件(如图像)添加更丰富的内容和元数据。通过在 Dropbox API 中启用include_media_info
选项,可以获得这些详细信息。
返回您的getFolderStructure
方法,并在path
之后添加参数。以下是一些新的可读性行:
getFolderStructure(path) {
this.dropbox().filesListFolder({
path: path,
include_media_info: true
})
.then(response => {
console.log(response.entries);
this.structure = response.entries;
})
.catch(error => {
console.log(error);
});
}
检查这个新 API 调用的结果将显示视频和图像的media_info
键。展开此选项将显示有关文件的更多信息,例如尺寸。如果要添加这些,需要在显示信息之前检查media_info
对象是否存在:
<li>
<strong>{{ f.name }}</strong>
<span v-if="f.size"> - {{ bytesToSize(f.size) }}
</span> -
<span v-if="f.media_info">
[
{{ f.media_info.metadata.dimensions.width }}px x
{{ f.media_info.metadata.dimensions.height }}px
]
</span>
</li>
从 Dropbox 检索数据时,请尝试更新路径。例如,如果您有一个名为images
的文件夹,请将this.getFolderStructure
参数更改为/images
。如果您不确定路径是什么,请在 JavaScript 控制台中分析数据并复制文件夹的path_lower
属性值,例如:
created() {
this.getFolderStructure('/images');
}
格式化文件大小
由于文件大小是以普通字节输出的,用户很难将其卸载。为了解决这个问题,我们可以添加一种格式化方法来输出更为用户友好的文件大小,例如显示1kb
而不是1024
首先,在数据对象上创建一个新键,该键包含一个名为byteSizes
的单元数组:
data() {
return {
accessToken: 'XXXX',
structure: [],
byteSizes: ['Bytes', 'KB', 'MB', 'GB', 'TB']
}
}
这是将被添加到图中的内容,因此可以随意将这些属性设置为小写或全字,例如,兆字节。
接下来,在您的组件中添加一个新方法bytesToSize
,该方法将获取一个参数bytes
,并输出一个带格式的字符串,该字符串的末尾是单位:
bytesToSize(bytes) {
// Set a default
let output = '0 Byte';
// If the bytes are bigger than 0
if (bytes > 0) {
// Divide by 1024 and make an int
let i = parseInt(Math.floor(Math.log(bytes) /
Math.log(1024)));
// Round to 2 decimal places and select the
appropriate unit from the array
output = Math.round(bytes / Math.pow(1024, i),
2) + ' ' + this.byteSizes[i];
}
return output
}
在我们看来,我们现在可以利用这种方法:
<li v-for="entry in structure">
<strong>{{ entry.name }}</strong>
<span v-if="entry.size"> - {{
bytesToSize(entry.size) }}</span>
</li>
添加加载屏幕
本章的最后一步是为我们的应用制作一个加载屏幕。如果 Dropbox API 运行缓慢(或者您有很多数据要显示!),这将告诉用户应用正在加载。
这个加载屏幕背后的理论是相当基本的。默认情况下,我们会将一个加载变量设置为true
,一旦加载数据,该变量就会设置为false
。基于此变量的结果,我们将利用视图属性来显示、然后隐藏包含加载文本或动画的元素,并显示加载的数据列表。
在标题为isLoading
的数据对象中创建新密钥。默认设置此变量为true
:
data() {
return {
accessToken: 'XXXX',
structure: [],
byteSizes: ['Bytes', 'KB', 'MB', 'GB', 'TB'],
isLoading: true
}
}
在组件的getFolderStructure
方法中,将isLoading
变量设置为false
。这应该在您设置结构后在承诺范围内发生:
getFolderStructure(path) {
this.dropbox().filesListFolder({
path: path,
include_media_info: true
})
.then(response => {
console.log(response.entries);
this.structure = response.entries;
this.isLoading = false;
})
.catch(error => {
console.log(error);
});
}
现在,我们可以在视图中使用此变量来显示和隐藏装载容器。
在包含一些加载文本的无序列表之前创建一个新的<div>
。请随意添加 CSS 动画或 gif 动画,让用户知道应用正在检索数据:
<h1>Dropbox</h1>
<div>Loading...</div>
<ul>
...
现在,我们只需要在应用正在加载时显示加载 div,并在数据加载后显示列表。因为这只是对 DOM 的一个更改,所以我们可以使用v-if
指令。为了让您可以自由地重新排列 HTML,请将属性添加到两者,而不是使用v-else
。
要显示或隐藏,我们只需要检查isLoading
变量的状态。我们可以在列表前加上感叹号,仅在应用未加载时显示:
<div>
<h1>Dropbox</h1>
<div v-if="isLoading">Loading...</div>
<ul v-if="!isLoading">
<li v-for="entry in structure">
<strong>{{ entry.name }}</strong>
<span v-if="entry.size">- {{
bytesToSize(entry.size) }}</span>
</li>
</ul>
</div>
我们的应用现在应该在装载后显示装载容器,然后在收集应用数据后显示列表。总而言之,我们完整的组件代码如下所示:
Vue.component('dropbox-viewer', {
template: '#dropbox-viewer-template',
data() {
return {
accessToken: 'XXXX',
structure: [],
byteSizes: ['Bytes', 'KB', 'MB', 'GB', 'TB'],
isLoading: true
}
},
methods: {
dropbox() {
return new Dropbox({
accessToken: this.accessToken
});
},
getFolderStructure(path) {
this.dropbox().filesListFolder({
path: path,
include_media_info: true
})
.then(response => {
console.log(response.entries);
this.structure = response.entries;
this.isLoading = false;
})
.catch(error => {
console.log(error);
});
},
bytesToSize(bytes) {
// Set a default
let output = '0 Byte';
// If the bytes are bigger than 0
if (bytes > 0) {
// Divide by 1024 and make an int
let i = parseInt(Math.floor(Math.log(bytes)
/ Math.log(1024)));
// Round to 2 decimal places and select the
appropriate unit from the array
output = Math.round(bytes / Math.pow(1024,
i), 2) + ' ' + this.byteSizes[i];
}
return output
}
},
created() {
this.getFolderStructure('');
}
});
在状态之间设置动画
作为对用户的一个很好的增强,我们可以在组件和状态之间添加一些转换。Vue 包含一些内置的过渡效果,这很有帮助。使用 CSS,这些转换允许您在插入 DOM 元素时轻松添加淡入淡出、滑动和其他 CSS 动画。有关转换的更多信息,请参见 Vue 文档。
第一步是添加 Vue 自定义 HTML<transition>
元素。使用单独的转换元素包装您的加载和列表,并为其指定一个属性name
和一个值fade
:
<script type="text/x-template" id="dropbox-viewer-
template">
<div>
<h1>Dropbox</h1>
<transition name="fade">
<div v-if="isLoading">Loading...</div>
</transition>
<transition name="fade">
<ul v-if="!isLoading">
<li v-for="entry in structure">
<strong>{{ entry.name }}</strong>
<span v-if="entry.size">- {{
bytesToSize(entry.size) }}</span>
</li>
</ul>
</transition>
</div>
</script>
现在,将以下 CSS 添加到文档的标题或单独的样式表(如果已有样式表的话):
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
通过 transition 元素,Vue 可以根据转换的状态和时间添加和删除各种 CSS 类。所有这些都以通过属性传入的名称开头,并附加当前转换阶段:
在浏览器中尝试该应用,您会注意到加载容器淡出,文件列表淡入。虽然在这个基本示例中,淡入淡出完成后列表会跳起来,但这是一个帮助您理解在 Vue 中使用转换的示例。
总结
在本章中,我们学习了如何制作 Dropbox viewer,这是一个单页应用,它列出了 Dropbox 帐户中的文件和文件夹,并允许我们通过更新代码来显示不同的文件夹内容。我们已经学习了如何将基本加载状态添加到应用中,并使用 Vue 动画进行导航。
在第 5 章、浏览文件树并从 URL加载文件夹中,我们将浏览我们的应用文件夹,并向我们的文件添加下载链接。
版权属于:月萌API www.moonapi.com,转载请注明出处