# Modal 对话框
一般为模态弹出框的形式,用于承载信息详情或操作。
# 💡 常见问题
- 1.为什么在多重嵌套 
Modal时,会出现某些Modal无法显示? 
如果需要在页面上同时显示多个 Modal,可以将它们平级放置。对于确实需要嵌套 Modal 的场景,我们提供了append-to-bod 属性。将内层 Modal 的该属性设置为 true,它就会插入至 body 元素上,从而保证内外层 Modal 和遮罩层级关系的正确。
# 代码演示
基础用法
before-close-modal,before-close-button,before-close分别在点击遮罩层,关闭图标和全部时起效
查看代码
<template>
  <w-button type="text" @click="visible = !visible">点击打开Modal</w-button>
  <w-modal
    :visible.sync="visible"
    :title="title"
    :before-close-modal="handleCloseModal"
    subtitle="副标题"
    width="30%"
  >
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <w-button @click="visible = false">取消</w-button>
      <w-button
        style="margin-left: 16px"
        type="primary"
        @click="visible = false"
      >
        确定
      </w-button>
    </span>
  </w-modal>
</template>
<script>
  export default {
    data() {
      return {
        visible: false,
      }
    },
    methods: {
      handleCloseModal(done) {
        this.$Confirm('确认关闭Modal?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      }
    }
  }
</script>可缩放 👉 V2.4.9
通过配置 resize 实现可缩放对话框。触发角分别是:左侧、右侧、底侧、左下角、右下角。
查看代码
<template>
  <w-button type="text" @click="visible = !visible">点击打开Modal</w-button>
  <w-modal
    :visible.sync="visible"
    :title="title"
    :close-on-click-modal="false"
        resize
        @before-resize-change="handleBeforeResizeChange"
        @after-resize-change="hanldeAfterResizeChange"
    width="30%"
  >
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <w-button @click="visible = false">取消</w-button>
      <w-button
        style="margin-left: 16px"
        type="primary"
        @click="visible = false"
      >
        确定
      </w-button>
    </span>
  </w-modal>
</template>
<script>
  export default {
    data() {
      return {
        visible: false,
      }
    },
    methods: {
      handleBeforeResizeChange(val) {
        console.log(val)
      },
      hanldeAfterResizeChange(val) {
        console.log(val)
      }
    }
  }
</script>全屏的两种使用 👉 V2.4.8
通过设置 fullscreen 默认打开就是全屏;通过设置 show-fullscreen 开启全屏按钮。
查看代码
<template>
          <w-button type="text" @click="visible1 = !visible1">
        默认全屏 Modal
      </w-button>
      <w-button type="text" @click="visible2 = !visible2">
        配置全屏按钮 Modal
      </w-button>
      <w-modal
        :visible.sync="visible1"
        :title="title"
        fullscreen
        destroyOnClose
        subtitle="副标题"
        width="30%"
      >
        <span>这是一段信息</span>
        <span slot="footer" class="dialog-footer">
          <w-button @click="visible1 = false">取消</w-button>
          <w-button
            style="margin-left: 16px"
            type="primary"
            @click="visible1 = false"
          >
            确定
          </w-button>
        </span>
      </w-modal>
      <w-modal
        :visible.sync="visible2"
        :title="title"
        show-fullscreen
        destroyOnClose
        :max-height="maxHeight"
        @change-fullscreen="handleChangeFullscreen"
        subtitle="副标题"
        width="30%"
      >
        <span>这是一段信息</span>
        <span slot="footer" class="dialog-footer">
          <w-button @click="visible2 = false">取消</w-button>
          <w-button
            style="margin-left: 16px"
            type="primary"
            @click="visible2 = false"
          >
            确定
          </w-button>
        </span>
      </w-modal>
</template>
<script>
  export default {
    data() {
      return {
        visible1: false,
        maxHeight: null,
        visible2: false,
      }
    },
    methods: {
      handleChangeFullscreen(val) {
        this.maxHeight = val ? '100vh' : null
      }
    }
  }
</script>超出滚动 👉 V2.2.14
设置 :max-height='200' 最大高度,超出时内容区域滚动
查看代码
<template>
  <w-button type="text" @click="visible = !visible">点击打开Modal</w-button>
  <w-modal
        :visible.sync="visible"
        :title="title"
        destroyOnClose
        width="30%"
        :max-height="300"
        class="modal-overflow-demo"
      >
        <div style="line-height: 20px; margin-bottom: 16px;">
          在中国互联网科技趋势引领下,患者就医体验愈发便捷高效。鉴于目前患者更加注重服务质量和体验,各方持续对这一领域进行重大战略投入。海外调查显示,49%的医疗供应商高管表示在未来五年内将改善患者体验作为组织的三大要务之一,部分已或将设立首席体验官,计划通过改善患者体验,在市场上脱颖而出。
        </div>
        <div style="line-height: 20px;">
          带着体验至上的目标,我们经过了大量的项目实践和总结,逐渐打磨形成一套符合医疗行业特性的标准化解决方案。通过将医疗体系中工作量巨大且复杂的功能进行抽象整合,得到一些稳定且高可复用的内容。WinDesign
          遵循协同、便捷、高效的设计理念,致力于通过标准化的基础组件以及后续模块化的业务组件来最大化的降低生产成本,提高沟通效率,提升用户体验。
        </div>
        <span slot="footer" class="dialog-footer">
          <w-button @click="visible = false">取消</w-button>
          <w-button
            style="margin-left: 16px"
            type="primary"
            @click="visible = false"
          >
            确定
          </w-button>
        </span>
      </w-modal>
</template>
<script>
  export default {
    data() {
      return {
        visible: false,
      }
    },
    methods: {
    }
  }
</script>WARNING
在开启拖拽时,如果内容区域添加了如 Select 选择器,请在 Select 选择器上配置 draggable-modal 属性,为了在拖拽的过程中关闭已经打开的 Select 选择器面板。
可拖拽对话框 👉 V2.4.6
试着拖动一下 header 部分吧!设置 draggable 属性为 true 以做到拖拽
查看代码
<template>
  <w-button type="text" @click="visible = !visible">点击打开Modal</w-button>
  <w-modal
    :visible.sync="visible"
    :title="title"
    draggable
    width="30%"
  >
      <w-select
        :silentBlur="false"
        @blur="test"
        style="width: 100%"
        v-model="value"
        placeholder="请选择"
        :draggable-modal="true"
        clearable
      >
        <w-option
          v-for="item in options"
          :key="item.value"
          :label="item.name"
          :value="item.value"
          :disabled="item.disabled"
        ></w-option>
      </w-select>
    <span slot="footer" class="dialog-footer">
      <w-button @click="visible = false">取消</w-button>
      <w-button
        style="margin-left: 16px"
        type="primary"
        @click="visible = false"
      >
        确定
      </w-button>
    </span>
  </w-modal>
</template>
<script>
  export default {
    data() {
      return {
        visible: false,
        options: [
          {
            value: '1',
            name: '炔诺酮片',
            size: '625微克/片',
            count: '10',
            unit: '片',
            price: '10.00',
            total: '100.00'
          },
          {
            value: '2',
            name: '扶达胶囊',
            size: '100毫克/粒',
            count: '5',
            unit: '粒',
            price: '12.00',
            total: '60.00'
          },
          {
            value: '3',
            name: '百士欣胶囊',
            size: '10毫克/粒',
            count: '2',
            unit: '粒',
            price: '22.50',
            total: '45.00',
            disabled: true
          },
          {
            value: '4',
            name: '别嘌醇片',
            size: '100毫克/片',
            count: '10',
            unit: '片',
            price: '14.50',
            total: '145.00'
          },
          {
            value: '5',
            name: '复方维生素注射液',
            size: '2毫升/支',
            count: '10',
            unit: '支',
            price: '12.73',
            total: '127.30'
          }
        ],
        value: '1',
      }
    },
  }
</script>关闭时销毁
当出现性能问题时,可以启用此功能。需要注意的是,当这个属性被启用时,在 transition.beforeEnter 事件卸载前,除了 header (可选) 与 footer (可选),Modal 内不会有任何其它的 DOM 节点存在。
查看代码
<template>
  <w-button type="text" @click="visible = !visible">点击打开Modal</w-button>
  <w-modal
    :visible.sync="visible"
    :title="title"
    destroyOnClose
    width="30%"
  >
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <w-button @click="visible = false">取消</w-button>
      <w-button
        style="margin-left: 16px"
        type="primary"
        @click="visible = false"
      >
        确定
      </w-button>
    </span>
  </w-modal>
</template>
<script>
  export default {
    data() {
      return {
        visible: false,
      }
    },
  }
</script>确认类对话框
正常情况下,我们不建议使用嵌套的 Modal,如果需要在页面上同时显示多个 Modal,可以将它们平级放置。对于确实需要嵌套 Modal 的场景,我们提供了append-to-body属性。将内层 Modal 的该属性设置为 true,它就会插入至 body 元素上,从而保证内外层 Modal 和遮罩层级关系的正确。
查看代码
<template>
  <section class="pagination-demo">
      description="正常情况下,我们不建议使用嵌套的 Modal,如果需要在页面上同时显示多个 Modal,可以将它们平级放置。对于确实需要嵌套 Modal 的场景,我们提供了append-to-body属性。将内层 Modal 的该属性设置为 true,它就会插入至 body 元素上,从而保证内外层 Modal 和遮罩层级关系的正确。">
      <w-button type='text'
                @click="outerVisible = true">点击打开外层 Modal</w-button>
      <w-modal  :visible.sync="outerVisible"
                width="60%"
                color
                title="外层 Modal"
                >
        <w-modal
          width="30%"
          title="内层 Modal"
          :visible.sync="innerVisible"
          append-to-body>
        </w-modal>
        <span slot="footer" class="dialog-footer">
            <w-button @click="outerVisible = false">取消</w-button>
            <w-button style="margin-left: 16px;" type="primary" @click="innerVisible = true">点击打开内层 Modal</w-button>
          </span>
      </w-modal>
  </section>
</template>
彩色样式
需要使用 color 属性可以为Modal添加色彩。
查看代码
<template>
  <w-button @click="visible = !visible">彩色样式的Modal</w-button>
  <w-modal  :visible.sync="visible"
    color
    :title="title"
    width="30%">
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
    <w-button @click="visible = false">取消</w-button>
    <w-button type="primary" @click="visible = false">确定</w-button>
    </span>
  </w-modal>
</template>异步关闭
点击确定,查看异步关闭效果。
查看代码
<template>
  <w-button @click="visible = !visible">点击打开 Modal</w-button>
  <w-modal  :visible.sync="visible"
    :title="title"
    width="30%">
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <w-button :icon="loadingIcon" @click="showModal()">取消</w-button>
      <w-button type="primary" :icon="loadingIcon" @click="showModal()">确定</w-button>
    </span>
  </w-modal>
</template>
<script>
export default {
  data () {
    return {
      visible: false,
      isIcon: '',
      title:'异步关闭',
      showClose: false
    }
  },
  computed:{
    loadingIcon:function(){
      return this.isIcon ? 'w-icon-loading' : ''
    }
  },
  methods: {
    showModal (val) {
      this.isIcon = true
      let _this= this
      setTimeout(function()  {
        _this.visible = false
        _this.isIcon = false
      }, 1500)
    }
  }
}
</script>自定义内容
Modal 组件的内容可以是任意的,甚至可以是表格或表单,下面是应用了 tree 组件的样例。
查看代码
<template>
  <w-button @click="visible = !visible">打开嵌套树的Modal</w-button>
  <w-modal :visible.sync="visible"
    :title="title"
    width="30%">
    <w-tree :data="data" :props="defaultProps"></w-tree>
    <span slot="footer" class="dialog-footer">
      <w-button @click="visible = false">取消</w-button>
      <w-button type="primary" @click="visible = false">确定</w-button>
    </span>
  </w-modal>
</template>
<script>
  export default {
    data () {
      return {
         data: [
          {
            label: '一级 1',
            children: [{
              label: '二级 1-1',
              children: [{
                label: '三级 1-1-1'
              }]
            }]
          }, {
            label: '一级 2',
            children: [{
              label: '二级 2-1',
              children: [{
                label: '三级 2-1-1'
              }]
            }, {
              label: '二级 2-2',
              children: [{
                label: '三级 2-2-1'
              }]
            }]
          }, {
            label: '一级 3',
            children: [{
              label: '二级 3-1',
              children: [{
                label: '三级 3-1-1'
              }]
            }, {
              label: '二级 3-2',
              children: [{
                label: '三级 3-2-1'
              }]
            }]
          }],
        defaultProps: {
          children: 'children',
          label: 'label'
        }
      }
    }
    }
</script>居中布局
标题和底部可水平居中。
查看代码
<template>
  <w-button @click="visible = !visible">点击打开Modal</w-button>
  <w-modal  :visible.sync="visible"
    center
    :title="title"
    width="30%">
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <w-button @click="visible = false">取消</w-button>
      <w-button type="primary" @click="visible = false">确定</w-button>
    </span>
  </w-modal>
</template># API
# Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | Version | 
|---|---|---|---|---|---|
| destroy-on-close | 当关闭 Modal 时,销毁其中的元素 | Boolean | — | false | v2.0.9 | 
| draggable | 为 Modal 启用可拖拽功能 | Boolean | — | false | v2.0.9 | 
| append-to-body | Modal 自身是否插入至 body 元素上。嵌套的 Modal 必须指定该属性并赋值为 true | Boolean | — | false | |
| before-close | 关闭前的回调,会暂停 Modal 的关闭 | Function(done),done 用于关闭 Modal | — | — | |
| before-close-modal | 点击遮罩层关闭前的回调,会暂停 Modal 的关闭,使用 before-close,此方法失效 | Function(done),done 用于关闭 Modal | — | — | |
| before-close-button | 点击关闭 icon 关闭前的回调,会暂停 Modal 的关闭,使用 before-close,此方法失效 | Function(done),done 用于关闭 Modal | — | — | |
| center | 是否对头部和底部采用居中布局 | Boolean | — | false | |
| custom-class | Modal 的自定义类名 | String | — | — | |
| close-on-click-modal | 是否可以通过点击遮罩 关闭 Modal | Boolean | — | true | |
| close-on-press-escape | 是否可以通过按下 ESC 关闭 Modal | Boolean | — | true | |
| fullscreen | 是否为全屏 Modal | Boolean | — | false | |
| lock-scroll | 是否在 Modal 出现时将 body 滚动锁定 | Boolean | — | true | |
| modal | 是否显示遮罩, 默认显示 | Boolean | — | true | |
| modal-append-to-body | 遮罩层是否插入至 body 元素上,若为 false,则遮罩层会插入至 Modal 的父元素上 | Boolean | — | true | |
| title | Modal 的标题,也可通过具名 slot (见下表)传入 | String | — | — | |
| top | Modal CSS 中的 margin-top 值 | String | — | 20vh | |
| show-close | 是否显示关闭按钮 | Boolean | — | true | |
| show-fullscreen | 是否显示全屏按钮 | Boolean | — | false | V2.4.8 | 
| subtitle | 副标题 | String | — | — | v2.0.0 | 
| visible | 是否显示 Modal,支持 .sync 修饰符 | Boolean | — | true | |
| width | Modal 的宽度 | String | — | 50% | |
| max-height | Modal 的最大高度 | Number / String | — | V2.2.14、V2.4.9 | |
| resize | 缩放 | Boolean | — | false | V2.4.9 | 
| resize-min-width | 缩放最小宽度 | Number | — | 300 | V2.4.9 | 
| resize-min-height | 缩放最小高度 | Number | — | 150 | V2.4.9 | 
# Slot
| 名称 | 说明 | Version | 
|---|---|---|
| — | Modal 的内容 | |
| footer | Modal 按钮操作区的内容 | |
| title | Modal 标题区的内容 | 
# Events
| 事件名称 | 说明 | 回调参数 | Version | 
|---|---|---|---|
| close | Modal 关闭的回调 | — | |
| closed | Modal 关闭动画结束时的回调 | — | |
| open | Modal 打开的回调 | — | |
| opened | Modal 打开动画结束时的回调 | — |