做者: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