コンテンツにスキップ
トップに戻る
このページについて

Portal-Vue入門

PortalVueとは?

PortalVueは、コンポーネントのテンプレート(またはその一部)をドキュメント内の任意の場所にレンダリングできる2つのコンポーネントのセットです。Vueアプリによって制御される部分の外側にもレンダリングできます!

Vue 3の`Teleport`はどうですか?

良い質問です!ほとんどのシナリオでは、新しい`Teleport`コンポーネントがこのライブラリよりも優れた機能を提供するため、`portal-vue`は必要ない場合があります(つまり、注意点なしで)。

詳細な説明については、こちらをご覧ください。

セットアップ

パッケージのインストール

bash
npm install --save portal-vue@next

# or with yarn
yarn add portal-vue@next

アプリケーションに追加する

js
import PortalVue from 'portal-vue'
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.use(PortalVue)

app.mount('#app')

詳細なインストール手順、追加オプション、CDN経由のインストールについては、ドキュメントのインストールセクションを参照してください。

ブラウザのサポート

このプロジェクトは最新のJavaScript向けに構築されており、Vue自体も最新のブラウザをターゲットにしています。ESモジュールをサポートするすべてのブラウザ、つまり以下のブラウザをサポートしています。

  • Chrome >=61
  • Firefox >=60
  • Safari >=11
  • Edge >=16

何らかの理由で古いブラウザをサポートする必要がある場合は、`node_modules/portal-vue/dist`をbabelでトランスパイルするファイルのリストに含めてください。

Vue CLIは、`transpileDependencies`を使用して、このための専用オプションを提供しています。

js
// vue.config.js
module.exports = {
  transpileDependencies: ['portal-vue']
}

使用方法

例について

以下の例には、ライブデモが含まれています。デモでは、1つのコンポーネント内でコンテンツを移動していますが、実際には`<portal-target>`はアプリ内のどこにでも配置できることに注意してください。

また、例のコードは単一ファイルコンポーネント形式( "`.vue`"ファイル)を使用しています。これについて詳しくない場合は、公式ドキュメントのこちらをご覧ください。

基本

html
<portal to="destination">
  <p>This slot content will be rendered wherever the
    <portal-target> with name 'destination'
    is located.
  </p>
</portal>

<portal-target name="destination">
  <!--
  This component can be located anywhere in your App.
  The slot content of the above portal component will be rendered here.
  -->
</portal-target>

ポータルの有効化/無効化

html
<portal to="destination" :disabled="true">
  <p>
    This slot content will be rendered right here as long as the `disabled` prop
    evaluates to `true`,<br />
    and will be rendered at the defined destination as when it is set to `false`
    (which is the default).
  </p>
</portal>

v-ifを使用した条件付きレンダリング

html
<portal to="destination" v-if="usePortal">
  <ul>
    <li>
      When 'usePortal' evaluates to 'true', the portal's slot content will be
      rendered at the destination.
    </li>
    <li>
      When it evaluates to 'false', the content will be removed from the
      destination
    </li>
  </ul>
</portal>

複数のポータル、1つのターゲット

`PortalTarget`コンポーネントには`multiple`モードがあり、複数の`Portal`コンポーネントからのコンテンツを*同時に*レンダリングできます。

コンテンツがレンダリングされる順序は、`Portal`コンポーネントの`order`プロップで調整できます。

html
<portal to="destination" :order="2">
  <p>some content</p>
</portal>
<portal to="destination" :order="1">
  <p>some other content</p>
</portal>

<div class="some-wrapper">
  <portal-target name="destination" multiple />
</div>

結果

html
<div class="some-wrapper">
  <p>some other content</p>
  <p>some content</p>
</div>

ユースケース

モーダルとオーバーレイの配置

古いブラウザでは、`position: fixed`プロパティを持つ要素が、他の`position`値を持つノードツリーにネストされている場合、`position: fixed`は信頼できません。

しかし、通常、モーダル、ダイアログ、通知、スナックバー、および同様のUI要素などのコンポーネントを固定位置にレンダリングする必要があります。

また、DOMのどこかで要素を互いに重ねてレンダリングしようとすると、z-indexが問題になる可能性があります。

PortalVueを使用すると、モーダル/オーバーレイ/ドロップダウンコンポーネントを、ページの`body`の最後に配置できる`<portal-target>`にレンダリングできるため、スタイリングと配置がはるかに簡単になり、エラーが発生しにくくなります。

これで、コンポーネントを`position: absolute`で配置できます。

html
<body>
  <div id="app" style="position: relative;">
    <div>
      <portal to="notification-outlet">
        <notification style="position: absolute; top: 20px; right: 20px;">
          This overlay can be positioned absolutely very easily.
        </notification>
      </portal>
    </div>
    <!-- rest of your app -->
  </div>

  <portal-target name="notification-outlet"></portal-target>
</body>

動的ウィジェットのレンダリング

Webサイトの小さな部分にVueを使用しているが、ページの反対側の場所に何かをレンダリングしたい場合は、PortalVueが役立ちます。

あなたのユースケースを教えてください!

ここで紹介したもの以外にもユースケースが見つかるはずです。Githubでissueを作成してご連絡ください。ここに掲載させていただきます。