element-plus/website/docs/jp/drawer.md
Xing.Wu 458d56e41e
feat(docs): Drawer code for composition (#2165)
* feat(docs): Drawer code for composition

* feat(docs): Drawer code for ElMessageBox

Co-authored-by: 无星 <32910694@qq.com>
2021-06-10 00:17:23 +08:00

14 KiB

Drawer

例えば、巨大なフォームを持っていたり、terms & conditions のようなものを表示するためのスペースが必要な場合、DrawerDialog とほぼ同じ API を持っていますが、ユーザーエクスペリエンスが異なります。

:::tip

Translation needed

Since v-model is natively supported for all components, visible.sync has been deprecated, use v-model="visibilityBinding" to control the visibility of the current drawer. :::

基本的な使い方

一時的にDrawerを多方向から呼び出す

:::demo Drawer には Dialog のように model-value を設定して Drawer 自体の表示を制御する必要があります。title は名前付きスロットで、タイトルは title という属性を使って設定することもできます。デフォルトでは、Drawerはブラウザウィンドウの30%の大きさの右隅から左隅に向かって展開します。このデフォルトの動作を変更するには、directionsize 属性を設定します。このショーケースでは before-close API の使い方も紹介しました。さらに詳しく知りたい場合は Attributesセクションもご覧ください。

<el-radio-group v-model="direction">
  <el-radio label="ltr">left to right</el-radio>
  <el-radio label="rtl">right to left</el-radio>
  <el-radio label="ttb">top to bottom</el-radio>
  <el-radio label="btt">bottom to top</el-radio>
</el-radio-group>

<el-button @click="drawer = true" type="primary" style="margin-left: 16px;">
  open
</el-button>

<el-drawer
  title="I am the title"
  v-model="drawer"
  :direction="direction"
  :before-close="handleClose">
  <span>Hi, there!</span>
</el-drawer>

<script>
  export default {
    data() {
      return {
        drawer: false,
        direction: 'rtl',
      };
    },
    methods: {
      handleClose(done) {
        this.$confirm('Are you sure you want to close this?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      }
    }
  };
</script>
<!--
<setup>

  import { defineComponent, ref } from 'vue';
  import { ElMessageBox } from 'element-plus';

  export default defineComponent({
    setup() {
      
      const drawer = ref(false);
      const direction = ref('rtl');
      const handleClose = (done) => {
        ElMessageBox
          .confirm('Are you sure you want to close this?')
          .then((_) => {
            done();
          })
          .catch((_) => {});
      };
      return {
        drawer,
        direction,
        handleClose,
      };
    },
  });

</setup>
-->

:::

タイトルなし

タイトルが不要になったら、引き出しからタイトルを外すことができます。

:::demo withHeader属性を**false**に設定すると、タイトルを削除することができます。アクセスしやすいようにしたい場合は、title`属性を設定してください。

<el-button @click="drawer = true" type="primary" style="margin-left: 16px;">
  open
</el-button>

<el-drawer
  title="I am the title"
  v-model="drawer"
  :with-header="false">
  <span>Hi there!</span>
</el-drawer>

<script>
  export default {
    data() {
      return {
        drawer: false,
      };
    }
  };
</script>
<!--
<setup>

  import { defineComponent, ref } from 'vue';

  export default defineComponent({
    setup() {
      return {
        drawer: ref(false),
      };
    },
  });

</setup>
-->

:::

カスタマイズコンテンツ

ダイアログと同様に、Drawerはあなたが望むように多くの多様なインタラクションを行うことができる。

:::demo

<el-button type="text" @click="table = true">Open Drawer with nested table</el-button>
<el-button type="text" @click="dialog = true">Open Drawer with nested form</el-button>
<el-drawer
  title="I have a nested table inside!"
  v-model="table"
  direction="rtl"
  size="50%">
   <el-table :data="gridData">
      <el-table-column property="date" label="Date" width="150"></el-table-column>
      <el-table-column property="name" label="Name" width="200"></el-table-column>
      <el-table-column property="address" label="Address"></el-table-column>
    </el-table>
</el-drawer>

<el-drawer
  title="I have a nested form inside!"
  :before-close="handleClose"
  v-model="dialog"
  direction="ltr"
  custom-class="demo-drawer"
  ref="drawer"
  >
  <div class="demo-drawer__content">
    <el-form :model="form">
      <el-form-item label="Name" :label-width="formLabelWidth">
        <el-input v-model="form.name" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="Area" :label-width="formLabelWidth">
        <el-select v-model="form.region" placeholder="Please select activity area">
          <el-option label="Area1" value="shanghai"></el-option>
          <el-option label="Area2" value="beijing"></el-option>
        </el-select>
      </el-form-item>
    </el-form>
    <div class="demo-drawer__footer">
      <el-button @click="cancelForm">Cancel</el-button>
      <el-button type="primary" @click="$refs.drawer.closeDrawer()" :loading="loading">{{ loading ? 'Submitting ...' : 'Submit' }}</el-button>
    </div>
  </div>
</el-drawer>

<script>
export default {
  data() {
    return {
      table: false,
      dialog: false,
      loading: false,
      gridData: [{
        date: '2016-05-02',
        name: 'Peter Parker',
        address: 'Queens, New York City'
      }, {
        date: '2016-05-04',
        name: 'Peter Parker',
        address: 'Queens, New York City'
      }, {
        date: '2016-05-01',
        name: 'Peter Parker',
        address: 'Queens, New York City'
      }, {
        date: '2016-05-03',
        name: 'Peter Parker',
        address: 'Queens, New York City'
      }],
      form: {
        name: '',
        region: '',
        date1: '',
        date2: '',
        delivery: false,
        type: [],
        resource: '',
        desc: ''
      },
      formLabelWidth: '80px',
      timer: null,
    };
  },
  methods: {
    handleClose(done) {
      if (this.loading) {
        return;
      }
      this.$confirm('Do you want to submit?')
        .then(_ => {
          this.loading = true;
          this.timer = setTimeout(() => {
            done();
            // animation takes time
            setTimeout(() => {
              this.loading = false;
            }, 400);
          }, 2000);
        })
        .catch(_ => {});
    },
    cancelForm() {
      this.loading = false;
      this.dialog = false;
      clearTimeout(this.timer);
    }
  }
}
</script>
<!--
<setup>

import {defineComponent, reactive, toRefs } from 'vue'; 
import { ElMessageBox } from 'element-plus'; 

  export default defineComponent({
    setup() {
      
      const state = reactive({
        table: false,
        dialog: false,
        loading: false,
        gridData: [
          {
            date: '2016-05-02',
            name: 'Peter Parker',
            address: 'Queens, New York City',
          },
          {
            date: '2016-05-04',
            name: 'Peter Parker',
            address: 'Queens, New York City',
          },
          {
            date: '2016-05-01',
            name: 'Peter Parker',
            address: 'Queens, New York City',
          },
          {
            date: '2016-05-03',
            name: 'Peter Parker',
            address: 'Queens, New York City',
          },
        ],
        form: {
          name: '',
          region: '',
          date1: '',
          date2: '',
          delivery: false,
          type: [],
          resource: '',
          desc: '',
        },
        formLabelWidth: '80px',
        timer: null,
      });

      const handleClose = (done) => {
        if (state.loading) {
          return;
        }
        ElMessageBox
          .confirm('Do you want to submit?')
          .then((_) => {
            state.loading = true;
            state.timer = setTimeout(() => {
              done();
              // 动画关闭需要一定的时间
              setTimeout(() => {
                state.loading = false;
              }, 400);
            }, 2000);
          })
          .catch((_) => {});
      };

      const cancelForm = () => {
        state.loading = false;
        state.dialog = false;
        clearTimeout(state.timer);
      };

      return {
        ...toRefs(state),
        handleClose,
        cancelForm,
      };
    },
  });

</setup>
-->

:::

入れ子にしたDrawer

Dialog のように Drawer を複数のレイヤーで構成することもできる。 :::demo 異なるレイヤーに複数のDrawerが必要な場合は、append-to-body 属性を true に設定しなければなりません。


<el-button @click="drawer = true" type="primary" style="margin-left: 16px;">
  open
</el-button>

<el-drawer
  title="I'm outer Drawer"
  v-model="drawer"
  size="50%">
  <div>
   <el-button @click="innerDrawer = true">Click me!</el-button>
   <el-drawer
     title="I'm inner Drawer"
     :append-to-body="true"
     :before-close="handleClose"
     v-model="innerDrawer">
     <p>_(:зゝ∠)_</p>
   </el-drawer>
  </div>
</el-drawer>

<script>
  export default {
    data() {
      return {
        drawer: false,
        innerDrawer: false,
      };
    },
    methods: {
      handleClose(done) {
        this.$confirm('You still have unsaved data, proceed?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      }
    }
  };
</script>
<!--
<setup>

  import { defineComponent, ref } from 'vue';
  import { ElMessageBox } from 'element-plus';

  export default defineComponent({
    setup() {
      
      const drawer = ref(false);
      const innerDrawer = ref(false);
      const handleClose = (done) => {
        ElMessageBox
          .confirm('You still have unsaved data, proceed?')
          .then((_) => {
            done();
          })
          .catch((_) => {});
      };
      return {
        drawer,
        innerDrawer,
        handleClose,
      };
    },
  });

</setup>
-->

:::

:::tip

Drawer内のコンテンツは遅延レンダリングされるべきであり、これはDrawer内のコンテンツが初期レンダリングのパフォーマンスに影響を与えないことを意味します。したがって、DOM の操作は ref を介して行うか、open イベントが発生した後に行うべきである。

:::

:::tip

Drawerは destroyOnClose というAPIを提供しています。これはフラグ変数であり、Drawerが閉じられた後にDrawer内の子コンテンツを破棄することを示します。Drawerが開くたびに mounted ライフサイクルを呼び出す必要がある場合にこのAPIを利用することができます。

:::

Drawer属性

Parameter Description Type Acceptable Values Defaults
model-value / v-model Drawerを表示する場合は、 boolean false
append-to-body DrawerがDocumentBody要素に挿入されている場合のコントロールは、ネストされたDrawerはこのパラメータをtrueに割り当てなければなりません。 boolean false
before-close 設定されている場合は、終了処理を停止します。 function(done), done is function type that accepts a boolean as parameter, calling done with true or without parameter will abort the close procedure
close-on-press-escape ESC を押してDrawerを閉じることができるかどうかを示す。 boolean true
custom-class Drawerの追加クラス名 string
destroy-on-close Drawerが閉じた後にChildrenが破壊されるべきかどうかを示す boolean - false
modal シャドウイングレイヤーを表示するか boolean true
direction Drawerの開き方向 Direction rtl / ltr / ttb / btt rtl
show-close Drawerの右上に閉じるボタンを表示するようにした boolean true
size Drawerのサイズ, ドローワが水平モードの場合は幅プロパティ, そうでない場合は高さプロパティ, サイズが number 型の場合はピクセル単位でサイズを記述します; サイズが string 型の場合は x% 記法を用います, それ以外の場合はピクセル単位で解釈されます number / string - '30%'
title Drawerのタイトルは、スロットの名前を指定して設定することもできます。 string
withHeader デフォルトは true で、withHeader が false に設定されている場合は title attributetitle slot の両方が動作しません。 boolean - true
modal-class シャドウレイヤーの追加クラス名 string

Drawerスロット

Name Description
Drawerの内容
title Drawerタイトルセクション

Drawerメソッド

Name Description
handleClose Drawerを閉じるには、このメソッドは before-close を呼び出す。

Drawerイベント

Event Name Description Parameter
open Drawerのオープニングアニメーションが始まる前にトリガーされます。
opened Drawerのオープニングアニメーションが終わった後にトリガーされます。
close Drawerのクロージングアニメーションが始まる前にトリガーされます。
closed Drawerのクロージングアニメーションが終わった後にトリガーされます。