绑定
- svelte与vue,react一样使用单向数据流,父组件可以设置属性传递给子组件,也可以给一个元素设置属性。
- 使用bind语法可以实现值的双向绑定(类似vue的v-model)
- bind可以将绑定值直接转化为type约定好的类型
- checkbox,radio,textarea绑定方式同input不在赘述
- 绑定select时如果没有给绑定值赋初始值,select会默认选中option,并且应注意此时的绑定值仍是未定义,应谨慎使用该值
- 支持contenteditable="true"属性的标签,可以使用textContent与innerHTML属性绑定
- 支持each块绑定,媒体标签属性值绑定,DOM尺寸绑定(绑定值是只读)
- bind的this绑定类似于vue中的ref,使用this可以绑定到任何标签并允许获取对渲染标签的引用。
- bind组件绑定能够直接获取子组件中的某一个属性值
<script>
let name = 'world';
</script>
<input bind:value={name}>
<h1>Hello {name}!</h1>
<script>
let a = '2';
</script>
<label>
<input type=number bind:value={a} min=0 max=10> //need number
<input type=range bind:value={a} min=0 max=10> //need number
</label>
<script>
let html = '<p>Write some text!</p>';
</script>
<div contenteditable="true" bind:innerHTML={html}></div>
<pre>{html}</pre>
<style>
[contenteditable] {
padding: 0.5em;
border: 1px solid #eee;
border-radius: 4px;
}
</style>
生命周期
- 组件加载
- 页面加载时请求的接口可以放在onMount中调用
- 对于兄弟组件,onMount会根据调用的顺序从上往下执行
- 对于父子组件,从里往外执行,子组件onMount执行完毕才会执行父组件的onMount
- 如果onMount返回了一个函数,函数会在组件销毁时执行
- 组件更新
- 对于兄弟组件beforeUpdate和afterUpdate按照组件调用顺序从上往下执行
- 对于父子组件先执行父组件的beforeUpdate然后执行子组件的beforeUpdate,当子组件的beforeUpdate执行完毕之后,再执行父组件的afterUpdate最后执行子组件的afterUpdate
- 如果组建中同事存在beforeupdate与onMount,首次beforeUpdate回调会在onMount之前执行,而父组件的onMount会在子组件的afterUpdate执行完毕后执行
- 组件销毁
- 对于兄弟组件按照调用顺序从上到下执行
- 对于父子组件先执行父组件的onDestroy,再执行子组件的onDestroy
生命周期 | 作用 | 说明 |
---|---|---|
onMount | 组件加载 | 在组件加载完成之后执行,类似于window.onload |
beforeUpdate | 组件更新 | 在组件更新时会执行该钩子函数 |
afterUpdate | 组件更新 | 组件更新完成时会执行该钩子函数 |
onDestroy | 组件销毁 | 在组件加载完成之后执行该钩子 |
完整的生命周期:
Tick函数
- 解决组件中某个状态更新了但是DOM没有更新的情况
- tick函数会返回一个Promise,当组件状态更细之后,会触发Promise的resolves
- 类似于vue中的nextTick函数
<script>
import { beforeUpdate, tick } from 'svelte';
beforeUpdate(async () => {
await tick();
console.log('这段代码会在组件状态更新后执行');
});
</script>
Stores
-
类比vuex等其他状态公共管理库的使用场景,Svelte的Stores用于组件间的状态共享,不仅限于父子兄弟组件通信
-
在Svelte中使用store.js来存储变量,以官网count为例,可以在任意组件中订阅变量变化也可以在任意组建中更新或者设置变量值
-
更新状态值:count.update(fn) update方法仅适用writable变量
count.update(n=>n+1) //update函数接收一个回调函数,n代表当前的值
-
设置状态值:count.set(val) set方法仅适用writable变量
count.set(0)
-
订阅变量变化:count.subscribe(fn)
count.subscribe(value=>{ count_value = value })
-
自动订阅:一般subscribe后需要在onDestroy钩子函数中取消订阅,不然会造成内存泄露,但是当订阅了多个store中的属性值时,会显得很复杂,可以使用$来引用store值。参考官方实例
-
任何以$开头的变量Svelte都将认为他是一个store属性,并且Svelte会阻止使用$创建变量
-
只读stores:一些不需要在其他地方写入的stores可以使用readable stores。readable()函数第一个参数可以是一个初始值,也可以是null或者undefined。第二个参数是start()函数该函数有set方法。并且返回一个stop函数。在取消订阅时调用stop()
import { readable } from 'svelte/store'; export const time = readable(new Date(), function start(set) { const interval = setInterval(() => { set(new Date()); }, 1000); return function stop() { clearInterval(interval); }; });
-
stores派生:类似于vuex的getter可以依赖其他的stores值输出一个新的派生值。
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) );
-
自定义stores:只要一个对象正确的使用 subscribe ,它就是可以称之为store。因此,使用特定语法来创建自定义 stores非常容易。
// stires.js import { writable } from 'svelte/store'; function createCount() { const { subscribe, set, update } = writable(0); return { subscribe, increment: () => update(n => n + 1), decrement: () => update(n => n - 1), reset: () => set(0) }; } export const count = createCount(); //app.svelte <script> import { count } from './stores.js'; </script> <h1>The count is {$count}</h1> <button on:click={count.increment}>+</button> <button on:click={count.decrement}>-</button> <button on:click={count.reset}>reset</button>
-
绑定store:当stores属性值有writable有可写属性,即可使用bind绑定值
// stores.js import { writable, derived } from 'svelte/store'; export const name = writable('world'); export const greeting = derived( name, $name => `Hello ${$name}!` ); // app.svelte <script> import { name, greeting } from './stores.js'; </script> <h1>{$greeting}</h1> <input bind:value={$name}> <button on:click="{() => $name += '!'}"> Add exclamation mark! </button>