做者:LeanCloud weakishhtml
最近团队内部须要一个上传文件的 web 小工具,须要写一个简单的前端页面。 像这样的小工具,若是引入 React 和 Vue,彷佛过重了,因此想尝试下 Svelte 这个无框架之框架(最终会编译成不带框架的 JS 代码)。前端
闲话少叙,直接上手。 首先,生成模板项目:node
npx degit sveltejs/template fileup
长期以来 Svelte 的一大痛点是不支持 TypeScript,不过去年开始也加入了 TypeScript 支持。 固然,像这样简单的小工具,直接用 JavaScript 写也没什么差异。 不过我仍是打算用下 TypeScript。react
和其余一些模板生成工具不一样,Svelte 官方没有提供单独的 TypeScript 模板项目仓库,也不会在生成模板的过程当中让你选择是用 TypeScript 仍是 JavaScript,而是在生成模板项目后,运行一个脚本把项目转成 TypeScript 项目:git
node scripts/setupTypeScript.js
转换以后,执行常规的依赖安装步骤,就能够运行了:github
npm install npm run dev
项目使用 npm 管理依赖,使用 rollup 打包,这些都不用操心,对于简单项目而言,只需修改 src/App.svelte
便可,模板、样式、交互逻辑都写在这一个文件中(这和 Vue 有点像):web
<script lang="ts"> // TypeScript 代码 </script> <style> /* CSS 代码 */ </style> <!-- Svelte 模板代码 -->
先来编写上传界面,google 一下,找到一个现成的组件 svelte-file-dropzonetypescript
npm i svelte-file-dropzone
将它加入依赖,在 App.svelte
的 script
部分引入,并编写相应的 TypeScript 代码和 Svelet 模板代码:npm
<script lang="ts"> import Dropzone from "svelte-file-dropzone"; let files: File[] function handleFilesSelect(e) { files = e.detail.acceptedFiles } </script> <Dropzone on:drop={handleFilesSelect}> Click to select files, or drag and drop some files here. </Dropzone>
获取选定的文件以后,再上传文件。 文件会上传到 LeanCloud,LeanCloud 是一家 BaaS 云服务商,也提供文件托管服务。 「svelte」的意思是「slender and elegant」,和「lean」也算是近义词,从这个角度说,这两个听起来还挺配的。编程
一样,咱们先把 LeanCloud 的 JavaScript SDK 加入依赖:
npm i leancloud-storage
而后初始化 SDK:
import LC from "leancloud-storage"; const appId = "your app id"; const appKey = "your app key"; const serverURL = "https://your-custom-domain.example.com"; LC.init({ appId, appKey, serverURL, });
appID
和 appKey
能够从 「LeanCloud 控制台 > 设置 > 应用 Keys」查看,serverURL
是在 LeanCloud 绑定的域名。 固然,这须要首先在 LeanCloud 注册帐号并建立应用。 应有关部门的要求,LeanCloud 国内版须要绑定已备案的域名,若是不想绑域名或者域名没有备案,能够用 LeanCloud 国际版。
国际版初始化时无需传入 serverURL
:
LC.init({ appId, appKey });
上传文件很是简单,只需两行代码:
async function uploadFile(toUpload): Promise<String> { const uploaded = await new LC.File(toUpload.name, toUpload).save(); return uploaded.get("url"); }
上面的代码中,用 new LC.File(文件名, 文件)
构建文件后,调用 save
方法保存到云端,以后就能够经过 url
属性获得能够访问该文件的 URL。
到目前为止,咱们已经完成了最核心的功能,选取文件和上传文件,只剩下最后一步,把获取的 URL 显示给用户了。
{#if files} <h2>Files</h2> {#each files as file, i} {#await uploadFile(file)} <p>Uploading {file.name} ({file.size} bytes) ...</p> {:then url} <p>Uploaded: <code>{url ?? ""}</code> </p> {:catch error} <pre>{error}</pre> {/await} {/each} {/if}
这里用到了 Svelte 的模板语法。 估计是为了节省写解析器的功夫,Svelte 的模板语法看起来有点别扭(#if
、/if
、:catch
),可是忽略这些视觉上小小的不适,总体上仍是清晰易读的。 先用 if
判断是否选取了文件,只有在选取了文件的状况下,才会显示文件列表。 接着用 each
遍历全部选中文件,进行上传操做,并在上传过程当中显示文件的名称和大小,上传完成后则显示文件的 URL。 固然,几乎全部程序都少不了错误处理的部分。 由于这是一个内部工具,因此就直接在网页上显示错误信息了,没额外作更多处理。 注意这里用了 await
等待上传文件的异步函数返回结果,获取到结果后将它赋值给 url
变量,而后就能够直接在界面中使用 url
变量了。
好了,大功告成,不到 50 行代码,就完成了这个简单的上传工具。 回头看看代码,很是直截了当。 但仔细想一想,仍是很神奇的,好比只是经过 files = e.detail.acceptedFiles
这一行赋值操做,界面就能感知到 files
的变化,相应地渲染不一样的内容。 这是由于 Svelte 会把 =
编译为相似 React 等框架中的 setState 方法。 有些人可能以为这有些太魔法了,但其实大多数编程语言中 =
就挺魔法的,好比会有 x = x + 1
; 这样的语句,只是你们都习惯了而已。
最后须要把它部署到一个地方。 由于是个纯静态页面,因此部署到什么地方都行。 既然文件托管已经用了 LeanCloud,那网页也部署到 LeanCloud 吧。
运行如下命令编译、打包项目:
npm run build
而后运行如下命令便可部署至 LeanCloud:
cd public lean switch --region CN --group web YOUR_APP_ID lean deploy --prod 1
这里 CN
表示 LeanCloud 华北节点,web
是云引擎分组的名称,若是使用了其余节点或者 LeanCloud 国际版,或者分组名称不一样,须要修改相应的值,具体能够查看「LeanCloud 控制台 > 云引擎 > 云引擎分组 > 部署 > 命令行工具」的说明。
若是没有安装 LeanCloud 命令行工具,须要先安装并关联帐号,关联帐号的步骤一样能够上述控制台区域找到。 另外,要访问部署在云引擎上的页面,还须要绑定一个云引擎域名,或者申请一个 avosapps.us
下的子域名(仅限国际版)。
下面是部署后的效果图:
能够看到,为了方便复制 URL,我加了复制到剪贴板的按钮。 使用 svelte-copy-to-clipboard 组件:
npm i svelte-copy-to-clipboard
只需添加 10 行代码:
<script lang="ts"> import CopyToClipboard from "svelte-copy-to-clipboard"; // 略 function handleSuccessfulCopy(i) { copyStatuses[i] = '✅' } function handleFailedCopy(i) { copyStatuses[i] = '❌' } </script> <!-- 略 --> {#if files} <h2>Files</h2> <!-- 略 --> {:then url} <p>Uploaded: <code>{url ?? ""}</code> <CopyToClipboard text={url} on:copy={() => handleSuccessfulCopy(i)} on:fail={() => handleFailedCopy(i)} let:copy> <button on:click={copy}>{copyStatuses[i]}</button> </CopyToClipboard> </p> <!-- 略 --> {/if}
若是但愿进一步改善用户体验,还能够在上传时显示进度。 这项改进就留给读者做为练习(提示)。
不能免俗,用 LightHouse 跑个分:
以前写页面的时候我并无考虑性能,但性能评分仍然达到了 100。 SEO 和可访问性方面有些小问题,改起来不麻烦,一样留给读者做为练习。 好吧,你也许已经发现了,我只是在为我本身的懒惰找借口。 不过,若是你真的完成了这些练习,欢迎来提 pr。
写到这里差很少要结束了,总结一下。 就小工具和交互很少的站点而言,Svelte 写起来更加直截了当,和 React、Vue 相比,编写的代码更加简明扼要, 套路代码(boilerplate code)更少,编译出的代码更加轻量,所以对我的健康(节省键盘敲击次数,避免肌肉劳损)和世界环境(访问者加载和运行的代码更少,显著下降碳排量)都更友好。 Svelte 这样的无框架(frameless)框架和 LeanCloud 这样的无服务器(serverless)云服务,抽象掉了大量无关业务的细节,可让开发者专一项目的核心功能,提高开发效率,改善开发体验。
题图 Paul Gilmore