Transcript from the "Special Elements" Lesson
>> So we've seen that Svelte components can contain any HTML, valid HTML is already valid Svelte. But on top of that, Svelte provides a number of what we call special elements. The first of these that we're gonna look at is svelte:self. And this is a way that a component can contain itself recursively.
[00:00:18] It's really useful for things like tree views. So here, we have a tree structure, we have folders containing files, and folders containing other folders. And we want to render this tree into our app. So we're gonna change our folder.svelte, What we wanna be able to do is just type in folder and then pass in the information like that.
[00:00:51] But that's not gonna work because this component doesn't have a reference to anything called folder. Instead, we need to reference svelte:self, Like so. And now we have a tree view that represents the data structure shown here. We also have a svelte:component element, which allows you to use dynamic components.
[00:01:23] So at the moment, we have a select drop-down that is bound to these RedThing, GreenThing, and BlueThing components. But it'd be a lot nicer if we could just have a single thing that changed the value of the component dynamically, so let's get rid of all that. And we use the special this prop, And that behaves exactly the same way as it did before.
[00:02:05] If this is a null value, then it just won't render anything at all. In the same way that we can add event listeners to DOM elements, we can add event listeners to the window object with svelte:window. So here, I'm gonna add the svelte:window, and then add a keydown handler, Which has been defined here.
[00:02:39] Hang on a minute, there's already a svelte:window at the beginning of the tutorial, just gonna get rid of that. And so now if I focus this window, that keydown handler is gonna get called whenever the window receives a keydown event. And just like with DOM events, we can use modifiers like once, prevent default, and so on.
[00:03:05] We can also add bindings to the window. In this component, we have a bunch of images from the Firewatch game. This is a nice little parallax effect that they have on their homepage. And I'm gonna bind the scroll value of the window to some local state. So we have this y value which is uninitialized, and we're using that in in our markup.
[00:03:34] So we're using it to determine the transform of each of the images that form our parallax layers. And we're also using it here, inside this span style, and we're using it inside some text. So we're gonna bind the value of the window's scrollY value to our local y variable.
[00:04:00] And now, as I interact with this, we get this nice beautiful parallax motion. There's a few different bindings that we have access to. As well as the scrollY value, we have scrollX, and we have innerWidth, innerHeight, outerWidth, outerHeight. And the online binding, which is an alias to window.navigator.online, which is really useful for indicating that the reason that your app isn't receiving any data is because the app is currently offline.
[00:04:41] Just like svelte:window we have a svelte:body special element that allows you to listen for events that fire on document body. It's particularly useful for the mouseenter and mouseleave events, which don't fire on window. So gonna find the svelte:body tag here, and add the mouseenter and mouseleave handlers that have been defined up here.
[00:05:10] On.mouseenter=handleMouseenter. On.mouseleave=handleMouseleave. And now when we move our mouse into the window, a little cat appears, isn't that nice? Okay, the svelte:head element allows us to inject content into the head of the document. Normally, obviously, all of your content is gonna go in the body, but sometimes you need to do things like add a stylesheet, we can do that here.
[00:05:55] And we can change the document title and other things like that inside the svelte:head element. And then finally, we have a svelte:options element, which allows you to specify options that are used by the compiler to control the output of the component. Now we're gonna use the immutable option as our example.
[00:06:24] This is an app containing a bunch of todos. And what you'll notice is that, anytime we toggle any of the todos, all of the todos get re-rendered. And we can see that because we have this afterUpdate flash function that runs. afterUpdate runs whenever the component receives any new state.
[00:06:46] And in an ideal world, that wouldn't be running when we change a todo that doesn't affect a particular component. And so we can optimize this by telling this todo component that it should expect immutable data. Which is to say that if we're gonna give it a new todo, then it's gonna be an entirely new object, we're not mutating anything.
[00:07:12] So if we add a svelte:options, Element to our todo.svelte, Then now when we toggle these todos, only the one that we're actually toggling is receiving that flash. Because the other todos, they're completely unaffected, their data hasn't changed. And here's a list of all of the other things that you can use with svelte:options, some of it relating to web components.