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>