svelte使用总结

svelte使用总结

概念

 

什么是Svelte?

Svelte.js是一个开源的JavaScript框架,通过将Svelte代码转换为流畅的UI界面,简化了Web应用程序的创建。该框架的一个关键区别是:它在编译阶段加载框架而不是用户运行时加载,因此其比 React 或 Vue 更快。

Svelte由它的架构决定运行速度。该框架将代码编译成独立的小型JavaScript模块,确保浏览器尽可能少地完成工作,从而加快加载速度。

 

Svelte 速度快的主要原因:

  • 无虚拟DOM

  • 代码量少

  • 响应式

 

Svelte与其它框架的区别:Svelte、React、Vue 的对比

Svelte与 React、Vue等等的框架对比,Svelte构建的应用程序是事先编译的,因此不必将整个框架提供给每个网站访问者。因此,用户的体验更流畅,消耗更少的带宽,这一切都感觉更快,更轻量级。

 Svelte.jsReact.jsVue.js
应用性能 比React和Vue更快 比Svelte慢,比Vue略慢 比Svelte慢,但比React略快
构建 脚本编译器 DOM Virtual DOM
平均应用大小 15 Kb 193 Kb 71 Kb
学习曲线 简单易学 相对容易学习 相对容易学习

Svelte 不依赖于在运行时加载的复杂库。相反,它会编译你的代码,并加载一个比 React更小的软件包。这种体积的差异换来的是访客更快的加载时间。

与 Vue 和 React 不同,Svelte几乎不需要初始化的脚手架,因为它是使用基本的 HTML、CSS 和 JavaScript 编写的。所以,Svelte的脚本看起来类似于普通的JS。

 

使用Svelte.js的优点

  • 更好的开发体验

  • 模块化 CSS

  • 内置动画

  • 项目体积小

 

语法

渲染

响应式数据

  • 使用响应式数据时需要在 script 中声明当前变量

  • { } 内可以使用 表达式

<script>
let name = "张三";
</script>

<main>
<p >我的名字叫{name}</p>
</main>

图片引入

  • 图片也是类型响应式数据的需要声明一个变量才能使用

  • svelte支持自动编译简写 ,所以 src= 可以写成 {src}

<script>
 let src = "./下载.png";
</script>

<main>
 <img {src} alt="" />
</main>

 

双向绑定

双向绑定最重要的语法 : bind

  • 双向绑定只需要通过 bind:value 即可完成。

  • 单选框组、复选框组:需要添加 bind:group 属性和value值。

  • 但需要区分 单个选框时则是需要使用 bind:checked

<script>
let name = '法外狂徒';
</script>

<input bind:value={name}>
<h1>Hello {name}!</h1>

单选框双向数据绑定:

<script>
let choice = false;
</script>

<label>
<input type="checkbox" bind:checked={choice}>
</label>

单选框 复选框 :

    <!-- 单选框组 -->
   <input type="radio" bind:group={books} name="books" value="单选1" />
   <input type="radio" bind:group={books} name="books" value="单选2" />
   <input type="radio" bind:group={books} name="books" value="单选3" />
   <br />
   
<!-- 复选框组 -->
   <input type="checkbox" bind:group={books} name="books" value="钢铁" />
   <input type="checkbox" bind:group={books} name="books" value="卖火柴" />
   <input type="checkbox" bind:group={books} name="books" value="唐诗300首" />

下拉选项框

    <select
       value={selected}
       on:change={(event) => {
          selected = event.target.value;
      }}
  >
       <option value="1">下拉选项1</option>
       <option value="2">下拉选项2</option>
       <option value="3">下拉选项3</option>
   </select>
  • 下拉选项框的操作直接使用 value与change事件配合完成

  • change事件:当下拉选定新值时就更改选择项

 

样式渲染

行内式:

<div style="color:red">字符串</div>

 

外链式:

<script>
   import "./mystylea1.css";
</script>

<main>
<div class="bluetext">蓝色文字</div>
</main>

 

当前页面使用样式:

<div class="myclass2">大头字</div>

<!-- vite.config.js文件中还需要进行定义预先编译器的设置 -->
<style lang="scss" type="text/scss">
  .myclass2 {
      font-size: 24px;
  }
</style>

svelte中想要使用scss语法需要先安装预处理器:svelte-preprocess, 由于需要支持scss,那sass当然也需要进行安装。

