首页 > 其他分享 >Svelte

Svelte

时间:2024-09-10 17:26:42浏览次数:1  
标签:Svelte Parent let Child msg import svelte

0x01 概述

(1)关于

  • 官网:

  • 介绍:

    • 开源的 JavaScript 框架
    • 增强型网络应用程序(Cybernetically enhanced web apps)
    • 在编译时加载框架,无需运行时(runtime)
  • 特点:

    • 减少代码量
    • 无虚拟 DOM
    • 提供响应式
  • 优点:

    • 内置动画
    • 专注于业务
    • CSS 模块化
  • 适用情况:

    • 构建和响应速度要求较高
    • 连接性较差
    • 交互效果需求大
  • 对比:

    Svelte React Vue
    应用性能 最快 最慢 中等
    构建方法 脚本编译器 DOM 虚拟 DOM
    平均应用大小(Kb) 15 193 71
    学习曲线 容易 较容易 较容易

(2)创建项目

需要 NodeJS、npm、git 等环境

  1. 使用命令 npm create vite@latest 启动 Vite 创建项目
  2. 输入项目名称,如 svelte-app
  3. 选择 Svelte 框架(framework)
  4. 选择 JavaScript 变体(variant)
  5. 使用 cd 命令进入项目目录并使用命令 npm install 安装依赖
  6. 使用命令 npm run dev 启动项目

(3)目录结构

  • node_modules:NodeJS 依赖目录

  • public:公共资源

  • src:代码资源文件

    • App.svelte:主应用页面文件

      <script>
      </script>
      
      <main>Hello world!</main>
      
      <style>
      </style>
      
    • main.js:入口文件

      import App from './App.svelte'
      
      const app = new App({
        target: document.getElementById('app'),
      })
      
      export default app
      
    • vite-env.d.ts:Vite 环境声明文件

  • index.html:页面文件

  • jsconfig.json:配置文件

  • package.json:NodeJS 包配置文件

  • svelte.config.js:Svelte 配置文件

  • vite.config.js:Vite 配置文件

0x02 基础语法

(1)数据渲染

  • 把在 <script> 标签中,使用 let 声明的变量渲染到页面中

  • 可以通过 {@html } 将 HTML 字符串渲染为 HTML 文档

  • 举例:

    <script>
      let src = "/vite.svg"
      let text = "Lorem ipsum.";
      let string = "<h1 style='color: red'>Hello World</h1>";
    </script>
    
    <main>
      <img src={src} alt="Svelte logo" />
      <p>Lower: {text.toLowerCase()}</p>
      <p>Upper: {text.toUpperCase()}</p>
      {@html string}
    </main>
    

(2)双向绑定

  • 方法:

    1. 通过 let 声明响应式变量
    2. 通过 bind: 进行绑定
  • 举例:

    <script>
      let text = "";
      let checkbox = false;
      let radioBook = "";
      let checkboxBooks = [];
      let selectBook = "";
    </script>
    
    <main>
      <p>输入内容:{text}</p>
      <input type="text" bind:value={text} />
    
      <p>单选框组:{radioBook}</p>
      <input type="radio" bind:group={radioBook} name="books" value="Book A" />
      <input type="radio" bind:group={radioBook} name="books" value="Book B" />
      <input type="radio" bind:group={radioBook} name="books" value="Book C" />
    
      <p>多选框:{checkbox}</p>
      <input type="checkbox" bind:checked={checkbox} />
    
      <p>多选框组:{checkboxBooks}</p>
      <input type="checkbox" bind:group={checkboxBooks} name="books" value="Book A" />
      <input type="checkbox" bind:group={checkboxBooks} name="books" value="Book B" />
      <input type="checkbox" bind:group={checkboxBooks} name="books" value="Book C" />
    
      <p>选择框:{selectBook}</p>
      <select bind:value={selectBook} on:click={(e) => console.log(e.target.value)}>
        <option value="Book A">Book A</option>
        <option value="Book B">Book B</option>
        <option value="Book C">Book C</option>
      </select>
    </main>
    

(3)样式

  • Svelte 支持通过 style: 定义元素内联样式

  • 举例:

    <script>
    </script>
    
    <main>
      <p style:color="red">Svelte 样式</p>
    
      <p style="color: blue">HTML 内联样式</p>
    
      <p class="style">Style 标签定义样式</p>
    </main>
    
    <style>
      .style {
        color: green;
      }
    </style>
    
  • Svelte 支持使用 Less、Sass 等 CSS 预处理语言开发样式

