一、简单体验

Svelte 的开发体验和 Vue 3 很类似

在 Svelte 组件中也是将 JS 写在 <script> 标签中,将 CSS 写在 <style> 中

稍微不同的点在于,DOM 模板不需要写在 <template> 中,而是可以写在任何地方

<script>
    import Nested from './Nested.svelte';
    const title = 'Hello World';
</script>

<style>
    p { color: purple; }
</style>

<h1>{title}</h1>
<p>Let's Enjoy Sevelte</p>
<Nested/>

Svelte 中的变量自带响应式特性,数据变更时会即时渲染到页面上

同时 Svelte 还提供了 $: 用来实现一段响应式逻辑,就像 Vue 中的 Computed 和 Watch

<script>
    let count = 0;
    const handleClick = () => count += 1;
    $: doubled = count * 2;
    $: if (count > 9) {
        console.log('count is dangerously high!');
count = 9; };
</script> <button on:click={handleClick}>Click</button> <p>{count} doubled is {doubled}</p>

总之 Svelte 是一个很好上手的框架,更多的特性或语法可以通过官方文档了解,《Svelte 迷途求索》将着重介绍 Svelte 实战中可能遇到的问题

 

 

二、创建 Props:父对子传参

在开发的时候,如果子组件中的某个数据需要通过父组件传入,就需要在子组件中声明 props

// 子组件

<script lang="ts">
  export let text: string = undefined;
</script>

<p>hello {text}</p>

没错,在 Svelte 中创建 props 就是这么简单粗暴,只需要使用 let 创建一个变量,然后通过 export 导出即可

可以给这个 prop 添加一个默认值,不管是上面的 undefined,还是一个具体的值,那么这个 prop 就会被标记为可选属性

Svelte 迷途求索(二) —— 组件传参和状态管理

如果没有设置默认值,这个 prop 就是一个必填属性。使用该组件时如果没有提供该属性,则会打印警告

Svelte 迷途求索(二) —— 组件传参和状态管理

Svelte 迷途求索(二) —— 组件传参和状态管理

 

 

三、通过 prop 传入函数:子对父传参

上面已经介绍过,组件的 prop 是通过 let 创建的

而使用 const, class, function 创建的 prop 都是只读属性,即使通过 export 导出,也不会接收外部参数

Svelte 迷途求索(二) —— 组件传参和状态管理 

Svelte 迷途求索(二) —— 组件传参和状态管理 

Svelte 迷途求索(二) —— 组件传参和状态管理

然而通过 prop 传入一个函数的情况还是挺常见的,比如子组件向父组件传参

好在虽然不能使用 function,但还是可以使用箭头函数作为 prop

下面这个例子中,子组件通过回调函数 onChange 实现了向父组件传参

// 子组件

<script lang="ts">
  // onChange 需要父组件提供
  export let onChange = (v: number) => {};

  let count: number = 0;

  const addCount = () => {
    count += 1;
    typeof onChange === 'function' && onChange(count);
  };
</script>

<button on:click={addCount}>Click</button>
<p>count: {count}</p>
// 父组件

<script lang="ts">
  import Child from './child.svelte';

  const onChange = (v: number) => {
    console.log('onChange', v);
  };
</script>

<Child {onChange} />
<!-- 
  * 等价于:
  * <Child onChange={onChange} />
 -->

 

 

四、状态管理:复杂情况的组件传参

通过 props 可以很轻松的实现父组件对子组件的传参

如果是兄弟组件之间传参,可以运用状态提升的思想来实现

但如果是更复杂的情况呢?比如祖孙组件,甚至是几个没有直接关系的组件。这时候就可以使用 Svelte 自带的状态管理

// stores/index.js

import { writable } from 'svelte/store';

export const titleStore = writable('Hello World');

export const userInfo = writable({
  name: 'Wise.Wrong',
  blog: 'https://www.cnblogs.com/wisewrong/',
});

svelte/store 模块提供了三个函数 writable、readable、derived,分别用来创建可写状态、只读状态、派生状态

其中最常用的是可写状态 writable, 上面的 stores/index.js 中就使用 writable 创建了两个 store 对象

但 store 对象是不能直接用于页面渲染的,比如下面的用法就会出错

Svelte 迷途求索(二) —— 组件传参和状态管理

这是因为 writable 创建的是包含 set、update、subscribe 方法的 store 对象

其中 subscribe 会在 store 更新的时候触发,类似 Vue 中的 watch

基于这个特性,我们可以这样读取 store 的值:

Svelte 迷途求索(二) —— 组件传参和状态管理

它确实生效了,但这样也太不优雅了,其实只需要在 store 前面加一个 $ 就行了

Svelte 迷途求索(二) —— 组件传参和状态管理 


 

如果需要在组件中修改 store 的值,可以用到 set 和 update 方法

import { titleStore } from './stores';

const onChange = (v: string) => {
  // set 接收的参数会作为 store 的新值
  titleStore.set(v);
};

const onUpdate = (str: string) => {
  // update 可以接收一个函数,其返回值会作为 store 的新值
  titleStore.update((v: string) => v + str);
}

但如果是在表单中,有时候连 update 或 set 都不需要,因为 store 可以配合 bind: 使用

<script lang="ts">
  // parent.svelte
  import { userInfo } from '../../stores';
  import Child from './child.svelte';
</script>

<div class="title">This is <strong>{$userInfo?.name}</strong></div>
<Child />

<style>
  .title {
    margin-bottom: 12px;
  }
</style>
<script lang="ts">
  // child.svelte
  import { userInfo } from '../../stores';
</script>

<section>
  <div>
    <span>姓名: </span>
    <input type="text" bind:value={$userInfo.name}>
  </div>
  <div>
    <span>博客: </span>
    <input type="text" bind:value={$userInfo.blog}>
  </div>
</section>

Svelte 迷途求索(二) —— 组件传参和状态管理

 

相关文章:

  • 2022-12-23
  • 2022-03-09
  • 2021-07-21
  • 2022-01-28
  • 2021-07-26
  • 2022-12-23
  • 2022-12-23
  • 2022-03-12
猜你喜欢
  • 2022-01-23
  • 2021-07-02
  • 2021-07-04
  • 2022-12-23
  • 2022-12-23
  • 2022-02-14
  • 2022-12-23
相关资源
相似解决方案