JSS Vue.jsサンプルアプリでのプレースホルダの操作

Version:
日本語翻訳に関する免責事項

このページの翻訳はAIによって自動的に行われました。可能な限り正確な翻訳を心掛けていますが、原文と異なる表現や解釈が含まれる場合があります。正確で公式な情報については、必ず英語の原文をご参照ください。

プレースホルダー は、JSSでビルドされたアプリケーションにおいて重要なコンポーネントです。

メモ

Sitecoreのレイアウト、プレースホルダー、レンダリングの仕組みとJSSがそれらをどのように活用するかの詳細については、Sitecoreデータを使用したJSSアプリでのページ構成 を参照してください。

このトピックでは、JSSを使用してVue.jsアプリケーションを開発するときにプレースホルダーを操作するために使用できる手法について説明します。

基本的なプレースホルダーのテクニック

プレースホルダーを追加する最も基本的で最も一般的な方法は、Placeholderコンポーネントを使用することです。

<template>
  <div>
    <h1>My App</h1>
    <sc-placeholder name="jss-main" :rendering="route" />
  </div>
</template>
<script>
import { Placeholder } from '@sitecore-jss/sitecore-jss-vue';

export default{
  name: 'MyComponent',
  props: {
    route: {
      type: Object
    }
  },
  components: {
    ScPlaceholder: Placeholder,
  }
}
</script>

nameは公開するプレースホルダーのキーであり、renderingは現在のSitecore提供のルート/レイアウト データ、または別のコンポーネント内からプレースホルダーを公開する場合は親コンポーネント データです。

Placeholderコンポーネントは、子コンポーネントのラッパーをレンダリングしません。これはVueのフラグメント技術によるものです。

SitecoreJssPlaceholderPluginのテクニック

この手法を使用すると、プレースホルダーを公開するコンポーネント インスタンスに計算されたプロパティとしてアタッチされたan array of the Vue components in a placeholderを取得できます。

この手法により、従来のSitecore開発ではほぼ不可能だった非常に強力な操作手法が可能になります。

この手法を使用するには、次のように、sitecore-jss-vueパッケージで提供されているSitecoreJssPlaceholderPlugin Vueプラグインをインストールする必要があります。

import { createApp, createSSRApp } from 'vue';
import { SitecoreJssPlaceholderPlugin } from '@sitecore-jss/sitecore-jss-vue';
import componentFactory from './path/to/your/componentFactory.js';

const app = isSSR ? createSSRApp(vueOptions) : createApp(vueOptions);

// The plugin uses a "global" componentFactory, but you can override
// the `componentFactory` at the component level if needed.
app.use(SitecoreJssPlaceholderPlugin, { componentFactory });

コンポーネントでプラグインを使用するには、コンポーネントにwithPlaceholderプロパティを追加します。

<template>
  <div>
    <component v-for="(tab, index) in tabs" :is="tab" :key="`tab${index}`" />
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    rendering: {
      type: Object,
    },
  },
  withPlaceholder: {
    placeholders: 'tabs',
  },
};
</script>

前の例では、SitecoreJssPlaceholderPluginプラグインはbeforeCreateフックにアタッチするミックスインを使用して、コンポーネント定義のwithPlaceholderプロパティを検索します。次に、プラグインはwithPlaceholderプロパティによって提供される値を使用して、renderingプロパティ データ内の指定されたプレースホルダ データ (tabsなど) を検索します。次に、プラグインは、プレースホルダの名前をデフォルトでプロパティ名として使用して、コンポーネントに計算プロパティを作成し、そのプレースホルダのすべてのVueコンポーネントの配列を計算プロパティに割り当てます。これにより、Vue.jsの動的コンポーネント機能を使用して、テンプレート内のプレースホルダーコンポーネントをレンダリングできます。

テンプレート内のコンポーネント配列を反復処理すると、Vueはコンポーネントを出力した場所にレンダリングするか、Placeholderコンポーネントを使用してこれを実現できます。この手法でプレースホルダーの内容を出力すると、プレースホルダーの内容にはラッピング コンポーネントがなく、インラインでレンダリングされます。これは、vue-carouselなどの特定のコンポーネント階層に基づくVueライブラリを使用している場合に非常に便利です。たとえば、次のコード サンプルについて考えてみます。