npm install svelte-preprocess sass node-sass --save-dev

安装好预处理器后,还需要对脚手架配置文件vite.config.js进行修改:

最终修改如下:

import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import sveltePreprocess from "svelte-preprocess";

// https://vitejs.dev/config/
export default defineConfig({
 plugins: [
   svelte({
     preprocess: sveltePreprocess(),
  }),
],});

 

插槽传值

匿名插槽

父组件:

<script>
import Box from './Box.svelte';
</script>

<div>
<Box>
这是一个子组件
</Box>
</div>

子组件:

<div class="box">
<slot></slot>
</div>
  • 此时子组件通过匿名函数获取到父级参数传递而来的值

 

具名插槽

父组件:

<script>
import Box from './Box.svelte';
</script>

<div>
<Box>
           <div slot="block1">插槽1</div>
           <div slot="block2">插槽2</div>
</Box>
</div>

子组件:

<div class="box">
<slot name="block1"></slot>
<slot name="block2"></slot>
</div>
  • 具名插槽需要绑定父级中定义的插槽名称

     

 

父传子

父传子的过程需要子组件暴露属性,父组件才能进行参数的传递。

<script>
   import Child from "./Child.svelte";
</script>

<main>
   <div class="box1">
       <!--通过子组件属性进行传参-->
       <Child msg="hello wold">
       </Child>
   </div>
</main>
  1. 定义一个对象来接收子组件传递参数

子组件:

<script>
 export let msg = ""; // 此处暴露出去的值,可以赋值默认值。
</script>

<div class="child">
父组件信息:{msg}
</div>

 

 

子传父

子组件

  • 子组件 通过使用自带函数方法 向父组件传递数据的方法

  • 并且需要定义一个事件来进行参数的传递

    import { createEventDispatcher } from "svelte";
   const dipatch = createEventDispatcher();

   const sendMSG = () => {
       dipatch("sendMSGtoParent", "你好父组件");
     //dipatch("父组件声明接收参数的名函数名称","需要传递的数据");
  };

触发事件

<button on:click={sendMSG}>点击传递数据</button>

父组件

  • 定义一个对象来接收子组件传递参数

 let smsg = "接收子组件参数有";
  • 通过 父组件声明接收参数的名函数名称 来进行事件的关联 并且使用 e.detail 获取到传递的数据

<main>
   <div class="box1">
       <Child  on:sendMSGtoParent={(e) => {
              smsg = e.detail; }} >
       </Child>
      {smsg}
   </div>
</main>

 

 

渲染html字符串

在svelte中提供一个特殊的标记 @html,使用该标记可以为我们渲染html字符串。

<script>
   let A1 = "我叫:<span style='color:blue'>张三</span>";
</script>

<div>
   <!-- 使用{@html "对象名"} 来使用html文本 -->
  {@html A1}
</div>

 

 

svelte事件

在svelte中定义事件也十分简单,与原生类似,不同的是,需要在on后面加上冒号。

格式如:on:事件名={方法引用}

修饰符:

  • preventDefault — 停止默认事件修饰符

  • stopPropagation —停止冒泡修饰符

  • passive — 提高滚动性能

  • nonpassive — 显式的设置passive: false

  • capture —捕获阶段处理事件

  • once — 只执行一次,完了后移除事件,使得下次不能被执行。

  • self — 仅在事件对象event.target为元素本身时执行事件。

  • trusted — 只有 event.isTrustedtrue才进行触发。

 

例子:

<button on:click|once={事件函数}>点击我</button>

例子:

<script>
 let count = 0;

 const reduce = () => {
   count--;
};

 const add = () => {
   count++;
};
</script>

<div>
 数量:
 <button on:click={reduce}>-</button>
{count}
 <button on:click={add}>+</button>
</div>

 

svelte的监听

当一个属性会被别的属性所影响而发生改变时就需要使用到 反应性

$: "需要依赖别的属性" = "被依赖的属性"

 

在svelte中,提供一个反应性的语法,在script标签中用$:符合进行定义。先来理解什么是反应性,当被依赖的响应式变量发生改变的时候,会自动同步更新反应性语法里面的表达式。

<script>
 let count = 0;

 const reduce = () => {
   count--;
};

 const add = () => {
   count++;
};

$: total = price * count;
</script>