(4)事件

  • Svelte 支持通过 on: 监听动作并触发事件

    • 语法:on:事件名|修饰符={方法}

    • 修饰符可选,取值包括:

      修饰符 含义 修饰符 含义
      capture 捕获阶段处理事件 nonpassive 显式设置 passive: false
      once 只能执行一次 passive 提高滚动性能
      preventDefault 停止默认事件 self 仅在事件对象 event.target 是元素本身时触发
      stopPropagaion 停止事件冒泡 trusted 仅在 event.isTrusted === true 时触发
  • Svelte 也支持使用 $: 进行监听变量改变(反应性

  • 举例:

    <script>
      let count = 0;
      const onm ouseover = () => {
        console.log("mouse over");
      };
    
      $: console.log("count", count);
    </script>
    
    <main>
      <button on:click|once={() => alert("Clicked")}>Click</button>
      <button on:click={() => count++}>Count: {count}</button>
      <div
        style="width: 100px; height: 100px; background-color: black"
        on:mouseover={onMouseover}
      />
    </main>
    
  • 通过 <svelte:body> 可以对页面的 <body> 绑定事件,如:

    <main style="height: 100vh;"></main>
    <svelte:body on:click={() => alert("Hello!")} />
    

(5)响应式数组/对象

  1. 声明一个数组,通过监听数组变化计算元素和,并渲染到页面展示

    <script>
      let arr = [1, 2, 3];
      $: sum = arr.reduce((sum, cur) => (sum += cur), 0);
    </script>
    
    <main>
      <p>{arr.join(" + ")} = {sum}</p>
      <button
        on:click={() => {
          arr.push(4);
        }}>Add 4</button
      >
    </main>
    

    此时,点击按钮后页面并未改变,需要通过浅/深拷贝解决

  2. click 事件中对 arr 进行浅拷贝

    <script>
      let arr = [1, 2, 3];
      $: sum = arr.reduce((sum, cur) => (sum += cur), 0);
    </script>
    
    <main>
      <p>{arr.join(" + ")} = {sum}</p>
      <button
        on:click={() => {
          arr.push(4);
          arr = [...arr];
        }}>Add 4</button
      >
    </main>
    

0x03 渲染控制

(1)条件渲染

  • 语法:

    {#if condition1}
    {:else if condition2}
    {:else}
    {/if}
    
  • 举例:

    <script>
      let flag = true;
    </script>
    
    <main>
      <button on:click={() => flag = !flag}>Change</button>
      {#if flag}
        <div>A</div>
      {:else}
        <div>B</div>
      {/if}
    </main>
    

(2)列表渲染

  • 语法:

    {#each array as item, index (key)}
    {/each}
    
  • 举例:

    <script>
      let students = [
        { id: 201, name: "John" },
        { id: 321, name: "Jane" },
        { id: 666, name: "Jim" },
      ];
    </script>
    
    <table>
      <tr>
        <th>序号</th>
        <th>学号</th>
        <th>姓名</th>
      </tr>
      {#each students as item, index (item.id)}
        <tr>
          <td align="center">{index}</td>
          <td align="center">{item.id}</td>
          <td align="center">{item.name}</td>
        </tr>
      {/each}
    </table>
    

(3)异步渲染

  • 语法:

    {#await async}
    {:then response}
    {/await}
    
  • 举例:

    <script>
      const sleep = async (duration) =>
        new Promise((resolve) => setTimeout(() => resolve("Done"), duration));
    </script>
    
    <main>
      {#await sleep(3000)}
        Loading...
      {:then res}
        {res}
      {/await}
    </main>
    

0x04 组件化开发

(1)创建组件

  1. 在 src 目录下创建 lib 作为组件文件目录,并在其中新建 Parent.svelte

    <script></script>
    
    <main>Parent</main>
    
    <style></style>
    
  2. 在 App.svelte 中导入并使用该组件

    <script>
      import Parent from "./lib/Parent.svelte";
    </script>
    
    <main>
      <Parent />
    </main>
    

(2)插槽

a. 匿名插槽

<slot /> 用于定义插槽

  1. 在 lib 目录下新建 Child.svelte

    <script></script>
    
    <main>Child</main>
    
    <style></style>
    
  2. 在 Parent.svelte 中使用匿名插槽

    <main>
      Parent
      <slot />
    </main>
    
  3. 在 App.svelte 的 Parent 组件中使用 Child 组件

    <script>
      import Child from "./lib/Child.svelte";
      import Parent from "./lib/Parent.svelte";
    </script>
    
    <main>
      <Parent>
        <Child />
      </Parent>
    </main>
    

b. 具名插槽

<slot /> 的属性 name 用于命名

  1. 在 Parent.svelte 中为插槽命名

    <main>
      Parent
      <slot name="slot1" />
      <slot name="slot2" />
    </main>
    
  2. 在 App.svelte 中通过名称使用不同的插槽

    <main>
      <Parent>
        <p slot="slot1">1: <Child /></p>
        <p slot="slot2">2: <Child /></p>
      </Parent>
    </main>
    

(3)数据传递

a. 父传子

通过组件属性来传值

  1. 在子组件 Child.svelte 中声明并暴露变量

    <script>
      export let msg = "";
    </script>
    
    <main>Child: {msg}</main>
    
  2. 在 App.svelte 中使用组件并通过属性传值

    <main>
      <Parent>
        <Child msg="Hello from Parent" />
      </Parent>
    </main>
    

b. 子传父

通过 createEventDispatcher 方法实现

  1. 在子组件 Child.svelte 中导入 createEventDispatcher 方法并添加按钮来发送数据

    <script>
      import { createEventDispatcher } from "svelte";
    
      const dispatch = createEventDispatcher();
      const onSend = () => dispatch("msg", "Hello from Child")
    </script>
    
    <main>
      Child
      <button on:click={onSend}>send</button>
    </main>
    
    • dispatch 的第一个参数是名称,第二个参数是数据
  2. 在父组件 App.svelte 中通过 on: 监听事件并获取、渲染数据

    <script>
      import Child from "./lib/Child.svelte";
      import Parent from "./lib/Parent.svelte";
    
      let msg = ""
    </script>
    
    <main>
      <p>Message: {msg}</p>
      <Parent>
        <Child on:msg={e => msg = e.detail} />
      </Parent>
    </main>
    

c. 上下文

通过 setContext 发送数据,getContext 接收数据

  1. 在 Parent.svelte 发送数据

    <script>
      import { setContext } from "svelte";
    
      setContext("msg", "Message from Parent");
    </script>
    
    <main>
      Parent
      <slot />
    </main>
    
  2. 在 Child.svelte 接收数据

    <script>
      import { getContext } from "svelte";
    
      let msg = getContext("msg") || "";
    </script>
    
    <main>
      Child: {msg}
    </main>
    

0x05 特性语法

(1)生命周期

  • Svelte 有四个生命周期方法

    • onMount:挂载时
    • beforeUpdate:更新前
    • afterUpate:更新后
    • onDestory:卸载时
  • 举例:

    <script>
      import { afterUpdate, beforeUpdate, onDestroy, onMount } from "svelte";
    
      onMount(() => console.log("app mount"));
      beforeUpdate(() => console.log("before update"));
      afterUpdate(() => console.log("after update"));
      onDestroy(() => console.log("app destroy"));
    
      let msg = "";
    </script>
    
    <main>
      <h1>{msg}</h1>
      <input type="text" bind:value={msg} />
    </main>
    

(2)全局状态管理

  1. 在 src 目录下新建 store.js

    import { writable } from "svelte/store";
    
    export const count = writable(0);
    
  2. 在 App.svelte 中使用并修改全局状态

    <script>
      import { count } from "./store";
    
      let countValue;
      count.subscribe((value) => {
        countValue = value;
      });
    </script>
    
    <main>
      {countValue}
      <button
        on:click={() => {
          count.update((value) => {
            value += 1;
            return value;
          });
        }}
      >
        +1
      </button>
    </main>
    

(3)动画

a. tweened 补间动画

举例:

<script>
  import { cubicOut } from "svelte/easing";
  import { tweened } from "svelte/motion";

  const process = tweened(0, {
    duration: 500,
    easing: cubicOut,
  });
</script>

<main>
  <progress value={$process} />
  <button on:click={() => process.set(0)}>0%</button>
  <button on:click={() => process.set(0.5)}>50%</button>
  <button on:click={() => process.set(1)}>100%</button>
</main>

b. spirng 弹性动画

举例:

<script>
  import { spring } from "svelte/motion";

  const process = spring(0, {
    stiffness: 0.1, // 刚度
    damping: 0.25, // 阻尼
  });
</script>

<main>
  <progress value={$process} />
  <button on:click={() => process.set(0)}>0%</button>
  <button on:click={() => process.set(0.5)}>50%</button>
  <button on:click={() => process.set(1)}>100%</button>
</main>

c. 显隐动画

举例:

<script>
  import { fade, fly } from "svelte/transition";

  let show = false;
</script>

<main>
  <button on:click={() => (show = !show)}>Toggle</button>
  {#if show}
    <p transition:fade>淡入淡出</p>
    <p transition:fly={{ y: 200, duration: 2000 }}>飞入飞出</p>
    <p in:fly={{ y: 200, duration: 2000 }} out:fade>飞入淡出</p>
  {/if}
</main>

案例:待办列表

  • App.svelte

    <script>
      import Item from "./lib/Item.svelte";
    
      let todoList = [
        {
          id: 1,
          content: "吃饭",
        },
        {
          id: 2,
          content: "睡觉",
        },
        {
          id: 3,
          content: "打豆豆",
        },
      ];
      let total = todoList.length;
      let newContent = "";
      const addItem = () => {
        total++;
        todoList = [
          ...todoList,
          {
            id: todoList.length + 1,
            content: newContent,
          },
        ];
        newContent = "";
      };
    </script>
    
    <main>
      <h3>待办列表</h3>
      <ul>
        {#each todoList as item, index (item.id)}
          <li>
            <Item content={item.content} on:send={(e) => total--} />
          </li>
        {/each}
      </ul>
      <p>总待办数:{todoList.length},未完成待办数:{total}</p>
      <div>
        <input type="text" bind:value={newContent} />
        <button on:click={addItem}>添加</button>
      </div>
    </main>
    
    <style>
      main {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
      }
      ul {
        list-style: none;
        padding: 0;
      }
    </style>
    
  • lib\Item.svelte

    <script>
      import { createEventDispatcher } from "svelte";
    
      let isChecked = false;
      export let content = "";
    
      const dispatch = createEventDispatcher();
      const onSend = () => {
        dispatch("send", undefined);
      };
      $: isChecked ? onSend() : null;
    </script>
    
    {#if isChecked}
      <input type="checkbox" bind:checked={isChecked} disabled />
      <span style="color: gray; text-decoration: line-through">{content}</span>
    {:else}
      <input type="checkbox" bind:checked={isChecked} />
      <span>{content}</span>
    {/if}
    
    <style>
    </style>
    

详细使用方法查看官方教程:https://www.svelte.cn/tutorial

-End-

标签:Svelte,Parent,let,Child,msg,import,svelte
From: https://www.cnblogs.com/SRIGT/p/18406806

相关文章

  • Python + Svelte,如何使用本地文件系统
    总结一下,我有一个用python编写的应用程序。它在输入时需要一堆视频文件。使用一些魔法并生成合并的视频文件输出。我没有找到一个好的GUI解决方案(tkinter,QT,TUI等),所以我选择Svelte框架。但是出现了一个问题,我如何使用本地文件系统。在GUI(svelte)上,我必须上......
  • SvelteKit - 1. 初始化项目
    官方doc-createaproject1、基本环境(下面是我这里的环境,亲测用node14和16install会报错)node:20.9.0npm:10.1.02、初始化项目npmcreatesvelte@latestmy-appcdmy-appnpminstallnpmrundevcreate时的选择:其中第一步选择创建应用的类型,有三个可供选......
  • svelte - 1. 基础知识
    svelte中文官网vue和svelt语法对比掘金-svelte入门简介文章目录1、基本页面框架2、动态属性3、嵌套组件4、@html:插入html标签,显示真实dom元素5、点击事件on:click={handleClick}6、响应式声明7、父子组件通信8、if-else(1)if(2)if-else(3)if-elseif-......
  • 基于svelte webpack开发umd格式的npm包
    原文链接:https://www.cnblogs.com/yalong/p/18101609背景:平常会接触到vue、react、jquery项目,项目中有一些公共组件其实是可以复用的,但是在vue项目中封装好的组件,在react中又不能用;于是想找个方法,实现一次开发,多框架复用,调研发现svelte正好符合这个要求,把组件封装成npm发布......
  • svelte路由01
    1、about.svelte页面a、使用 use:link 方式<script>import{link}from'svelte-spa-router';</script><div>这里是about关于我们</div><div><ahref="/home"use:link>进入首页</a></div>......
  • svelte的一些基础demo
    脚手架Vite:vite是集成了svelte,初始化的时候选择svelte就行了。npminitviteSvelteKit:底层基于vite的更上层框架,类似于nextjs。[email protected]文件结构和vue类似svelte文件是.svelte结尾的文件,比如demo.svelte......
  • svelte响应式原理
    svelte文件编译为js后的结构源代码:<scriptlang="ts">letfirstName='张'letlastName='三'letage=18functionhandleChangeName(){firstName='王'lastName='二'}fu......
  • JavaScript Library – Svelte
    前言上一回我介绍了 Alpine.js。作为我开发企业网站draft版本的renderengine。用了一阵子后,我觉得它真的非常不好用。所以打算换一个。前端有好几个framework/library/compiler都可以用来做MVVMrenderengine。比如Angular、React、Vue、LIt、Solid、Qwik、Svelt......
  • Svelte
    Svelte是一种全新的构建用户界面的方法。传统框架如React和Vue在浏览器中需要做大量的工作,而Svelte将这些工作放到构建应用程序的编译阶段来处理。(而不是用户运行时加载,因此比vue和react更快)与使用虚拟(virtual)DOM差异对比不同。Svelte编写的代码在应用程序的状态更改时......
  • Svelte框架结合SpreadJS实现表格协同文档
    SpreadJS是葡萄城结合40余年专业控件技术和在电子表格应用领域的经验而推出的纯前端表格控件。作为一个类Excel控件,SpreadJS如何实现当前比较流行的表格协同呢?本篇文章将......