<carousel>
  <slide>Slide 1 Content</div>
  <slide>Slide 2 Content</div
  <slide>Slide 3 Content</div
</carousel>

前のサンプルでは、コンポーネント階層がcarousel -> slideであることが想定されています。プレースホルダーを使用してslideコンポーネントを追加し、Sitecoreで定義できるようにする場合は、Placeholderコンポーネントsc-placeholderを使用して同じ階層を実現できます。

<carousel>
  <sc-placeholder name="jss-slides" :rendering="rendering" />
</carousel>

コンポーネントの変換

前の例のCarousel->Slide IDのように完全にフラットなコンポーネント階層が必要な場合は、計算されたプロパティが配列であることを利用して、インライン テンプレートを使用してラッパーで子コンポーネントを変換できます。この手法を使用すると、子Sitecoreコンポーネントはラッピングにまったく気付かず、懸念事項を明確に分離するためにコンテンツのみをレンダリングできます。

<template>
  <carousel>
    <template v-for="(slide, index) in $options.computed.slidesPlaceholder">
      <!-- this `v-if` is important, as it helps prevents breakage of the carousel markup when using Sitecore Experience Editor -->
      <component v-if="slide.isxEditorComponent" :is="slide" />

      <!-- wraps _all_ child components in a <slide> component -->
      <slide v-else :key="`slide${index}`">
        <component :is="slide" />
      </slide>
    </template>
  </carousel>
</template>

<script>
export default {
  name: 'ContainerComponent',
  props: {
    rendering: {
      type: Object,
    },
  },
  withPlaceholder: {
    // you can alias the computed prop name for the placeholder or pass an array of placeholders
    placeholders: {
      placeholder: 'slides',
      computedPropName: 'slidesPlaceholder',
    },
  },
};
</script>

スロットAPI

SitecoreJssPlaceholderPluginプラグインが提供する動的計算プロパティの代わりにスロットパターンを好む場合、JSSプレースホルダーにはデフォルトのスロットスコープがあります。<Placeholder>コンポーネントのdefaultスコープスロットを使用すると、動的に計算されたプロパティと同じ方法でプレースホルダーコンテンツのレンダリングを引き継ぐことができます。

次の例は、デフォルトのスコープ付きスロットを使用してcomponents配列をレンダリングする方法を示しています。

<template>
  <sc-placeholder :rendering="rendering" name="jss-main">
    <div v-slot="{components, isEmpty}">
      <!--
        The placeholder is considered "empty" if it contains no assigned presentation components.
        However, if in Experience Editor (EE) mode, the placeholder may still contain EE-generated components.
      -->
      <template v-if="!isEmpty">
        <template v-for="(component, index) in components">
          <!--
            If the component is a presentation component, i.e. not an EE-generated component,
            we may want to wrap it in another component or markup.
          -->
          <div v-if="!component.isxEditorComponent" :key="index">
            <component :is="component" />
          </div>
          <!-- Else the component is an EE-generated component, render it as-is -->
          <component v-else :is="component" :key="index" />
        </template>
      </template>
      <template v-else>
        <!--
          In EE-mode, we still want to render "empty" placeholders so that content authors can
          assign components to them.
        -->
        <component v-for="(component, index) in components" :is="component" :key="index" />
      </template>
    </div>
  </sc-placeholder>
</template>

<script>
import { Placeholder } from '@sitecore-jss/sitecore-jss-vue';

export default {
  name: 'MyComponent',
  props: {
    rendering: {
      type: Object,
    }
  },
  components: {
    ScPlaceholder: Placeholder,
  },
};
</script>

直接プレースホルダーのイントロスペクション

プレースホルダのレンダリングを完全に制御する場合は、コンポーネントではなくプレースホルダのdataにアクセスし、$props.renderingを使用してトラバースして子コンポーネントのデータとフィールドを検出できます。これは、プレースホルダ階層がJavaScriptオブジェクトであるためです。このデータは、任意の方法でレンダリングできます。