<div>
数量:
 <button on:click={reduce}>-</button>
{count}
 <button on:click={add}>+</button>
{total}
</div>
  • count 被改变时 total 就会产生改变

 

修改数组或对象时没反应

  • 问:虽然修改了数组,但是不会产生效果是什么情况?

  • 答:数组和对象变量的指向地址并无发生变化,使得sevelte不能识别是否发生的变量,无法进一步的触发渲染事件

解决方法:

对象:

1、对象合并: Object.assign({}, obj1, obj2)

2、解构: {...obj1, ...obj2}

3、 json转化: JSON.parse(JSON.stringify(obj1))

数组:

1、解构: [...arr1, ...arr2]

2、 json转化: JSON.parse(JSON.stringify(arr1))

例子:

<script>
 let arr = [1, 2, 3];

 $: total = arr.reduce((total, val) => (total += val));
</script>

<div>
{arr.join(" + ")} = {total}

 <br />
 <button
   on:click={() => {
    arr.push(arr.length + 1);
    arr = [...arr];
  }}>add item</button
 >
</div>
  • 通过 arr = [...arr] 达到重新加载了数组

  • total 依赖数组的变化而更新值

 

条件渲染

svelte有着自己的一套模板语法,使用起来结构更加清晰.

条件渲染的条件是放在标签语法{#if }里面,而分支用{:else}分开,最终再以{/if}结束。

<script>
 let flag = true;
</script>

{#if flag}
 <div>A</div>
{:else}
 <div>B</div>
{/if}
  • 条件渲染也支持嵌套。

<script>
 let flag = true;
 let flag2 = false;
</script>

{#if flag}
 <div>1</div>
{#if flag2}
     <div>2</div>
  {:else}
     <div>3</div>
  {/if}
{:else}
 <div>4</div>
{/if}

 

列表渲染

同样svelte有对于循环也是有响应的模板语法。

格式:

{#each 数组 as 数组项目, 数组下标 (唯一的键值)}
	<div>{数组项目.属性}</div>
{/each}
<script>
  import { each } from "svelte/internal";

  let arr = [
    { name: "小明", age: 20 },
    { name: "小红", age: 19 },
    { name: "小蓝", age: 20 },
    { name: "小天", age: 15 },
  ];
</script>

{#each arr as item, index}
  <div>
    {index}、姓名:{item.name} 年龄:{item.age}
  </div>
{/each}

通过each后面的圆括号来指定唯一的键(key)

<script>
 import { each } from "svelte/internal";

 let arr = [
  { id: 1, name: "小明", age: 20 },
  { id: 2, name: "小红", age: 19 },
  { id: 3, name: "小蓝", age: 20 },
  { id: 4, name: "小天", age: 15 },
];
</script>

{#each arr as item, index (item.id)}
 <div>
  {index}、姓名:{item.name} 年龄:{item.age}
 </div>
{/each}

 

Await模板标签

svelte有个与promise配合使用的模板标签,以提高用户的体验感。

语法1:含等待、成功、失败状态(较为常用)

{#await Promise}
等待状态
{:then 成功值}
成功状态 //接收 resolve(成功的参数)
{/await}

语法2:不含失败和等待状态

{#await Promise then 成功值}
成功状态
{/await}

例子1、

<script>
 let timer = new Promise((resolve) => {
   setTimeout(() => {
     resolve("倒计时完成");
  }, 3000);
});
</script>

{#await timer}
loading...
{:then res}
{res}
{/await}

例子2、

<script>
 let timer = new Promise((resolve) => {
   setTimeout(() => {
     resolve("倒计时完成");
  }, 3000);
});
</script>

{#await timer then res}
{res}
{/await}

 

绑定Dom元素

可以通过bind:this,将元素绑定到具体的变量中去。

作用类似于 $ref

<script>
let input;

export function focus() {
input.focus();
}
</script>

<input bind:this={input} />

 

生命周期

svelte中的生命周期:

  • onMount

  • onDestroy

  • beforeUpdate

  • afterUpdate

<script>
import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';

// 挂载期    
onMount(async () => {
// 一般可以通过挂载来进行网络请求。
});
   
   // dom节点更新前
   beforeUpdate(() => {
       // 用于记录dom节点更新前的状态
  })
   
   // dom节点更新后
   afterUpdate(() => {
       // 在dom接口更新后所需事件
  })
   
   // 卸载期
   onDestroy(() => {
// 卸载工作
       // 例如释放变量、删除时钟。
});
</script>

 

tick的用法

tick函数返回一个Promise, 你可以在任意地方使用tick。它的作用是:有了await tick()后,它不会里面刷新dom,而去等待下一次微任务就绪的时候(包括其他组件已经渲染完成)再继续往下执行。

<script>
 import { tick } from "svelte";

 let count = 0;
 async function hello() {
   count++;

   new Promise((resolve) => {
     setTimeout(() => {
       resolve("hello");
    }, 3000);
  }).then((res) => {
     console.log(res);
  });

   await tick();
   console.log(count);
}
</script>

count: {count}
<button on:click={hello}>click me</button>

 

全局数据管理

当我们需要一个全局的数据仓库的时候,用此方法

新建 store.svelte文件:

import { writable } from 'svelte/store';
export const count = writable(0);
  • 引入 writable方法声明全局变量

  • 导出一个名为 count的变量了,并且初始值使用 writable标明了

 

接收全局变量值

在页面中需要先引入 全局变量

    import { count } from './stores.js';

通过定义该页面的自定义变量来接收全局变量

语法:

"自定义变量名".subscribe((value)=>{"所进行的操作"})
<script>  
    let number;
//读取全局数据
   count.subscribe((value) => {
       number = value;
  });
</script>

{{number}}

 

重置全局变量值

  • 将值重置为新值

  • 语法:

"全局变量名".set("具体值");
  <button
       on:click={() => {
          count.set(1002);
      }}>设置</button
   >

 

操作全局变量值

  • 通过uppdate方法来更新全局数据

  • 语法

"全局变量名".update((val)=>{"所进行的操作"});
    <button
       on:click={() => {
          count.update((val) => {
              val++;
              return val;
          });
      }}>-</button
   >

 

只读全局仓库:只允许内部修改

export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => {
set(new Date());
}, 1000);

return function stop() {
clearInterval(interval);
};
});

 

利用derived基于原有的仓库数据进行定义新变量

import { readable, derived } from 'svelte/store';

export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => {
set(new Date());
}, 1000);

return function stop() {
clearInterval(interval);
};
});

const start = new Date();

export const elapsed = derived(
time,
$time => Math.round(($time - start) / 1000)
);

 

 

Axios的封装

安装axios:

npm install axios

 

fetch文件

export function fetch(uri, data, method = "POST", responseType = "json") {
 return new Promise((resolve, reject) => {
   axios({
     url: BASEURL + uri,
     method: method,
     params: method === "GET" ? data : null,
     data: method === "POST" ? data : null,
     // headers: {
     //   "Content-Type": "application/json",
     // },
     responseType: responseType,
  })
    .then(function (response) {
       resolve(response.data);
    })
    .catch(err => {
       reject(err);
    });
});
}

 

 

通过ajax请求数据

创建api.js文件,导入fetch文件。

在api.js写请求接口。

 

配置路由

路由配置

安装路由依赖:

npm install svelte-spa-router

定义路由:

import Home from './routes/Home.svelte'
import Author from './routes/Author.svelte'
import Book from './routes/Book.svelte'
import NotFound from './routes/NotFound.svelte'

const routes = {
   // Exact path
   '/': Home,

   // Using named parameters, with last being optional
   '/author/:first/:last?': Author,

   // Wildcard parameter
   '/book/*': Book,

   // Catch-all
   // This is optional, but if present it must be the last
   '*': NotFound,
}

使用路由:

<body>
   <Router {routes}/>
</body>

 

接收路由参数:

<script>
import {location, querystring} from 'svelte-spa-router'
</script>
<p>The current page is: {$location}</p>
<p>The querystring is: {$querystring}</p>

路由跳转:

声明式:

<script>
import {link} from 'svelte-spa-router'
let myLink = "/book/456"
</script>
<a use:link={myLink}>The Biggest Princess</a>

导航式:

import {push, pop, replace} from 'svelte-spa-router'

// The push(url) method navigates to another page, just like clicking on a link
push('/book/42')

// The pop() method is equivalent to hitting the back button in the browser
pop()

// The replace(url) method navigates to a new page, but without adding a new entry in the browser's history stack
// So, clicking on the back button in the browser would not lead to the page users were visiting before the call to replace()
replace('/book/3')
 
posted @   Dollom  阅读(680)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
点击右上角即可分享
微信分享提示