Compile Svelte in your head. Part 1/3

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 .





, Svelte:





<h1>Hello World</h1>
      
      



Svelte REPL





, <style>



:





<style>
  h1 {
    color: rebeccapurple;
  }
</style>

<h1>Hello World</h1>
      
      



Svelte REPL





Svelte HTML, Svelte HTML .





, :





<script>
  let name = 'World';
</script>

<h1>Hello {name}</h1>
      
      



Svelte REPL





JavaScript .





, on:







<script>
  let count = 0;
  function onClickButton(event) {
    console.log(count);
  }
</script>

<button on:click={onClickButton}>Clicked {count}</button>
      
      



Svelte REPL





:





<script>
  let count = 0;
  function onClickButton(event) {
    count += 1;
  }
</script>

<button on:click={onClickButton}>Clicked {count}</button>
      
      



Svelte REPL





Svelte JavaScript, .





Svelte

Svelte , JavaScript.





, Svelte , . , Svelte .





:





<h1>Hello World</h1>
      
      



Svelte REPL





:





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 -->
      
      



Svelte REPL





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>
      
      



Svelte REPL





:





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>
      
      



Svelte REPL





… :





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]);
      
      



, ctx



, Map



, . .





$$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>
      
      



Svelte REPL





:





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>
      
      



Svelte REPL





:





// ...
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











  • API





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!








All Articles