svelte 與其餘框架javascript
簡單瞭解語法css
組件html
svelte
不知道你們有沒有了解過,最近一次偶然刷文章,看到一篇《都快2020年,你還沒據說過SvelteJS?》 [0] 的文章,看了svelte與其餘框架的對比前端
svelte 中文 doc [1]vue
對比各框架開發的項目的尺寸java
對比各項目的 Lighthouse 性能評分node
說實話屬實有點驚訝到我。 ** 真的假的?react
因而我抱着試試就試試的心態來作個評測人git
svelte 的做者 Rich Harris 在一篇名爲《虛擬DOM純粹是開銷》 [2] 的文章中指出,爲何不使用虛擬domgithub
虛擬dom的三個步驟
<div>
,這意味着咱們能夠保留相同的DOM節點<div>
以查看是否須要更改,添加或刪除任何屬性。在這兩種狀況下,咱們都有一個屬性-aclassName
的值爲"greeting"
而 svelte 直接跳過前面兩步,直接執行第三步
if (changed.name) { text.data = name; }
這幾乎就是Svelte生成的更新代碼。與傳統的UI框架不一樣,Svelte是一種編譯器,它在構建時就知道應用程序中的狀況如何變化,而沒必要等着在運行時進行工做。
vue 的做者尤雨溪,在知乎回答了個 《如何看待 svelte 這個前端框架?》 [3] 問題
「svelte 的核心思想在於 經過靜態編譯來減小框架運行時的代碼」
我覺着這兩個ui仍是比較不錯的
Material UI
https://github.com/hperrin/sv...
SVELTESTRAP
https://github.com/bestguy/sv...
老嚴閒來的時候找到了 一個叫作 Realworld
存儲庫中有24種conduit實現As ,也就是用來對比性能的以及大小的;
今天一塊兒來對比一下 vue/react/svelte 這三個框架的
vue:https://github.com/gothinkste...
react:https://github.com/gothinkste...
svelte:https://github.com/sveltejs/r...
感興趣的同窗也能夠看看其餘框架 https://github.com/gothinkste...
這三個項目,打包順序基本上在同一時間執行 npm run build
,svelte 直接在我我眨眼的一瞬間打完包 ,啪 很快啊 (有點誇張~幾秒鐘)
靜靜的等待vue和react同時打包完以後,我開始進行統一壓縮靜態文件,壓縮格式爲zip
排名以下
果真差距仍是確實如傳說同樣恐怖
嚴老溼本次使用 Chrome 的 Lighthouse (谷歌網頁性能分析工具) 來對比性能評分
全局安裝 lighthouse
npm install -g lighthouse
執行 (直接使用的對應的線上地址)
lighthouse https://realworld.svelte.dev/
這是我在下面所測試的截屏
vue
react
svelte
性能得分排名以下:
svelte
也是不負衆望 穩居第一
看到上面,每天被逼着作性能優化的同窗,激動起來了 ~ 那咱們一塊兒來簡單學習一下這個性能強悍的 svelte 吧
svelte 模板 [4] ,咱們直接使用一個模板來開工
git clone https://github.com/sveltejs/template & cd template-master
yarn install or npm install
下載完成以後,咱們看看目錄。老嚴的評價就是 簡潔
yarn dev or npm run dev
啓動完成以後
Your application is ready~! � - Local: http://localhost:5000 - Network: Add `--host` to expose
地址欄輸入 http://localhost:5000
咱們能夠看到這樣的一個頁面 hello world
這裏咱們使用 sveltestrap
npm install --save sveltestrap npm install --save bootstrap
在 main.js 中引入
import 'bootstrap/dist/css/bootstrap.min.css';
在頁面中引入組件
<script> import { Button } from "sveltestrap"; const handleClick = () => alert("I warned you!"); </script> <Button color="danger" on:click={handleClick}>Do Not Press</Button>
在學習以前我以爲有必要簡單瞭解一下其語法
在 vue 中咱們的變量須要寫在 data
中 ,而 svelte
語法更加貼合原生
<!-- vue --> data() { return { name: 'hhh', }; } <div>{{name}}</div>
svelte 綁定數據 ,svelte 動態綁定須要加上 {}
<script> import { Button } from "sveltestrap"; // 定義數據 let name = "hhh"; let src = 'http://crazy-x-lovemysoul-x-vip.img.abc188.com/images/logo.png'; </script> <!-- 綁定數據 --> <!-- 若是kv一致只用寫一個 --> <img {src} alt=""> <Button>{name}</Button>
vue 中有條件渲染 v-if
v-else-if
v-else
,svelte 也有
<script> let condition = 1; </script> {#if condition == 2} <p>悲</p> {:else if condition == 1} <p>傷 </p> {:else if condition == 0} <p>日</p> {:else} <p>記</p> {/if}
循環渲染列表
<script> // 定義變量 let news = [ { id: 1, title: '拜登呼籲必須中止把對手當敵人' }, { id: 2, title: '江蘇響水致78死爆炸案一審宣判' }, { id: 3, title: '嫦娥五號將擇機實施月面軟着陸' } ]; </script> <ul> <!-- 有沒有點 ejs的感受 --> {#each news as {title}} <li> <a href="https://www.baidu.com/s?rsv_idx=1&wd={title}"> {title} </a> </li> {/each} </ul> <style> ul,li{ list-style: none; } a{ color: #ff3e00; } </style>
咋感受有點像 ejs
循環渲染呢 [5]呢?
在 svelte
中方法直接寫函數定義函數便可使用
<script> import { Button } from "sveltestrap"; // 定義數據 let name = "hhh",title = '標題'; // 定義方法 const handleClick = () => { name = "嚴老溼" title = "老嚴帶你入坑 svelte" }; </script> <!-- on:click 綁定方法 {綁定動態值}--> <Button color="danger" on:click={handleClick}>{name}</Button> <h1>{title}</h1>
組件是框架必不可少的一個功能
來看看 svelte 中如何建立一個組件吧
app.svelte
<script> // 直接引入組件便可使用 無需註冊 import Child from './components/child.svelte' let name = '我是你爹' </script> <div> {name} <Child></Child> </div>
建立一個 child.svelte 頁面
<script> let title = '我是你兒子' </script> <div>{title}</div>
那麼組件有了,咱們來看看組件傳值吧!
app.svelte
<script> import Child from './components/child.svelte' let name = '我是你爹' let childName = "狗剩" </script> <div> {name} <Child {childName}></Child> </div>
child.svelte
<script> export let childName; </script> <div>爹給我取的名字是 {childName}</div>
剛剛咱們是簡單的單一傳值
接下來咱們傳一個對象試試
app.svelte
<script> import Child from './components/child.svelte' let name = '我是你爹' let aboutMe = { name:'狗剩', age:18, gender:'man' } </script> <div> {name} <!-- 經過... 展開 aboutMe --> <Child {...aboutMe}></Child> </div>
child.svelte
<script> export let name,gender,age; </script> <div>我取的名字是 {name}</div> <div>我取的年齡是 {age}</div> <div>我取的性別是 {gender}</div>
那這多費勁吶?還須要一個個接收。有一話叫存在即合理
在官方 api 中提到 svelte 提供了一些動畫效果出來給你們使用
咱們直接使用官方示例 淡入淡出動畫
<script> import { fade } from 'svelte/transition'; let visible = true; </script> <label> <input type="checkbox" bind:checked={visible}> visible </label> {#if visible} <p transition:fade> Fades in and out </p> {/if}
在 svelte 中的生命週期有onMount 、beforeUpdate 、afterUpdate 、afterUpdate 下面老嚴依次給你們夥列出來
該onMount
函數做爲將component掛載到DOM後當即執行的回調。它必須在component初始化期間被調用(但沒必要位於component內部;能夠從外部模塊調用它)。
<script> import { onMount } from 'svelte'; onMount(() => { console.log('the component has mounted'); }); </script>
若是須要onMount
返回一個函數,則在卸載 component 時調用該函數。
<script> import { onMount } from 'svelte'; onMount(() => { const interval = setInterval(() => { console.log('beep'); }, 1000); return () => clearInterval(interval); }); </script>
beforeUpdate
任何狀態更改後組件更新以前,回調函數會當即運行。第一次回調運行將在初始onMount以前.
<script> import { beforeUpdate } from 'svelte'; beforeUpdate(() => { console.log('the component is about to update'); }); </script>
afterUpdate
在組件更新後當即運行回調
<script> import { afterUpdate } from 'svelte'; afterUpdate(() => { console.log('the component just updated'); }); </script>
在組件卸載後運行回調。在onMount、beforeUpdate、afterUpdate和onDestroy中,這是惟一一個在服務器端組件中運行的組件。4
<script> import { onDestroy } from 'svelte'; onDestroy(() => { console.log('the component is being destroyed'); }); </script>
老嚴逛着逛着 正好看到一個 官方示例的 to do list
原本還想着說帶你們作,那既然有現成的,將就一下
沒有什麼框架是寫一個 todolist 還學不會的 ,老嚴在代碼裏面也加了一些代碼註釋
由於樣式代碼 太多,咱們先上效果圖再看代碼
<script> import { quintOut } from 'svelte/easing'; import { crossfade } from 'svelte/transition'; import { flip } from 'svelte/animate'; // 動畫 const [send, receive] = crossfade({ duration: d => Math.sqrt(d * 200), fallback(node, params) { const style = getComputedStyle(node); const transform = style.transform === 'none' ? '' : style.transform; return { duration: 600, easing: quintOut, css: t => ` transform: ${transform} scale(${t}); opacity: ${t} ` }; } }); let uid = 1; // 默認數據 let todos = [ { id: uid++, done: false, description: 'write some docs' }, { id: uid++, done: false, description: 'start writing blog post' }, { id: uid++, done: true, description: 'buy some milk' }, { id: uid++, done: false, description: 'mow the lawn' }, { id: uid++, done: false, description: 'feed the turtle' }, { id: uid++, done: false, description: 'fix some bugs' }, ]; // 新增待辦 function add(input) { const todo = { id: uid++, done: false, description: input.value }; todos = [todo, ...todos]; input.value = ''; } // 刪除方法 function remove(todo) { todos = todos.filter(t => t !== todo); } // 選中方法 function mark(todo, done) { todo.done = done; remove(todo); todos = todos.concat(todo); } </script> <div class='board'> <!-- 點擊回車執行add --> <input placeholder="what needs to be done?" on:keydown={e => e.which === 13 && add(e.target)} > <!-- 代辦 --> <div class='left'> <h2>todo</h2> {#each todos.filter(t => !t.done) as todo (todo.id)} <label in:receive="{{key: todo.id}}" out:send="{{key: todo.id}}" animate:flip > <!-- 選中表明已作完 --> <input type=checkbox on:change={() => mark(todo, true)}> {todo.description} <!-- 刪除 --> <button on:click="{() => remove(todo)}">remove</button> </label> {/each} </div> <!-- 已完成 --> <div class='right'> <h2>done</h2> {#each todos.filter(t => t.done) as todo (todo.id)} <label class="done" in:receive="{{key: todo.id}}" out:send="{{key: todo.id}}" animate:flip > <!-- 修改狀態爲代辦 --> <input type=checkbox checked on:change={() => mark(todo, false)}> {todo.description} <!-- 刪除 --> <button on:click="{() => remove(todo)}">remove</button> </label> {/each} </div> </div> <style> .board { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 1em; max-width: 36em; margin: 0 auto; } .board > input { font-size: 1.4em; grid-column: 1/3; } h2 { font-size: 2em; font-weight: 200; user-select: none; margin: 0 0 0.5em 0; } label { position: relative; line-height: 1.2; padding: 0.5em 2.5em 0.5em 2em; margin: 0 0 0.5em 0; border-radius: 2px; user-select: none; border: 1px solid hsl(240, 8%, 70%); background-color:hsl(240, 8%, 93%); color: #333; } input[type="checkbox"] { position: absolute; left: 0.5em; top: 0.6em; margin: 0; } .done { border: 1px solid hsl(240, 8%, 90%); background-color:hsl(240, 8%, 98%); } button { position: absolute; top: 0; right: 0.2em; width: 2em; height: 100%; background: no-repeat 50% 50% url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23676778' d='M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M17,7H14.5L13.5,6H10.5L9.5,7H7V9H17V7M9,18H15A1,1 0 0,0 16,17V10H8V17A1,1 0 0,0 9,18Z'%3E%3C/path%3E%3C/svg%3E"); background-size: 1.4em 1.4em; border: none; opacity: 0; transition: opacity 0.2s; text-indent: -9999px; cursor: pointer; } label:hover button { opacity: 1; } </style>
當你能夠手動寫出這個todolist的時候,你就已經出師了,由於老嚴也就這點能耐 哈哈
最後代碼,我提交到了git 有須要的同窗能夠去下載噢
git clone git@github.com:CrazyMrYan/study-svelte.git
[0] https://zhuanlan.zhihu.com/p/...
[2] https://svelte.dev/blog/virtu...
[3] https://www.zhihu.com/questio...
[4] https://github.com/sveltejs/t...
[5] https://ejs.bootcss.com/#docs