svelte归档

本文最后更新于:2021年5月23日 上午

rollup作者搞的框架,玩玩看orz..

学了一两天,跟vue比较像的一点是都是用模板语法,结构啥的都比较像,毕竟框架要解决的问题都是相似的。但跟vue的实现是完全不同,这部分看情况吧,有需要就去研究下。

1.模版里使用变量

<p>{name}</p>
<img src={url}></img>
<script>
	let name = 'john';
  let url = 'xxx/xxx.jpg';
</script>

更新数组与对象

  • 数组

    并不支持数组的原生方法(push,pop,shift,unshift,splice),也就是说以上方法不会触发响应。

  • 对象

    经验法则:变量名必须出现在赋值语句左侧,否则不触发响应(如变量名obj)

    let obj = {
      foo:{
        bar: 'aaa',
      }
    }
    // 触发响应
    obj = { foo: {bar: 'bbb' } };
    obj.foo = { bar: 'bbb' };
    obj.foo.bar = 'bbb';
    
    // 不触发响应
    let foo = obj.foo;
    foo = { bar: 'ccc' };
    foo.bar = 'ccc';

2.反应式(响应)

  • 反应式声明(类似vue的computed)

    <script>
    	let count = 0;
    	$: double = count * 2;
    </script>
  • 运行时使用

    let count = 0;
    // 单行
    $: console.log(`the count is ${count}`);
    // 代码块
    $: {
      console.log(`the count is ${count}`);
      alert(`the count is ${count}`)
    }

3.循环

<script>
	let cats = [
    {id: 0, name: 'Mimi'},
    {id: 1, name: 'Miao'},
    {id: 2, name: 'Tom'},
  ]
</script>
<ul>
	{#each cats as cat}
  <li>id:{cat.id}, name:{cat.name} </li>
  {/each}
</ul>

默认第二个参数是数组的index

{#each cats as cat, index}
  <li>index:{index}, name:{cat.name}</li>
{/each}

当然也可以进行结构赋值

{#each cats as {id, name}, index}
	<li>index: {index}, id:{id}, name:{name}</li>
{/each}

唯一标识符,也就是key值。

{#each cats as cat(cat.id)}
	<li> name:{cat.name}</li>
{/each}

svelte内部是用Map来处理key,因此你完全可以把整个对象作为key

{#each cats as cat(cat)}
	<li> name:{cat.name}</li>
{/each}

4.事件

可以用on:<event>的形式监听任何事件(注意冒号:后不能加空格)

<script>
	function handleClick(){
    console.log('click');
  }
</script>
<div on:click={handleClick}></div>

修饰符列表

once

仅执行一次

<script>
	function handleClick(){
    console.log('click');
  }
</script>
<div on:click|once={handleClick}></div>

capture

在capture阶段触发而不是bubbling阶段

self

仅当event.target是自身时才执行

更多….

上述修饰符也可以组合使用,如 on:click|once|capture={handleClick}

5.组件事件

有点像vue的emit和on

例如,约定事件message,子组件Inner.svelte

<script>
	import {createEventDispatcher} from 'svelte';
  const dispatch = createEventDispatcher();
  function handleClick(){
    dispatch('message', {
      text: 'hello',
    })
  }
</script>
<button on:click={handleClick}>
	Button
</button>

父组件app.svelte,在事件的detail属性里得到传参

<script>
  import Inner from './Inner.svelte';
  function handleMessage(event) {
    console.log(event.detail); // {text: "hello"}
  }
</script>

<main>
  <Inner on:message={handleMessage} />
</main>

注意:exclamation::​组件事件不会冒泡,如果Inner和app组件中间还有一层组件middle,那么需要在middle组件处转发事件,才能使Inner的触发的事件传递到app上

// middle组件内
function forward(event){
  dispatch('message', event.detail);
}
<Inner on:message={forward}/>

有点麻烦,简写的形式是不给message事件传值,不传值的情况默认转发所有事件

<script>
	import Inner from './Inner.svelte'
</script>
<Inner on:message/>

6.双向绑定

使用bind:的形式,input输入会修改变量name,改变属性name也会修改input里的值

<script>
	let name = '';
	function handleInput(){
		console.log(name);
	}
</script>

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

定义input的值类型, number, range, checkbox, radio

<script>
	let a = 0;
</script>
<label>
	<input type=number bind:value={a} min=0 max=10>
	<input type=range bind:value={a} min=0 max=10>
</label>

7.生命周期

  • onMounted(),如果回调函数的返回值为函数,那么将在销毁组件时执行

  • onDestroy()

  • beforeUpdate() / afterUpdate()

  • tick(),返回一个promise,在dom更新后执行。类似于vue里的nextTick()

8.Store

基本使用

store.js

import { writable } from 'svelte/store';
export const count = writable(0);

App.svelte

<script>
	import { count } from './stores.js';
	function increment() {
		count.update(n=>n+1);
	}
  function decrementer(){
    count.update(n=>n+1);
  }
  function resetter(){
    count.set(0);
  }
</script>
<button on:click={increment}>+</button>
<button on:click={decrementer}>-</button>
<button on:click={resetter}>reset</button>

避免内存泄漏

使用unsubscribe

let count_value;
const unsubscribe = count.subscribe(value => {
	count_value = value;
});
onDestroy(unsubscribe);

简写–自动subscribe,使用$来快速使用store的变量。仅在store变量在顶级作用域声明或import时生效。

<script>
  import { count } from './stores.js';
</script>
<h1>
  the count is {$count}
</h1>

9.


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!