svelte系列 --- 响应式

1,728 阅读2分钟

所谓响应式(反应性),对应React的状态或Vue的 data

在Svelte中,声明响应式变量和我们声明一个普通变量没有差别

只要在Svelte中声明一个变量,这个变量会被自动被认为是“状态”

当你改变它的值,所有引用的地方都会自动更新

简单来说: Svelte 代替我们去关注数据应该如何更新,使开发者以十分简单的方式去更新和处理 UI 数据

触发响应式 --- 赋值

Svelte 核心是功能强大的响应式系统,用于使 DOM 与你的应用程序状态保持同步

赋值 --- 是触发 Svelte 响应式的核心,Svelte 编译器根据赋值来确定是否需要更新相应的值

<script>
  // 定义了一个变量; 会自动识别为svelte的状态,加入svelte的响应式系统中 	
  let count = 0;

   function handleClick() {
       // 当svelte的状态发生改变的时候, 所有引用这个状态的地方,都会自动更新
       // Svelte 会针对赋值生成一些代码,以便于在状态发生改变的时候告诉 DOM 什么地方需要更新
        count += 1
    }
</script>

<!-- svelte通过on:事件名的方式来绑定事件 -->
<!--
     注意: svelte的属性 引号可以省略 
     on:click="{handleClick}" <=> on:click={handleClick}
-->
<button on:click={handleClick}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

响应式声明

在某些时候,svelte中有些状态是依赖于其它状态的

当依赖的状态发生改变的时候,需要重新计算,以得出当前状态的最新结果

(其实这和vue中的计算属性是十分相似的)

<script>
  let count = 0;

  // 我们使用 $: 的方式来进行响应式声明
  // 当依赖的状态count发生改变的时候,svlete会自动计算并更新doubled的值
  /*
	注意:
            1. 响应式声明只能定义在顶层, 在其余部分定义是会报错的
            2. 定义响应式声明的变量的时候,不需要加var|let|const (此时svelte会自动为该变量进行定义和赋值)
	*/
  $: doubled = count * 2;
  
  function handleClick() {
	count += 1;
        // $: doubled = count * 2; => error
   }
</script>
// 和vue不同的时候,svlete的响应式声明即可以是变量,也可以是语句

// 语句
$: console.log(`the count is ${count}`);

// 代码块
$: {
    console.log(`the count is ${count}`);
    alert(`I SAID THE COUNT IS ${count}`);
}

// 逻辑语句
$: if (count >= 10) {
    alert(`count is dangerously high!`);
    count = 9;
}

检测响应式数据更新

svelete的响应式是由`赋值触发的

所以诸如 pushsplice 等数组方法, 虽然更新了状态,但是因为没有赋值操作,所以不会引起UI(界面)的自动更新。

// 这种语句是不起作用的
numbers.push(numbers.length + 1);

// 解决方法,赋值 --- 更新变量的名称,必须出现在赋值的左侧

// 1. 手动赋值(会出现多余的一行代码)
numbers.push(numbers.length + 1);
numbers = numbers;

// 2. 为对象(普通对象或数组)的属性赋值
// 例如 obj.foo += 1 或 array[i] = x,其实与直接赋值给自身的方式是一样的。
numbers[numbers.length] = numbers.length + 1

// 3. 展开运算符 --- 常用 --- 可以使用类似的办法来替代 pop、shift、unshift 和 splice
numbers = [...numbers, numbers.length + 1]
// svelte触发响应式更新的核心规则: 更新变量的名称,必须出现在赋值的左侧
const foo = obj.foo; foo.bar = 'baz'; // => error 不会触发ui的更新,除非后面加上 obj = obj
obj.foo.bar = 'baz'; // => success 会触发ui的更新