Svelte
的做者也是 rollup
的做者 Rich Harris,前端界的輪子哥。sevlte
項目首次提交於 2016 年 11 月 16 日,目前版本是 3.6.1
(2019-06-27),v3 版本進行了大改動,跟以前的版本有很大的差異(v一、v2 版本 API 用法跟 vue 很像,v3 徹底屬於本身的風格)。html
看下 2016-12-02,尤雨溪大神對此框架的評價(固然已通過時了,可是核心的思想仍是一致的):前端
這個框架的 API 設計是從 Ractive 那邊傳承過來的(天然跟 Vue 也很是像),但這不是重點。Svelte 的核心思想在於『經過靜態編譯減小框架運行時的代碼量』。舉例來講,當前的框架不管是 React Angular 仍是 Vue,無論你怎麼編譯,使用的時候必然須要『引入』框架自己,也就是所謂的運行時 (runtime)。可是用 Svelte 就不同,一個 Svelte 組件編譯了之後,全部須要的運行時代碼都包含在裏面了,除了引入這個組件自己,你不須要再額外引入一個所謂的框架運行時!
Svelte
跟 vue 和 react同樣,是一個數據驅動組件框架。可是也有很大的不一樣,它是一個運行時框架,無需引入框架自己,同時也沒用到虛擬 DOM(運行時框架特性決定了這個框架跟虛擬 DOM 無緣)。vue
Svelte runs at build time, converting your components into highly efficient imperative code that surgically updates the DOM. As a result, you're able to write ambitious applications with excellent performance characteristics.
雖然沒使用到虛擬 DOM,但同樣能夠達到出色的性能,並且對開發者編寫代碼是十分便捷。react
那麼咱們先看下 svelte
的由於意思:苗條的。苗條的框架正是做者的初始目的,苗條包括代碼編寫量、打包大小等等。webpack
總結一下這個框架的優點,即做者開發新框架的目的。git
一個 Svelte 組件是靜態編譯,全部須要的運行時代碼都包含在裏面了,除了引入這個組件自己,你感受不到框架存在。github
svelte 模板提供一些簡便的用法,在維護和編寫上都變得更簡單,代碼量更少(維護的代碼),這些模板會編譯爲最終的js 代碼。web
即 tree shaking,這個概念原本也是做者首先提出來的,webpack 是參考了 rollup。前端框架
既有響應式數據的優勢,v3 版本也解決了 vue 數據綁定缺點,用起來十分方便。app
react hook
import React, { useState } from 'react'; export default () => { const [a, setA] = useState(1); const [b, setB] = useState(2); function handleChangeA(event) { setA(+event.target.value); } function handleChangeB(event) { setB(+event.target.value); } return ( <div> <input type="number" value={a} onChange={handleChangeA}/> <input type="number" value={b} onChange={handleChangeB}/> <p>{a} + {b} = {a + b}</p> </div> ); };
vue
<template> <div> <input type="number" v-model.number="a"> <input type="number" v-model.number="b"> <p>{{a}} + {{b}} = {{a + b}}</p> </div> </template> <script> export default { data: function() { return { a: 1, b: 2 }; } }; </script>
svelte
<script> let a = 1; let b = 2; </script> <input type="number" bind:value={a} /> <input type="number" bind:value={b} /> <p>{a} + {b} = {a + b}</p>
都不用多說,一眼就看出來,svelte 簡單多了。
在 react 和 vue 盛行的時代,你會據說虛擬 DOM 速度快,並且還可能被灌輸一個概念,虛擬 DOM 的速度比真實 DOM 的速度要快。
因此若是你有這個想法,那麼你確定疑惑 svelte 沒用到虛擬 DOM,它的速度爲何會快?
其實虛擬 DOM 並非何時都快,看下粗糙的對比例子。
這裏並無直接統計渲染的時間,經過不少條數據咱們就能夠感覺出來他們直接的性能。特別是點擊每條數據的時候,明顯感受出來(因爲是在線上的例子,因此首次渲染速度不許確,主要看點擊的響應速度)。
固然這僅僅是在 50000 條數據下的測試,對比一下框架所謂的速度,實際的狀況下咱們是不會一次性展現這麼多數據的。因此在性能還可行的狀況下,更多的選擇是框架所帶來的的便利,包括上手難度、維護難度、社區大小等等條件。
svelte
https://svelte.dev/repl/367a2...
<script> import { onMount } from "svelte"; const = []; for (let i = 0; i < 50000; i++) { list.push(i); } const beginTime = +new Date(); let name = "world"; let data = list; function click(index) { return () => { data[index] = "test"; }; } onMount(() => { const endTime = +new Date(); console.log((endTime - beginTime) / 1000, 1); }); </script> {#each data as d, i} <h1 on:click={click(i)}> <span> <span> <span> <span>Hello {name} {i} {d}!</span> </span> </span> </span> </h1> {/each}
vue
<div id="component-demo" class="demo"> <div v-for="(d, i) in list" @click="click(i)"> <span> <span> <span> <span> Hello {{name}} {{i}} {{d}}! </span> </span> </span> </span> </div> </div>
const list = [] for(let i = 0; i < 50000; i++) { list.push(i); } const beginTime = +new Date(); new Vue({ el: '#component-demo', data: { list: list, name: 'Hello' }, methods:{ click(index){ const list = new Array(50000); list[index] = 'test' this.list = list } }, mounted(){ const endTime = +new Date(); console.log((endTime - beginTime) / 1000,1); } })
react
const list = [] for(let i = 0; i < 50000; i++) { list.push(i); } class App extends React.Component { constructor(props){ super(props); this.state = { list } } click(i) { return ()=>{ list[i] = 'test' this.setState({ list, }) } } render() { return ( <div> {this.state.list.map((v,k)=>{ return( <h1 onClick={this.click(k)}> <span> <span> <span> <span> Hello wolrd {k} {v}! </span> </span> </span> </span> </h1> ) })} </div> ) } } function render() { ReactDOM.render( <App />, document.getElementById('root') ); } render();
首先虛擬 DOM 不是一個功能,它只是實現數據驅動的開發的手段,沒有虛擬 DOM 咱們也能夠實現數據驅動的開發方式,svelte 正是作了這個事情。
單純從上面的對比例子來看,svelte 的速度比虛擬 DOM 更快(不一樣框架虛擬 DOM 實現會有差異)。雖然沒有進行更深層次的對比,可是若是認爲虛擬 DOM 速度快的觀點是不徹底對的,應該說虛擬 DOM 能夠構建大部分速度還能夠的 Web 應用。
徹底兼容原生 html 用法
編寫代碼是那麼的天然,以下面就是一個組件。
<script> const content = 'test'; </script> <div> { test } </div>
響應式也是那麼的天然
<script> let count = 0; function handleClick () { // calling this function will trigger an // update if the markup references `count` count = count + 1; } </script> <button on:click="handleClick">+1</button> <div>{ count }</div>
表達式也能夠是響應式的
這個就牛逼了,更加的天然,這種特性只有靜態編譯才能作到,這個就是 svelte 目前獨有的優點。
<script> let numbers = [1, 2, 3, 4]; function addNumber() { numbers.push(numbers.length + 1); } $: sum = numbers.reduce((t, n) => t + n, 0); </script> <p>{numbers.join(' + ')} = {sum}</p> <button on:click={addNumber}>Add a number</button>
自動訂閱的 svelte store
這個其實就是訂閱發佈模式,不過 svelte 提供了自身特有的便捷的綁定方式(自動訂閱),用起來是那麼的天然,那麼的爽。
這種特性只有靜態編譯才能作到,這個就是 svelte 目前獨有的優點。
stores.js
import { writable } from 'svelte/store'; export const count = writable(0);
A.svelte
<script> import { count } from './stores.js'; </script> <h1>The count is {$count}</h1>
B.svelte
<script> import { count } from './stores.js'; function increment() { $count += 1; } </script> <button on:click={increment}>增長</button>
全部組件均可以單獨使用
能夠直接在 react、vue、angular 等框架中使用。
// SvelteComponent.js 是已經編譯後的組件 import SvelteComponent from './SvelteComponent'; const app = new SvelteComponent({ target: document.body, props: { answer: 42 } });
svelte 是一個剛起步不久的前端框架,不管在維護人員仍是社區上都是大大不如三大框架,這裏列舉一下本人認爲的 svelte 存在的缺點。
props 是可變的
固然這也是這個框架故意這樣設計的,這樣 props 也是能夠響應式的。
<script> export let title; title = '前綴' + title </script> <h1> { title } </h1>
props 目前沒法驗證類型
<script> export let propOne; export let propTwo = 'defaultValue'; </script>
沒法經過自定義組件自己直接訪問原生 DOM
須要利用 props 的雙向綁定特性,這就可能致使深層次組件的須要層層傳遞 DOM 對象(是子父傳遞,不是父子傳遞)。
App.svelte
<script> export let customDOM; </script> <A bind:dom={customDOM} /> <!--bind:this 是無用的,只有再原生纔有用-->
A.svelte
<script> export let dom; </script> <div bind:this={dom}> test </div>
只有組件才支持 svelte 的靜態模板特性
js 文件是不支持 sevelte 靜態模板特性的,像下面這樣是會報錯的。
import { count } from './stores.js'; function increment() { $count += 1; }
找了一下,沒找到能夠支持 ts 的解決方案,若是有解決方案能夠評論下。
學習和總結文章同步發佈於 https://github.com/xianshanna...,有興趣能夠關注一下,一塊兒學習和進步。