关于前端:聊聊Sveltejs技术它做了什么以及如何实现的下

聊聊Svelte.js技术它做了什么以及如何实现的(下)

一. 循环语句

     循环渲染这个咱们必定是离不开了, Svelte.js给咱们提供了乏味的书写形式。

<script>
  const arr = ['x1', 'x2', 'x3'];
</script>

<ul>
  {#each arr as item}
    <li>{item}</li>
  {/each}
</ul>

     尽管Svelte.js没有虚构dom, 然而循环的时候也须要key, 它的写法有点非凡。

<script>
  const arr = ['x1', 'x2', 'x3'];
</script>

<ul>
  {#each arr as item, i (i)}
    <li>{i} --- {item}</li>
  {/each}
</ul>

     下面的(i)就是key值, i是序号必须应用,item隔开。

二. 循环语句编译成什么


初始化就一个变量这个没啥说的。

     图二的ctx是个素组, ctx[0]是咱们定义的arr, ctx[1]是以后li对应的值。

三. 循环语句如何解决key

上面是设置了key的循环体编译后的代码。

咱们重点看下更新dom数据的时候key是怎么工作的。

其实在Svelte.js外面也须要diff算法来更新dom, 这个点须要明确。

四. 父子组件

父组件

/src/App.svelte

<script>
  import Son from './子组件.svelte';
  const options = {
    msg: 'xxxxxx',
  };

  // 如此传递属性
  const footer = {
    footer1: 'footer1',
    footer2: 'footer2',
  };

  // 解决订阅事件
  function handleEmit(res) {
    console.log('相应事件1', res);
    console.log('相应事件2', res.detail);
  }
</script>

<div>
  <p>父组件</p>
  <Son {options} {...footer} on:emit={handleEmit} />
</div>
子组件

/src/子组件.svelte

<script>
  import { createEventDispatcher } from 'svelte';

  export let options;
  export let footer1;
  export let footer2;

  // 触发事件公布
  const dispatch = createEventDispatcher();

  function emit() {
    dispatch('emit', {
      msg: '你好',
    });
  }
</script>

<div>
  <p>子组件: {options.msg}</p>
  <p>footer1: {footer1}</p>
  <p>footer2: {footer2}</p>
  <button on:click={emit}>点击触发事件</button>
</div>
  1. 子组件间接import引入子组件即可应用。
  2. 父组件行间传递参数, 子组件export接管。
  3. 父组件可应用扩大运算符传递参数。
  4. 父组件on:emit={handleEmit}的模式监听子组件公布的事件。
  5. 子组件引入createEventDispatcher实现事件的公布。
  6. 子组件能够轻易扭转传递过去的值, 不会影响该值在父组件内的值(重点)。
  7. 父组件传递给子组件的值的扭转, 会从新渲染子组件。

五. 父子组件打包剖析

六. 款式

     在Svelte.js外面款式是默认沙盒的, 也就是说咱们在一个.svelte文件外面写的款式不会渗透到全局。
     很不便很爽的一点是咱们不必模板字符串的形式拼接, 这样写款式真爽。

<script>
  const color = 'red';
  const isBlack = true;
</script>

<div>
  <p>文字1</p>
  <p style="color:{color}" class:black={isBlack}>文字2</p>
</div>

<style>
  p {
    color: blueviolet;
    font-size: 29px;
    font-weight: 800;
  }
  .black {
    border: 1px solid black;
  }
</style>

class:black={isBlack}的意思就是只有isBlacktrue才会赋予black这个className。

如果要设置全局款式能够在html或者main.js文件外面引入。

七. 生命周期

     生命周期的概念当初根本所有库都有, svelte在这一点做的也很不错。

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

  onMount(() => {
    console.log('mounted');
  });

  onDestroy(() => {
    console.log('onDestroy');
  });

  beforeUpdate(() => {
    console.log('beforeUpdate');
  });

  afterUpdate(() => {
    console.log('afterUpdate');
  });
</script>
  1. onMount 将在组件首次出现到DOM之后运行。
  2. onDestroy 当销毁组件时调用。
  3. beforeUpdate 在DOM更新前运行。
  4. afterUpdate 在DOM更新后运行。

留神生命周期能够屡次调用如下:

  onMount(() => {
    console.log('mounted1');
  });

  onMount(() => {
    console.log('mounted2');
  });

八. 异步申请

     异步申请与组件构造的交融设置, 比方咱们平时些我的项目要为不同dom块写loading成果, 这样就要有n个loading变量, 而上面的办法会使咱们少定义一些变量。

<script>
  function ajax() {
    return new Promise((res) => {
      setTimeout(() => {
        res('申请胜利');
      }, 1000);
    });
  }
</script>

<div>
  {#await ajax()}
    <p>...loading</p>
  {:then res}
    <p>
      res: {res}
    </p>
  {/await}
</div>

     成果为申请中显示loading, 申请完显示内容, 前面还能够加一个{:catch err}标签, 然而在这里处理错误其实不太好。

打包代码的样子

handle_promise办法外面, 如果判断咱们传入的是promise则替咱们执行promise并把后果赋予下来, 他还有其余简单操作咱们不必深究。

     看起来挺实用的写法其实也不太实用。

九. 计算属性

     你能够在 JavaScript 中用标识符标记一个语句,如下所示:$: foo = bar。它会在 foo = bar 语句中增加一个名为 $ 的标识符(如果之前未定义 foo,则严格模式下会出错)。
     所以在这种状况下,当 Svelte 看到任何带有 $: 前缀的语句时,它就晓得右边的变量要从左边的变量中获取值。咱们当初有了一种办法能够将一个变量的值绑定到另一个变量。

在js外面间接编写是不会报错的, 长常识了原来咱们能够利用这点, 开发本人的编译器来发明新的语法规定:

计算属性的用法:
<script>
  let n = 1;

  $: nn = n * 2;

  function addn() {
    n++;
  }
</script>

<div>
  <button on:click={addn}>点了{nn}次</button>
</div>

上述的nn就永远等于n*2

打包后如何实现的

十. 观察者

<script>
  let n = 0;

  // 1: 大括号内的全副执行
  $: {
    const titel = 'n的值为: ';
    console.log(titel + n);
  }

  // 2: 加判断条件
  $: if (n > 5) {
    alert('n 大于 5');
  }

  function addn() {
    n++;
  }
</script>

<div>
  <button on:click={addn}>点了{n}次</button>
</div>

  1. 最开始大括号的内容默认会执行一次。
  2. 大括号内的值如果发生变化就导致大括号里的代码整体执行一次。
  3. $:能够标示条件语句。
打包后的代码

不得不拜服svelte把标识符玩的很出彩。

十一. 动画

第一种: 自带动画(淡入淡出)
<script>
  import { fade } from 'svelte/transition';
  let visible = true;

  function change() {
    visible = !visible;
  }

</script>

<button on:click={change}>点击动画</button>

{#if visible}
  <div transition:fade>第一种</div>
{/if}
  1. 第一要引入动画fade
  2. 标签定义transition:fade
第二种自定义动画
<script>
  import { elasticOut } from 'svelte/easing';
  let visible = true;

  function change() {
    visible = !visible;
  }

  // 自定义
  function whoosh(node, params) {
    const existingTransform = getComputedStyle(node).transform.replace(
      'none',
      ''
    );
    return {
      delay: params.delay || 0,
      duration: params.duration || 400,
      easing: params.easing || elasticOut,
      css: (t, u) => `transform: ${existingTransform} scale(${t})`,
    };
  }
</script>

<button on:click={change}>点击动画</button>

{#if visible}
  <div in:whoosh>自定义</div>
{/if}
  1. in:whoosh指定了动画应用whoosh函数。
  2. whoosh返回的是动画的延迟时间、执行工夫、以及css成果等等。

这个就不探讨打包文件了。

十二. 输入框双向绑定

<script>
  let value = '';
</script>

<div>
  <input type="text" bind:value />
  <p>value: {value}</p>
</div>

打包文件

做法也比拟强硬, 就是

十三. vue外面应用svelte组件

     svelte的一大劣势就是跨平台, 它能够应用在任何框架内, 因为他就是原生js代码, 这里看下咱们如何在vue我的项目中应用它。

<script>
  let n = 0;

  function addn() {
    n++;
    console.log('触发了:addn');
  }
</script>

<div>
  <button on:click={addn}>点了{n}次</button>
</div>

/src/main.js

import App from './App.svelte';
export default App;

     这里是把咱们简略写个点击事件的代码打包, yarn build 之后把bundle.js复制到名为xxx的文件夹中的index.js文件中, 放到指标工程的node_modules, 这是为了模仿实在的应用场景。

index.js文件咱们要解决一下, 不便导出。

改装前

改装后

具体的应用形式
<script>
import xxx from "xxx";

export default {
  name: "App",
  mounted() {
    new xxx({
      target: document.body, // 轻易传入你想插入的元素与初始值
    });
  },
};
</script>

十四. 技术选型

     平时开发怎么可能两个技术混合应用, 比方我用vue开发曾经引入了vue的runtime就没必要在应用这门技术了, 然而如果你是用svelte开发了一些跨平台的兼容性特地好的组件还是能够思考应用svelte来做的, 这样不论是react还是vue都能够方便使用你的组件。

    要留神在工程体量较小的时候svelte的确有劣势的, 然而逻辑简单之后就不太好用了, 咱们看了它的打包文件的写法就能得悉它在打包后必然会呈现大量的逻辑代码, 所以逻辑多到肯定水平后其实性能不肯定比runtime的模式好了。

end.

     这次就是这样, 心愿和你一起提高。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理