Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add <svelte:this /> tag #58

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

kwangure
Copy link

@Prinzhorn
Copy link

I wouldn't deprecated the current API because your design suffers from one limitation: you can only get a single reference to each of the things. But there are pre-processors that dynamically need to use things like onDestroy (e.g. https://github.com/zodern/melte). If the old API is removed and you cannot import onDestroy this would become a mess.

@kwangure
Copy link
Author

kwangure commented Oct 4, 2021

I propose one <svelte:this /> tag, but you can get multiple references. Preprocessors by definition run before the compiler and can modify markup as needed.

<svelte:this 
	on:destroy={localHandler} 
	on:destroy={preprocessorHandler} 
	on:destroy 
	bind:props={localProps} 
	bind:props={preprocessorPropVar}/>

@Prinzhorn
Copy link

<svelte:this 
	on:destroy={localHandler} 
	on:destroy={preprocessorHandler} 
	on:destroy 
	bind:props={localProps} 
	bind:props={preprocessorPropVar}/>

This is not valid. I don't know what parser Svelte uses, but none of setAttribute, getAttribute or removeAttribute can work with duplicates. As far as I'm aware nowhere in Svelte are duplicate attributes currently used or allowed. You get a "Attributes need to be unique" error. And since Svelte tries to be as close to valid HTML as possible I don't see this happen.

Lifecycle functions also don't have to be inside a .svelte file, as long as they run synchronously on component creation. This is not only relevant for preprocessors but also useful for other abstractions, e.g. https://github.com/zodern/melte/blob/8884995a9dc27af2852f838bea15ea09f21b7ea2/tracker.js#L8-L12

@kwangure
Copy link
Author

kwangure commented Oct 5, 2021

Binding to DOM elements needs attributes to be unique because setAttribute/getAttribute would overwrite each other. So far $feature APIs in Svelte have largely been readonly which means they're not bound by the uniqueness constraint.

I'm not sure if there's a technical reason why bind:clientWidth and bind:offsetWidth are required to be unique even though they're readonly. Perhaps for onsistency with other attributes? 🤷

That said, I agree there is a case to be made for external code doing their own clean up and handling lifecycle events imperatively.

@lukaszpolowczyk
Copy link

I have a suggestion for dispatch:

<script>
  function sayHello() {
    testevent({
      test: 'food'
    });
  }
</script>.
<svelte:this dispatch:testevent />

<div on:click={sayHello}>test</div>.

That is with dispatch:testevent={testevent} or dispatch:testevent and WITHOUT e.g. let testevent = _=>{};.

With bind:name you need let name;, but this is a different syntax and can be simplified.

Giving the name already in the attribute also makes it clearer.

@winstonDeGreef
Copy link

<svelte:this 
	on:destroy={localHandler} 
	on:destroy={preprocessorHandler} 
	on:destroy 
	bind:props={localProps} 
	bind:props={preprocessorPropVar}/>

Instead of that, it could be possible that multiple bindings on atributes are seperated by commas. ie:

<svelte:this
	on:destroy={localHandler, preprocessorHandler}
	bind:props={localProps, preprocessorPropVar}/>

@kwangure
Copy link
Author

The comma is already an operator in JavaScript. Comma separated values returns the last value in a list.

let foo = ("bar", "baz");

console.log(foo); // baz

Tangentially, a debugging tip: do on:destroy={console.log(handler), handler} when want to log inline expressions in the Svelte curly braces to see what's what.

@winstonDeGreef
Copy link

The comma is already an operator in JavaScript. Comma separated values returns the last value in a list.

let foo = ("bar", "baz");

console.log(foo); // baz

Tangentially, a debugging tip: do on:destroy={console.log(handler), handler} when want to log inline expressions in the Svelte curly braces to see what's what.

or make it possible for on:destroy etc. to accept an array aswel.
This would make it so that the both following possibilities are valid.

  1. on:destroy={handler}
  2. on:destroy={[handler, preprocessorHandler]

@lukaszpolowczyk
Copy link

<svelte:this> + SvelteKit

I think it would be interesting to add stores $app/stores from SvelteKit as a <svelte:this> parameter:

<script>
  let pathname = 'untracked';

  function start_subscribing() {
    page.subscribe($page => {
      pathname = $page.url.pathname;
    });
  }
</script>
<svelte:this
  stores:navigatin
  stores:page
  stores:session
  stores:updated
/>

Benefit: Avoids the special case with getStores() that you need to use, if you need to defer store subscription until after the component has mounted, for some reason. With <svelte:this stores:page> the behavior is always the same.

I don't know how feasible it would be to contain the SvelteKit part inside <svelte:this>, but the whole <svelte:this> is also only theoretical for now...

I wonder if anything else could be moved to <svelte:this>...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants