作者:LeanCloud weakish
最近团队外部须要一个上传文件的 web 小工具,须要写一个简略的前端页面。像这样的小工具,如果引入 React 和 Vue,仿佛太重了,所以想尝试下 Svelte 这个无框架之框架(最终会编译成不带框架的 JS 代码)。
闲话少叙,间接上手。首先,生成模板我的项目:
npx degit sveltejs/template fileup
长期以来 Svelte 的一大痛点是不反对 TypeScript,不过去年开始也退出了 TypeScript 反对。当然,像这样简略的小工具,间接用 JavaScript 写也没什么差异。不过我还是打算用下 TypeScript。
和其余一些模板生成工具不同,Svelte 官网没有提供独自的 TypeScript 模板我的项目仓库,也不会在生成模板的过程中让你抉择是用 TypeScript 还是 JavaScript,而是在生成模板我的项目后,运行一个脚本把我的项目转成 TypeScript 我的项目:
node scripts/setupTypeScript.js
转换之后,执行惯例的依赖装置步骤,就能够运行了:
npm install
npm run dev
我的项目应用 npm 治理依赖,应用 rollup 打包,这些都不必操心,对于简略我的项目而言,只需批改 src/App.svelte
即可,模板、款式、交互逻辑都写在这一个文件中(这和 Vue 有点像):
<script lang="ts">
// TypeScript 代码
</script>
<style>
/* CSS 代码 */
</style>
<!-- Svelte 模板代码 -->
先来编写上传界面,google 一下,找到一个现成的组件 svelte-file-dropzone
npm i svelte-file-dropzone
将它退出依赖,在 App.svelte
的 script
局部引入,并编写相应的 TypeScript 代码和 Svelet 模板代码:
<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