Introduction
Let's remember how we write web applications without frameworks:
Create an element
// h1
const h1 = document.createElement('h1');
h1.textContent = 'Hello World';
// ... body
document.body.appendChild(h1);
Updating the element
// h1
h1.textContent = 'Bye World';
Removing the element
// , h1
document.body.removeChild(h1);
Add styles to the element
const h1 = document.createElement('h1');
h1.textContent = 'Hello World';
// h1
h1.setAttribute('class', 'abc');
// ... <style> head
const style = document.createElement('style');
style.textContent = '.abc { color: blue; }';
document.head.appendChild(style);
document.body.appendChild(h1);
Listening for click events on an element
const button = document.createElement('button');
button.textContent = 'Click Me!';
// click
button.addEventListener('click', () => {
console.log('Hi!');
});
document.body.appendChild(button);
In pure JavaScript, we need to write something like this.
The main purpose of this article is to show how the Svelte compiler converts the Svelte syntax into the code blocks I showed above.
Svelte syntax
Next, I'll show you some basic Svelte syntax examples.
, Svelte:
<h1>Hello World</h1>
, <style>
:
<style>
h1 {
color: rebeccapurple;
}
</style>
<h1>Hello World</h1>
Svelte HTML, Svelte HTML .
, :
<script>
let name = 'World';
</script>
<h1>Hello {name}</h1>
JavaScript .
, on:
<script>
let count = 0;
function onClickButton(event) {
console.log(count);
}
</script>
<button on:click={onClickButton}>Clicked {count}</button>
<script>
let count = 0;
function onClickButton(event) {
count += 1;
}
</script>
<button on:click={onClickButton}>Clicked {count}</button>
Svelte JavaScript, .
Svelte
Svelte , JavaScript.
, Svelte , . , Svelte .
:
<h1>Hello World</h1>
:
function create_fragment(ctx) {
let h1;
return {
c() {
h1 = element('h1');
h1.textContent = 'Hello world';
},
m(target, anchor) {
insert(target, h1, anchor);
},
d(detaching) {
if (detaching) detach(h1);
},
};
}
export default class App extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, {});
}
}
2 :
create_fragment
class App extends SvelteComponent
create_fragment
Svelte - Svelte. Svelte DOM .
create_fragment
Svelte DOM .
create_fragment
. , :
c()
create. .
h1
:
h1 = element('h1');
h1.textContent = 'Hello World';
m(target, anchor)
mount. .
h1
target
:
insert(target, h1, anchor);
// http://github.com/sveltejs/svelte/tree/master/src/runtime/internal/dom.ts
export function insert(target, node, anchor) {
target.insertBefore(node, anchor || null);
}
d(detaching)
destroy. .
h1
DOM :
detach(h1);
// http://github.com/sveltejs/svelte/tree/master/src/runtime/internal/dom.ts
function detach(node) {
node.parentNode.removeChild(node);
}
. , .
export default class App extends SvelteComponent
- , API.
, create_fragment. Svelte , .
<h1>
, :
<!-- empty -->
class App extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, null, safe_not_equal, {});
}
}
Svelte null
create_fragment
!
init - , Svelte , :
,
ctx
Svelte create_fragment
DOM.
, this.$$
.
, $$
, . !
Svelte , :
<script>
let name = 'World';
</script>
<h1>Hello {name}</h1>
:
function create_fragment(ctx) {
// ...
return {
c() {
h1 = element('h1');
h1.textContent = `Hello ${name}`;},
// ...
};
}
let name = 'World';
class App extends SvelteComponent {
// ...
}
:
,
<script>
,
h1
, , .
:
<script>
let name = 'World';
function update() {
name = 'Svelte';
}
</script>
<h1>Hello {name}</h1>
… :
function create_fragment(ctx) {
return {
c() {
h1 = element('h1');
t0 = text('Hello ');
t1 = text(/*name*/ ctx[0]);
},
m(target, anchor) {
insert(target, h1, anchor);
append(h1, t0);
append(h1, t1);
},
p(ctx, [dirty]) {
if (dirty & /*name*/ 1) set_data(t1, /*name*/ ctx[0]);
},
d(detaching) {
if (detaching) detach(h1);
},
};
}
function instance($$self, $$props, $$invalidate) {
let name = 'World';
function update() {
$$invalidate(0, (name = 'Svelte'));
}
return [name];
}
export default class App extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}
:
<h1>
2 ,text (...)
create_fragment
p(ctx, dirty)
instance
script
instance
,
create_fragment
,ctx[0]
?
Svelte , <script>
.
:
? :
count++
? :
name = 'Svelte'
?
<h1>Hello {name}</h1>
?
const i = 1;
let i = 1;
...
Svelte , (- name = 'Svelte';
), h1
, .
, , p
.
p(ctx, dirty)
u_p_date
p(ctx, dirty)
, (dirty
) (ctx
) .
instance
, App
.
instance
.
, , App
, :
<App />
<App />
<App />
<!-- -->
<h1>Hello world</h1>
<h1>Hello world</h1>
<h1>Hello world</h1>
name
1 , instance
:
<App />
<App />
<App />
<!-- -->
<h1>Hello world</h1>
<h1>Hello Svelte</h1>
<h1>Hello world</h1>
<!-- -->
instance($$self, $$props, $$invalidate)
instance :
Svelte ctx
.
init
Svelte instance
ctx
:
// ,
const ctx = instance(/*...*/);
const fragment = create_fragment(ctx);
//
fragment.c();
// DOM
fragment.m(target);
name
name
, ctx
:
t1 = text(/* name */ ctx[0]);
$$invalidate
Svelte - $$invalidate
.
,
$$invalidate
:
name = 'Svelte';
count++;
foo.a = 1;
//
name = 'Svelte';
$$invalidate(/* name */, name);
count++;
$$invalidate(/* count */, count);
foo.a = 1;
$$invalidate(/* foo */, foo);
$$invalidate
:
// ...
const ctx = instance(/*...*/);
const fragment = create_fragment(ctx);
// ,
const dirty = new Set();
const $$invalidate = (variable, newValue) => {
// ctx
ctx[variable] = newValue;
//
dirty.add(variable);
//
scheduleUpdate(component);
};
// ,
function flushUpdate() {
//
fragment.p(ctx, dirty);
//
dirty.clear();
}
<script>
let name = 'world';
function update() {
name = 'Svelte';
}
</script>
<h1 on:click={update}>Hello {name}</h1>
:
function create_fragment(ctx) {
// ...
return {
c() {
h1 = element('h1');
t0 = text('Hello ');
t1 = text(/*name*/ ctx[0]);
},
m(target, anchor) {
insert(target, h1, anchor);
append(h1, t0);
append(h1, t1);
dispose = listen(h1, 'click', /*update*/ ctx[1]);},
p(ctx, [dirty]) {
if (dirty & /*name*/ 1) set_data(t1, /*name*/ ctx[0]);
},
d(detaching) {
if (detaching) detach(h1);
dispose();},
};
}
function instance($$self, $$props, $$invalidate) {
let name = 'world';
function update() {
$$invalidate(0, (name = 'Svelte'));
}
return [name, update];}
// ...
:
instance
2
listen
mount
dispose
destroy
, instance
, .
update
, instance
ctx
.
Svelte JavaScript, , .
listen dispose
, , Svelte , DOM.
,
<h1
on:click={update}
on:mousedown={update}
on:touchstart={update}>
Hello {name}!
</h1>
:
// ...
dispose = [
listen(h1, 'click', /*update*/ ctx[1]),
listen(h1, 'mousedown', /*update*/ ctx[1]),
listen(h1, 'touchstart', /*update*/ ctx[1], { passive: true }),
];
// ...
run_all(dispose);
, Svelte :
//
dispose1 = listen(h1, 'click', /*update*/ ctx[1]);
dispose2 = listen(h1, 'mousedown', /*update*/ ctx[1]);
dispose2 = listen(h1, 'touchstart', /*update*/ ctx[1], { passive: true });
// ...
dispose1();
dispose2();
dispose3();
, .
, , Svelte JavaScript. Svelte dispose
, .
Svelte - HTML.
Svelte, JavaScript .
3 :
1. create_fragment
, DOM .
2. instance
,
<script>
, .
, .
$$invalidate
3. class App extends SvelteComponent
create_fragment
instance
-
Svelte JavaScript, :
h1
,
create_fragment
instance
,
dispose
, .
...
, Svelte .
:
Join the Russian-speaking Svelte community on Telegram - @sveltejs . There you can find help or advice on almost any issue, as well as discuss the most pressing topics. If you don't have time for chats, subscribe to the @sveltejs_public channel for news and useful materials on Svelte.
I hope this material was useful for you!