Quick side-by-side comparison of Svelte 2 and 3
Client-side component API
import App from './App.html';
const app = new App({
target: document.querySelector('main'),
data: { name: 'world' }
});
app.set({ name: 'everybody' });
// get() is being removed for v3...
const { name } = app.get();
const listener = app.on('thingHappened', event => {
console.log(`A thing happened: ${event.thing}`);
});
// some time later...
listener.cancel();
app.destroy();
import App from './App.svelte';
const app = new App({
target: document.querySelector('main'),
props: { name: 'world' }
});
app.$set({ name: 'everybody' });
// must set compiler option: { accessors: true }
const { name } = app;
app.$on('thingHappened', event => {
console.log(`A thing happened: ${event.detail.thing}`);
});
// some time later...
// No need to cancel $on listener
app.$destroy();
Events
export default {
methods: {
sayHello() {
this.fire('message', {test: 'Hello!'})
}
}
}
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function sayHello() {
dispatch('message', { text: 'Hello!' });
}
Computed properties
export default {
data() {
return {
name: 'Fred',
place: 'world!'
};
},
computed: {
hello({name, place}) {
return `${name} says 'Hello, ${place}'`
}
}
}
// use export if your property needs to be set externally
export let name = 'Fred';
let place = 'world!'
// v3 has no computed properties
// instead it uses reactive statements
$: hello = `${name}, says 'Hello, ${place}`
Directives
<div class:foo="a ? b : c">...</div>
<div class:foo="{a ? b : c}">...</div>
Component lifecycle
export default {
data() {
return { name: 'Fred' }
},
oncreate() {
console.log('The component has been created');
},
onstate({ changed, current, previous }) {
if (previous && changed.name) {
console.log(`${previous.name} -> ${current.name}`);
}
},
onupdate({ changed, current, previous }) {
console.log('The DOM has been updated');
},
ondestroy() {
console.log('The component has been destroyed');
}
}
import { onMount, beforeUpdate, afterUpdate, onDestroy } from 'svelte';
export let name = 'Fred';
let prev_name;
onMount(() => {
console.log('the component has mounted');
});
beforeUpdate(() => {
if (prev_name && name !== prev_name) {
console.log(`${prev_name} -> ${name}`);
}
prev_name = name;
});
afterUpdate(() => {
console.log('the component just updated');
});
onDestroy(() => {
console.log('the component is being destroyed');
});
Helpers
<div>{ dayjs(dateString) }</div>
<script>
import dayjs from 'dayjs';
export default {
data() {
return { dateString: '2018-08-08' }
},
helpers() {
dayjs
}
}
</script>
<script>
import dayjs from 'dayjs';
let dateString = '2018-08-08';
</script>
<div>{ dayjs(dateString) }</div>
Custom methods
<button on:click="say('hello')">say hello!</button>
<script>
export default {
methods: {
say(message) {
console.log(message);
}
}
};
</script>
<script>
// 'export' to expose method externally
function say(message) {
console.log(message);
}
</script>
<button on:click="{() => say('hello')}">say hello!</button>
Custom event handlers
<div on:drag="handleDrag(event)">drag me</div>
<script>
export default {
events: {
drag(node, callback) {
// implementation goes here
}
}
}
</script>
<script>
function drag(node) {
// implementation goes here
return {
destroy() {
// the node has been removed from the DOM
}
};
}
</script>
<div use:drag>drag me</div>
Refs
<canvas ref:canvas></canvas>
<script>
export default {
oncreate() {
const canvas = this.refs.canvas;
const ctx = canvas.getContext('2d');
}
}
</script>
<script>
import { onMount } from 'svelte';
let canvasElement;
onMount(() => {
const ctx = canvasElement.getContext('2d');
});
</script>
<canvas bind:this={canvasElement}></canvas>