Giter Site home page Giter Site logo

Custom element interop about svelte HOT 11 CLOSED

sveltejs avatar sveltejs commented on September 27, 2024 1
Custom element interop

from svelte.

Comments (11)

snuggs avatar snuggs commented on September 27, 2024 1

@Rich-Harris Ironically i've implemented this within the past few weeks. I've figured it out with your exact API coincidentally (even the ability to use new xComponent format.

You and I seem to see eye to eye on recent patterns and is the reason i haven't (fully) drank the ng/em kool-aid. Besides the element based stuff I don't have much usage for the other tools the framework provides. Even "routing" is simplistic enough for me to have a mini extension. No need for anything else but I digress.

The trick was 2 abstractions (extensions). One to HTMLElement and the other to DocumentFragment So basically a "template" is a document fragment and is a nice abstraction as you can easily create one off document.createDocumentFragment and this is what the default <template> element returns from template.content it's how you access the contents and DocumentFragment dom as you may already know. There is one major caveat you may already know about but I didn't. Must use the native-shim.js webcomponent fill or some REALLY funky stuff starts happening with firing constructors super(). Also event callbacks don't get bound like you'd think. Spent 2 days battling this last week in Hawaii before finding a solution. I think it has something to do with the state of registering webcomponents being torn in migration.
CustomElements v0

// dynamically register
document.registerElement ( // less flexible
  `svelt-button`,
  {extends: 'button', prototype: Object.create (HTMLSveltButton.prototype)}
)

let element = document.registerElement (`svelt-button`, {extends: 'button'})

// dynamically create
// existing custom svelt element in the dom (i.e. <svelt-button></svelt-button>)
document.createElement (`svelt-button`, `button`)

// one caveat is this method seems to fire off the constructor (but not events)
// for existing elements in the DOM as a side effect when `creating` a new element.

CustomElements v1

// dynamically register
// preferred but DEFINITELY need a polyfill as the spec is not fully matured.
// Pulled my hair out a bit on this one.
window.customElements.define ('my-svelte', SveltComponent)

With those two abstractions i've been able to build pretty much any interface even down to the event binding. Happy to contribute.

Let me know where I can help!

P.S. I gotta tell ya my most liked feature so far with all the components is how you get an attributes mutation observer out of the box! And can control which attributes are "watched" for mutation. it's baked into the spec @mohsen1

capture d ecran 2016-11-30 a 02 21 59
capture d ecran 2016-11-30 a 02 20 52
capture d ecran 2016-11-30 a 02 23 46

from svelte.

mohsen1 avatar mohsen1 commented on September 27, 2024

...or provide an option to compile to custom elements? From output code I can see how easy it is to do that.

Since custom elements need dash separated names compiler should convert camelCase to kebob-case.

from svelte.

PaulBGD avatar PaulBGD commented on September 27, 2024

So here's a few issues I think we'll have to solve before implementing something like this:

  1. Defining a custom element is global, while svelte currently uses imports + manually listing components that the component needs.
  2. Custom elements are supposed to have names with a dash in them, while svelte components are generally named after class name conventions (CamelCase vs lisp-case)
  3. Does svelte define the component? Does the user define each component?

from svelte.

snuggs avatar snuggs commented on September 27, 2024

@PaulBGD

  1. could possibly set a global env of window or pass in window.customElements
  2. Don't forget about hyphen names can't be started with one i.e. <-foo> but <foo-> is valid (but a little hackey to me). Currently having that discussion with my colleagues devpunks/snuggsi#86
  3. I believe user is extending from a Svelte component. Which seems to be the norm these days

Hope this helps.

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

I think maybe we could close this issue — I'm still not really sold on web components, so I'd be hesitant to add the maintenance burden of having the compiler support them directly. It's already very easy to use custom elements like so:

import Counter from './Counter.html';
import { register } from 'svelte-custom-elements';

register('my-component', Counter, [ 'value' ]);

document.body.innerHTML = '<my-component value="42"></my-component>';

You could even use svelte-custom-elements inside Svelte components:

<my-component value="{{value}}"></my-component>

<script>
  import './my-component'; // contains the first three lines of the example above

  export default {
    data() {
      return { value: 42 };
    }
  };
</script>

from svelte.

snuggs avatar snuggs commented on September 27, 2024

@Rich-Harris far better for Svelte to wrap around a custom element. As it's no different than a canonical dom node at that point from Svelte's perspective. Trust me on this one. You're def digging in the right direction and don't really have to do anyting much with the svelte-custom-element "plugin"(?). I'll be working on updating the specs for Custom Elements soon.

from svelte.

snuggs avatar snuggs commented on September 27, 2024

@Rich-Harris re not buyin' it yet... Agreed on not sold 100% but we're working on that sales pitch ;-)

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

