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

Proposal: Component property and Slot feature (aka, props / v-bind / <Slot>) #104

Open
mantaroh opened this issue Feb 16, 2023 · 6 comments
Labels
documentation Improvements or additions to documentation

Comments

@mantaroh
Copy link
Collaborator

mantaroh commented Feb 16, 2023

What is this?

#103 describe conditional rendering feature. This conditional feature need the data which passing from parent component of html. This mean we need to pass the data into child component.

Furthermore, we had better to pass the whole of HTML Node into child component. This feature is known as Slot feature.

This features inspired from Vue / React.

Use case

There are many use case this feature.

1. props with v-if

Almost props usage is this case. Conditional Rendering use props for condition.

Parent component:

<sample-component v-bind:target="top"></sample-component>

Child component:

<div v-if="props.target==='top'">
 <p>Top page header</p>
</div>
<div v-else>
 <p>Other page header</p>
</div>

Rendering Result:

<div>
  <p>Top page header</p>
</div>

2. display props value

Sometime pass the user information into component, and display this value.

Parent component:

<sample-component v-bind:name="userX" v-bind:age="10"></sample-component>

Child component:

<div>
  <p>{%= props.name %}</p>
  <p>{%= props.age %}<p>
</div>

Render Result:

<div>
  <p>userX</p>
  <p>10</p>
</div>

In this case, we recommend to use Slot feature

3. dissplay Slot value

Slot allow the pass the whole child element into components.

Parnet component:

<div>
  <sample-component>
   Here is slot description
  </sample-component>
</div>

Child component:

<div>
  <slot></slot>
</div>

Render Result:

<div>
  <div>
    Here is slot description
  </div>
</div>

Consideration

  • Parse order

spear-cli parse the following order:

  1. search components and parsing it
  2. search html/htm/spear and parsing it
  3. inject component into target page.
  4. inject cms data into target page. (Convert html element which has cms-xxx attr)
  5. bundle (copy build result into dist)

We consider the following case:
(blog contents has target-template-string which specify the field type name.)

index.html

<div cms-loop cms-content-type="blog">
  <!-- We expect convert to v-bind:template=description before props convert -->
  <sample-component v-bind:template="{%= blog_target-template-string %}"></sample-component>
</div>

sample-component.spear

<div cms-item cms-content-type="blog" cms-content="c-xxxxxxxx">
  <h1>{%= "blog_" + props.template %}</h1>
</div>

If we start props convert step before inject cms content, an above convert might be failed since index.html pass the {%=blog_target-template-string %} into sample-component via props.template.
So we need to props convert first step.


これはなに?

#103 は条件付きレンダリングについて記載しています。この条件付きレンダリングでは、データをHTMLの親コンポーネントから渡す必要があります。つまり、データを親から子へ伝搬する必要がります。

さらにHTMLノードすべての要素を子コンポーネントへ伝える必要もあり、それは Slot 機能として知られています。

これらの機能は Vue/React からヒントを得ています。

ユースケース

これらの機能はいくつかのユースケースがあります。

1. v-if を利用するための props

props を利用するほとんどのケースがこれに該当します。条件付きレンダリングでは条件として props を利用します。

親コンポーネント:

<sample-component v-bind:target="top"></sample-component>

子コンポーネント

<div v-if="props.target==='top'">
 <p>Top page header</p>
</div>
<div v-else>
 <p>Other page header</p>
</div>

レンダリング結果

<div>
  <p>Top page header</p>
</div>

2. props の値を表示する

ユーザー情報を子コンポーネントへ渡して、それを表示することに利用します。

親コンポーネント:

<sample-component v-bind:name="userX" v-bind:age="10"></sample-component>

子コンポーネント:

<div>
  <p>{%= props.name %}</p>
  <p>{%= props.age %}<p>
</div>

レンダリング結果:

<div>
  <p>userX</p>
  <p>10</p>
</div>

このケースでは、Slot 機能を利用したほうが良いです。

3.Slot の値を表示する

Slotは小要素すべてをコンポーネントへ渡す方法です。

親コンポーネント:

<div>
  <sample-component>
   Here is slot description
  </sample-component>
</div>

子コンポーネント:

<div>
  <slot></slot>
</div>

レンダリング結果:

<div>
  <div>
    Here is slot description
  </div>
</div>

考慮すべき点

解析順番

spear-cli 解析は以下の順番で行われます。

  1. コンポーネントの探索・解析
  2. html / htm / spear ファイルの探索・解析
  3. ターゲットのページにコンポーネントを注入
  4. ターゲットのページにCMSコンテンツを注入
  5. バンドル(dist ディレクトリへコピー)

props を導入するにあたって、以下のケースでは注意が必要です。
(blog コンテンツは target-template-string という表示するフィールド名を保持するフィールドを持っています。)

index.html

<div cms-loop cms-content-type="blog">
  <!-- props の注入前に v-bind:template=description に変換されることを期待しています。 -->
  <sample-component v-bind:template="{%= blog_target-template-string %}"></sample-component>
</div>

sample-component.spear

<div cms-item cms-content-type="blog" cms-content="c-xxxxxxxx">
  <h1>{%= "blog_" + props.template %}</h1>
</div>

もし、CMSコンテンツ注入前に props の注入が行われた場合、上記例は {%= blog_target-template-string %} を props.template` 経由で sample-component へ渡してしまうため、期待した結果になりません。

@qst-exe
Copy link
Contributor

qst-exe commented Feb 16, 2023

Can we use Named Slots too?
https://vuejs.org//guide/components/slots.html#named-slots

@oxo-yuta
Copy link

oxo-yuta commented Feb 16, 2023

The v- prefix will conflict with future cases such as combining Spear and Vue, so I thought it best to write it in a uniquely simple way.

@oxo-yuta
Copy link

If we start props convert step before inject cms content, an above convert might be failed since index.html pass the {%=blog_target-template-string %} into sample-component via props.template.
So we need to props convert first step.

I think we should inject CMS contents before props convert step 🤔
If we could change the layout and display method with values on the content side, we would be able to create a more flexible site.

@mantaroh
Copy link
Collaborator Author

@qst-exe

Can we use Named Slots too?

Yep. That's true.
We should have name attribute as well.

@mantaroh
Copy link
Collaborator Author

mantaroh commented Mar 9, 2023

I implemented the slot feature in #131. We need a document for this feature.

@mantaroh mantaroh added the documentation Improvements or additions to documentation label Mar 9, 2023
@mantaroh
Copy link
Collaborator Author

#114 related work

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

No branches or pull requests

3 participants