Svelte
Svelte用于构建快速Web应用程序。
Svelte与React和Vue一样,致力于让轻松构建灵活、交互式的用户界面。
不同之处在于,Svelte在构建时将代码转换为更好的JavaScript,而不是在运行时解释和执行代码。
这意味着不必支付框架本身的性能成本,并且在首次加载时不会有额外的性能损失。
可以使用Svelte编写整个应用程序,也可以使用Svlte逐步重构现有代码;也可以只输出一个独立的组件(不强制附加框架本身),并在任何框架中使用它。
<script>
let name = 'world';
</script>
<h1>Hello world!</h1>
在大括号中,我们可以编写任意JavaScript。
然后可以尝试将名称更改为name。toUpperCase()以使问候更加强烈。
注意:看起来正在创建一个全局变量,但实际上,name仍然限于组件的局部变量,也就是说,无法访问全局对象(Window)中组件中声明的name变量。
<script>
let src = 'tutorial/image.gif';
</script>
<img>
样式
对于特定的函数,Svelte仍然有相应的运行时代码,例如组件逻辑、if/else切换逻辑、循环逻辑等。但是在编译时,如果没有使用函数,则相应的代码根本不会编译成结果。就像Babel中未使用的函数的助手不会被引入一样,就像使用lodash或RxJS时,只有相应的函数被选择性地引入一样。
<img src={src} alt="A man dances.">
基于这两个特性,Svelte应用程序的最终代码量可能非常小。例如,它的TodoMVC min+gzip仅晚了3kb。
然而,Svelte并非没有潜在问题:
(1) 尽管简单演示中的代码量确实很小,但同一组件模板通过这种隐式操作生成的代码量将大于vdom渲染函数的代码量,并且多个组件中会有大量重复代码(尽管gzip可以缓解这个问题,但解析和求值是不可避免的)。
项目中的组件越多,代码量的差异就越小。
同时,它并不是广告中所说的“没有运行时”,而是根据代码按需导入。
使用的函数越多,Svelte需要包含的运行时代码就越多。很难说它在实际生产项目中会有多大的规模优势。
(2) Svelte在大型应用程序中的性能仍有待观察,尤其是在大量动态内容和嵌套组件的情况下。它的更新策略决定了它还需要一个类似于React的shouldComponentUpdate的机制来防止过度更新。
<style>
p {
color: purple;
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
}
</style>
<p>这是一段话。</p>
嵌套组件
将整个应用程序放在一个组件中是不切实际的。相反,我们可以从其他文件导入组件,并将其作为包含元素包含。
请注意,即使Nested Svelte具有<p>元素,App的Svelte风格也不受影响。
还要注意,组件名称Nested是大写的。此约定用于使我们能够区分用户定义的组件和常规HTML标记。
<script>
import Nested from './Nested.svelte';
</script>
前端
通常,字符串以纯文本形式插入,这意味着<和>等字符没有特殊含义。
但有时需要将HTML直接呈现到组件中。例如,正在阅读的单词现在存在于markdown文件中,该文件以HTML的形式包含在本页中:
<script>
let string = `this string contains some <strong>HTML!!!</strong>`;
</script>
<p>{string}</p>
Svelte在将{@html…}中的表达式插入DOM之前不会清理它们。换言之,如果使用此功能,则必须手动从不受信任的源中转义HTML,否则可能会使用户暴露于XSS攻击。
一个App实例
还需要配置文本编辑器。如果正在使用VS代码,请安装Svelte扩展。否则,请按照本指南中的说明配置文本编辑器,以便。svelte文件与相同。html来突出显示语法。
然后,一旦项目建立,就可以轻松地使用Svelte组件。编译器将每个组件转换为一个常规JavaScript类-只需导入并使用new来实例化:
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
answer: 42
}
});
有时,检查流经应用程序的数据是有用的。
一种解决方案是使用控制台。标记内的log(…)。但是,如果要暂停执行,可以将{@debug…}标记与要检查的值的逗号分隔列表一起使用:
<script>
let user = {
firstname: 'Ada',
lastname: 'Lovelace'
};
</script>
{@debug user}
<h1>Hello {user.firstname}!</h1>
笔记
可以在组件中使用HTML注释。
以svelte ignore开头的内容将被注释掉,直到在注释结束标记处结束。一般来说,带注释的内容包含可访问性(a11y,一些有助于提高可访问性的信息)信息,因此请仅在有充分理由时使用。
<!-- 这是一句注释! -->
<h1>Hello world</h1>
如果键是一个表达式,它必须是唯一的,以标识列表中的每个列表项,以便Svelte可以更改列表中任何位置的数据,而不是在末尾添加或删除数据。密钥可以是任何对象,但建议使用字符串和数字,因为它们允许在对象本身更改时保留标识。
{#each items as { id, name, qty }, i (id)}
<li>{i + 1}: {name} x {qty}</li>
{/each}
{#each objects as { id, ...rest }}
<li><span>{id}</span><MyComponent {...rest}/></li>
{/each}
{#each items as [id, ...rest]}
<li><span>{id}</span><MyComponent values={rest}/></li>
{/each}
它可以与{@debug…}一起使用以替换控制台。日志(…)。每当指定变量的值发生变化时,它都会记录这些变量的值。如果打开devtools,代码执行将在{@debug…}语句的位置暂停。
它接受单个变量名。
可以使用的修改器有:
PreventDefault:调用事件。preventDefault()在程序运行之前
StopPropagation:调用事件。stopPropagation()以防止事件到达下一个标记
被动:提高了触摸/滚轮事件的滚动性能(Svelte将在适当的情况下自动添加)
捕获:表示其程序是在捕获阶段触发的,而不是通过冒泡触发的
一次:程序运行一次后删除自身
可以连接修饰符,例如:单击|once|capture={…}。
如果未为使用的on:命令事件指定特定值,则意味着组件将负责转发事件,这意味着组件的用户可以监听事件。
<script>
let counter = 0;
function increment() {
counter = counter + 1;
}
function track(event) {
trackEvent(event)
}
</script>
<button on:click={increment} on:click={track}>Click me!</button>