Discussion icon indicating copy to clipboard operation
Discussion copied to clipboard

Better content insertion API

Open yyx990803 opened this issue 9 years ago • 8 comments

Context: https://hacks.mozilla.org/2015/06/the-state-of-web-components/ (See the "Distribution" section)

TL;DR: browser vendors cannot agree on the content distribution API for web components. The current <content select="xxx"> syntax will likely be replaced.

The post describes two possible new APIs: an imperative one and a new declarative one. In Vue this has to do with the internal compilation cycle so we are mostly interested in the new declarative API, the "name slots" proposal from Apple:

Component template:

<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
<div>some shadow content</div>

When using the component:

<x-page>
  <header slot="header">header</header>
  <footer slot="footer">footer</footer>
  <h1>my page title</h1>
  <p>my page content<p>
</x-page>

Rendered result:

<x-page>
  <header slot="header">header</header>
  <h1>my page title</h1>
  <p>my page content<p>
  <footer slot="footer">footer</footer>
  <div>some shadow content</div>
</x-page>

The benefits of this proposal over the current <content> API, is that it is much more explicit (the exposed "slots" essentially become part of the component's interface), and thus makes it easier to compose nested components:

<list-item>
  <avatar slot="left-avatar" src="{{user.avatarUrl}}"></avatar>
  <p slot="primary-text">{{user.name}}</p>
  <p slot="secondary-text">{{user.tagline}}</p>
</list-item>

I'm hoping to ship this in 1.0 - and it's even possible to maintain compat with the current <content> syntax. Discuss!

yyx990803 avatar Jul 21 '15 18:07 yyx990803

This is great, love how explicit it is the communication between the content definition and the actual data

thelinuxlich avatar Jul 21 '15 19:07 thelinuxlich

I don't really have any opinion on this, but when it comes to content insertion, I really like the principle React uses, which is to write all the html to the shadow dom, and on each update to the dom, they just insert/remove the diff between the previous and the last html (which leads to great speed). Having said that, Vue.js is still 100 times better than React, and I suppose implementing something like that is mostly a design/architecture decision that would go pretty deep into the core of the library.

swift1 avatar Jul 21 '15 20:07 swift1

Explicit is better than implicit. And I can not come up with the use case where <content> fits better then named slots.

simplesmiler avatar Jul 22 '15 02:07 simplesmiler

I don't get why the footer slot changes position from component to rendered results. Apart from that: :+1: for the new syntax. I didn't really like the strange css nth-child selection method at all.

nirazul avatar Jul 22 '15 06:07 nirazul

@Nirazul all content without explicit slot name gets distributed into the unnamed default <slot>.

yyx990803 avatar Jul 22 '15 14:07 yyx990803

Ah great, thank you, makes sense to me. Looking forward to the change :)

nirazul avatar Jul 22 '15 14:07 nirazul

What would happen if a slot was blank?

<x-page>
  <header slot="header">header</header>
  <h1>my page title</h1>
  <p>my page content<p>
</x-page>

Would the output then miss the heading?

<x-page>
  <h1>my page title</h1>
  <p>my page content<p>
  <footer slot="footer">footer</footer>
  <div>some shadow content</div>
</x-page>

Mat-Moo avatar Jul 23 '15 12:07 Mat-Moo

It would be nice to be able to access the child component context from slot.

<child>
  <ul>
    <li class="header">Header</li>
    <li class="collection-item" v-for="item in items">
      <slot name="my-item">{{ item }}</slot>
    </li>
  </ul>
</child>

<parent>
  <child>
    <p slot="my-item">{{ item.id }} {{ item.name }}</p> 
  </child>
</parent>

Expected Result:

  <ul>
    <li class="header">Header</li>
    <li class="collection-item" v-for="item in items">
      <p slot="my-item">ID NAME</p> 
    </li>
  </ul>

imaia avatar Mar 10 '16 13:03 imaia