@snuggs There are some tangible benefits to components not being DOM nodes — for example, suppose you have a component like this...

<!-- App.html -->
<Foo bar='{{bar}}' baz='{{baz}}'/>

...which has a computed property qux that's derived from bar and baz. At the moment, if bar and baz change simultaneously...

app.set({
  bar: 1,
  baz: 2
});

...then Foo only needs to recompute qux once, and no DOM manipulation is wasted. Whereas if it's a DOM node instead...

<!-- App.html -->
<my-foo bar='{{bar}}' baz='{{baz}}'/>

...then Svelte has to generate code like this:

foo.bar = state.bar; // invokes a setter, which in turn updates `qux`
foo.baz = state.baz; // invokes a setter again!

Now, one possible solution to that problem is for updates to happen asynchronously. But then you have a programming model that's much harder to reason about, because the DOM isn't necessarily the way you'd expect it to be given your application state.

This is just one small manifestation of the problem, but the point that it illustrates is that the DOM is kind of a bad API for building state-driven applications. They're good for some things, but I just don't think they're a great substance to build complex apps out of. I say that as someone who was very enthusiastic about web components at the beginning!

from svelte.

snuggs avatar snuggs commented on September 27, 2024

@Rich-Harris well... could just do work and trigger a render flag on rAF (requestAnimationFrame). That way if your code runs within 16ms good to go (Which it shouldn't be longer than an order of magnitude less than that). Secondly going off community traction most aren't interested in attribute changes. (Not a valid excuse tho for this use case).

Lastly i feel a touch of a strawman situation as the spec as stated here prohibits any JS operation to the same constraints. I was thinking about on the fly updating observedAttributes however perusing the spec defines this operation being put on the queue stack during defineition and is not a live list. (Perhaps it should be if you have any interest in this feature).

One should be able to use or set attributes on a custom element no different than if an <img> was in a Svelte component. Hence why I said your particular repro is merely an edge case of the DOM that would be there if custom elements didn't exist.

Thanks for the chat. Felt good riding on a 🦄 for a little bit but I think my $0.25 is up my friend. Meaning...what I proposed is great in theory. But Svelte doesn't have to do anything but sit back as it's in good position already.

Below are the implementation operations the platform must abide by. It's the isRunning flag that's why the attribute list can't be live:
capture d ecran 2017-07-10 a 22 47 39

FWIW jQuery has been doing the same for almost a decade now. "Fast" often just has to be "Fast enough". And human perception of "instant" is 30ms. That's why benchmarks are futile. But that's a topic for another day: :trollface: ❤️

// what React proposes for coupling with jQuery testing.

    $('input', this.getDOMNode()).prop({
      indeterminate: true,
      checked: false
    })

No magic trick there. Just plain (sequential) property updates to the HTML attribute. Any library would be in the same boat if needing transactional attribute updates. Luckily have the callback stack that only queues updates. They are processed non-determinantly so could possibly get off 2 operations in 1 on the queue but haven't tested so could be wrong.

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

Going to close this in favour of #797, which is a proposal for outputting custom elements directly from the compiler.

from svelte.

snuggs avatar snuggs commented on September 27, 2024

@Rich-Harris agreed! Wherever I can help let me know. I rock with you.

from svelte.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.