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


    一、简单体验

    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 就会被标记为可选属性

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

     

     

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

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

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

     

     

    然而通过 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 对象是不能直接用于页面渲染的,比如下面的用法就会出错

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

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

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

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

     


     

    如果需要在组件中修改 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>

     

  • 相关阅读:
    min.js文件 反压缩查看
    Simple HTML DOM解析器 使用php解析网页字符串进行dom操作
    使用clipboard.js实现页面内容复制到剪贴板
    php7微信支付回调失败
    微信卡券开发
    Windows内存性能分析(一)内存泄漏
    LoadRunner添加检查点
    LoadRunner中两种录制模式的区别
    Jmeter参数化_CSV Data Set Config
    APTM敏捷性能测试模型
  • 原文地址:https://www.cnblogs.com/wisewrong/p/15817215.html
Copyright © 2020-2023  润新知