これに適した使用例は、タブなどのコンポーネントで、複数の場所 (タブのタイトルとタブの内容) に一部をレンダリングする場合です。例えば:

<template>
  <div class="tabs-container">
    <div class="tabs-heading">
      <ul>
        <li v-for="(tab, index) in rendering.placeholders['jss-tabs']" :key="`tab${index}`">
          <button :class="`${index === activeTabIndex ? 'active' : null}`" v-on:click="activeTabIndex = index">
            <sc-text :field="tab.fields.title" />
          </button>
        </li>
      </ul>
    </div>
    <div class="tabs-content">
      <component :is="activeTab" />
    </div>
  </div>
</template>
<script>
export default {
  name: 'Tabs',
  props: {
    rendering: {
      type: Object,
    }
  },
  data() {
    return {
      activeTabIndex: 0,
    };
  },
  withPlaceholder() {
    return {
      placeholders: [
        {
          placeholder: 'jss-tabs',
          computedPropName: 'tabsPlaceholder',
        },
      ],
    };
  },
  computed: {
    activeTab() {
      return this.$options.computed.tabsPlaceholder && this.$options.computed.tabsPlaceholder[this.activeTabIndex];
    },
  },
}
</script>

複数のプレースホルダー

コンポーネント内の複数のプレースホルダーは、前述の手法のいずれかを使用してレンダリングできます。例えば:

  • 基本的な手法を使用します。

    <template>
      <div>
        <h1>My App</h1>
        <sc-placeholder name="jss-column-1" :rendering="rendering" />
        <sc-placeholder name="jss-column-2" :rendering="rendering" />
      </div>
    </template>
    <script>
    import { Placeholder } from '@sitecore-jss/sitecore-jss-vue';
    export default{
      name: 'MyComponent',
      props: {
        rendering: {
          type: Object
        }
      },
      components: {
        ScPlaceholder: Placeholder,
      }
    }
    </script>
  • SitecoreJssPlaceholderPluginの使用:

    <template>
      <div>
        <div class="col-1">
          <component v-for="(comp, index) in this.$options.computed.phColumn1" :is="comp" :key="`comp${index}`" />
        </div>
        <div class="col-2">
          <component v-for="(comp, index) in this.$options.computed.phColumn2" :is="comp" :key="`comp${index}`" />
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'MyComponent',
      props: {
        rendering: {
          type: Object,
        },
      },
      withPlaceholder: {
        placeholders: [
          {
            placeholder: 'jss-column-1',
            computedPropName: 'phColumn1',
          },
          {
            placeholder: 'jss-column-2',
            computedPropName: 'phColumn2',
          },
        ],
      },
    };
    </script>

プレースホルダーの強化

プレースホルダーコンポーネントは、エクスペリエンスを向上させることができる多くのカスタマイズをサポートしています。

エラーコンポーネント

プレースホルダでレンダリングエラー (つまり、例外) が発生した場合は、プレースホルダの内容の代わりにエラー コンポーネントが表示され、エラーの詳細がコンソールに記録されます。このコンポーネントは、errorComponentプロパティを使用して独自のVueコンポーネントを置き換えることでカスタマイズできます。

欠落しているコンポーネントの処理

プレースホルダーにcomponentFactory不明なレンダリング名が含まれている場合 (たとえば、バックエンド開発者がFooレンダリングを作成してページに追加するが、まだFoo.jsファイルがない場合)、レンダリングはVueコンポーネントのs missingComponentComponentプロパティで定義されたMissingComponentコンポーネントに置き換えられます。デフォルトの実装は単純なメッセージですが、missingComponentComponentプロパティで独自のVueコンポーネントを使用してカスタマイズできます。

非表示のレンダリングの処理

レンダリングがパーソナライゼーションルールによって非表示になっている場合、レンダリングにJSS実装がない場合のエラーメッセージを防ぐために、レンダリングはHiddenRenderingコンポーネントに置き換えられます。独自のコンポーネントを作成し、hiddenRenderingComponentプロパティを使用してプレースホルダに提供できます。

この記事を改善するための提案がある場合は、 お知らせください!