🔥超级简单的Svelte,学不会你来打我
大约 4 分钟
Svelte作为后起之秀,近些年的热度已经盖过Angular了(上香!)
声明式API:Svelte的API是基于声明式编程风格的,这使得代码更易于理解和维护。组件化:Svelte支持组件化开发,使得代码可以更容易地重用和管理。响应式:Svelte具有内置的响应式功能,使得数据的变化可以自动更新视图。轻量级:由于Svelte不需要运行时库,因此生成的应用程序文件大小更小,加载速度更快。
Svelte框架的使用在近年来逐渐流行起来,被越来越多的开发者和公司所采用,如大型企业Netflix、IBM等。
一、模版语法
1.模版命名
Svelte的语法是基于HTML、CSS和JavaScript的,文件后缀名为.svelte
<!-- example.svelte -->
<script>
  let count = 0;
</script>
<button>
  Clicked {count}
</button>
<style>
</style>
2.插值表达式
使用双花括号 {} 来进行插值表达式,将表达式的值插入到模板中。例如:
<h1>Hello, {name}!</h1>
3.条件语句
使用 if 和 else 关键字来实现条件语句。例如:
{#if loggedIn}
  <h1>Welcome back, {user}!</h1>
{:else}
  <button on:click={login}>Log in</button>
{/if}
4.循环语句
使用 each 关键字来实现循环语句。例如:
{#each items as item}
  <li>{item}</li>
{/each}
5.组件引用
使用组件名来引用一个组件,然后像 HTML 标签一样使用它。例如:
<script>
import MyComponent from '/path/example.svelte'
</script>
<MyComponent />
6.事件处理
使用 on: 前缀来绑定事件处理函数。例如:
<button on:click={handleClick}>Click me!</button>
7.双向绑定
使用 bind: 前缀来实现双向绑定。例如:
<input type="text" bind:value={name} />
8.插槽语法
默认插槽
<!-- MyComponent.svelte -->
<div>
  <h2>{title}</h2>
  <slot></slot>
</div>
<!-- App.svelte -->
<MyComponent title="Hello">
  <p>World!</p>
</MyComponent>
具名插槽
<!-- MyComponent.svelte -->
<div>
  <h2>{title}</h2>
  <slot name="content"></slot>
</div>
<!-- App.svelte -->
<MyComponent title="Hello">
  <p slot="content">World!</p>
</MyComponent>
看完模版语法,可以说和vue时一脉相承
二、声明变量
不用任何修饰,直接定义就可以被捕获,对于开发者来说,依赖收集是无感的
<script>
  let count = 0;
  function handleClick() {
    count += 1;
  }
</script>
<button on:click={handleClick}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
三、监听变量的变化
 1.$方式
<script>
  let name = 'Alice';
  let age = 30;
  $: {
    console.log(`name 变为 ${name}`);
    console.log(`age 变为 ${age}`);
  }
</script>
<h1>{name}</h1>
<p>{age}</p>
 2.watch()接口
<script>
  import { watch } from 'svelte';
  let name = 'Alice';
  let age = 30;
  watch(
    [$name, $age],
    (currentValues, previousValues) => {
      console.log(`name 从 ${previousValues[0]} 变为 ${currentValues[0]}`);
      console.log(`age 从 ${previousValues[1]} 变为 ${currentValues[1]}`);
    }
  );
</script>
<h1>{name}</h1>
<p>{age}</p>
三、组件化
<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
</script>
<button>父组件内容</button>
<Child />
<!-- Child.svelte -->
<script>
</script>
<p>子组件内容</p>
1.组件之间通信
 props
<!-- Parent.svelte -->
<script>
  let name = 'Svelte';
</script>
<Child name={name} />
<!-- Child.svelte -->
<script>
  export let name;
</script>
<h1>Hello {name}!</h1>
 context
<!-- App.svelte -->
<script>
  import { createContext } from 'svelte';
  export const theme = createContext('light');
</script>
<svelte:options context="theme" />
<main>
  <h1>App</h1>
  <!-- ... -->
</main>
<!-- Header.svelte -->
<script>
  import { getContext } from 'svelte';
  import { theme } from './App.svelte';
  const currentTheme = getContext(theme);
</script>
<header class={currentTheme}>
  <h2>Header</h2>
  <!-- ... -->
</header>
 store
<!-- Counter.svelte -->
<script>
  import { writable } from 'svelte/store';
  export const count = writable(0);
</script>
<h1>Count: {$count}</h1>
<button on:click={() => $count += 1}>Increment</button>
<!-- DisplayCount.svelte -->
<script>
  import { count } from './Counter.svelte';
</script>
<h1>Count: {$count}</h1>
 EventBus
<!-- Sender.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  function handleClick() {
    dispatch('my-event', { message: 'Hello, world!' });
  }
</script>
<button on:click={handleClick}>Click me!</button>
<!-- Receiver.svelte -->
<script>
  import { onMount } from 'svelte';
  function handleEvent(event) {
    console.log(event.detail.message);
  }
  onMount(() => {
    window.addEventListener('my-event', handleEvent);
    return () => {
      window.removeEventListener('my-event', handleEvent);
    };
  });
</script>
2.生命周期钩子
onMount: 在组件挂载到 DOM 中后执行,类似于 Vue 中的mounted钩子。beforeUpdate: 在组件的数据更新前执行,类似于 Vue 中的beforeUpdate钩子。afterUpdate: 在组件的数据更新后执行,类似于 Vue 中的updated钩子。onDestroy: 在组件销毁后执行,类似于 Vue 中的destroyed钩子。
<!-- App -->
<script>
    import Father from "./Father.svelte"
    let show = true;
</script>
<button on:click={() => show = !show}>
    show
</button>
{#if show}
    <Father />
{/if}
<!-- Father.svelte -->
<script>
    import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';
    import Child from "./Children.svelte"
    onMount(() => console.log('father onMoute'))
    onDestroy(() => console.log('father onDestroy'))
    beforeUpdate(() => console.log('father beforeUpdate'))
    afterUpdate(() => console.log('father afterUpdate'))
</script>
<h1>Hello!</h1>
<Child />
<!-- Children.svelte -->
<script>
    import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';
    onMount(() => console.log('child onMoute'))
    onDestroy(() => console.log('child onDestroy'))
    beforeUpdate(() => console.log('child beforeUpdate'))
    afterUpdate(() => console.log('child afterUpdate'))
</script>
<h1>World!</h1>
执行顺序如下
father beforeUpdate
child beforeUpdate
child onMoute
child afterUpdate
father onMoute
father afterUpdate
father onDestroy
child onDestroy
五、指令
1.内置指令
bind::用于双向绑定表单元素的值。例如,可以使用bind:value指令来双向绑定输入框的值,使得输入框中的值能够与组件中的变量同步。on::用于监听 DOM 元素的事件。例如,可以使用on:click指令来监听按钮的点击事件,并在事件触发时执行相应的逻辑。class:和style::用于设置 DOM 元素的 class 和 style 属性。例如,可以使用class:active指令来根据条件动态添加或删除activeclass,从而改变元素的样式。
2.自定义指令
<script>
  function selectOnFocus(node, options) {
    node.addEventListener('focus', () => {
      node.select();
    });
  }
</script>
<input type="text" use:selectOnFocus />
六、总结
Svelte被设计成编译时框架,可以将代码打包成高效的JavaScript代码,从而提高应用程序的性能和响应速度。相比其他前端框架,Svelte的体积更小、性能更好,同时也具有很好的可维护性和可扩展性。这些特点使得Svelte在国外得到了广泛的关注和应用。
