Dialog

ElementUI提供的 el-dialog,在使用上经常造成混淆,它主要有两个概念需要理解:visible、@close。

给出几个例子,来看看结果会如何

例子1

下面例子中,关闭弹框的叉除,弹框不会被关闭。

  1. // message-board.vue
  2. <el-dialog :visible="visible"/>

因为,弹框的显示是靠visible属性,el-dialog在点击叉除时候,只会做下面的调用,要能关闭弹框,参考例子2.

  1. // el-dialog.vue
  2. this.$emit('update:visible', false);
  3. this.$emit('close')

例子2

下面例子中,关闭弹框的叉除,弹框会被关闭。

  1. // message-board.vue
  2. <el-dialog :visible.sync="visible"/>

因为,子组件的'update:visible' 和 父组件的visible.sync 配合使用,能将visible的值同步给父组件。

另外一种做法,通过手动来设置visible当然也可以:

  1. // message-board.vue
  2. <el-dialog :visible="visible" @close="visible=false"/>

例子3

我们在多构造一层引用,让情况更复杂一些。

下例中,关闭弹框同样不会有任何反应:

  1. // header.vue
  2. <div class="header>
  3. <message-board :visible="visible" />
  4. <button @click="visible=true">open</butotn>
  5. </div>
  6. // message-board.vue
  7. <div class="message-board">
  8. <el-dialog :visible="visible"/>
  9. </div>

下面的例子开始有意思,弹框可以被正常关闭,但是遇到了预期之外的行为:

  • 通过浏览器插件,可以看到 message-board.vue中visible为false,header.vue中值为true
  • 同时浏览器发出了警告,提示不能直接修改visible
  • 再次通过点击header.vue中的按钮,想打开弹框,会不再起作用。
  1. // header.vue
  2. <div class="header>
  3. <message-board :visible="visible" />
  4. <button @click="visible=true">open</butotn>
  5. </div>
  6. // message-board.vue
  7. <div class="message-board">
  8. <el-dialog :visible.sync="visible"/>
  9. </div>

原因是,我们通过 message-board.vue中的.sync语法虽然修改了visible,但是没法同步给header.vue中的visible。后续再次点击按钮,visible的值在header.vue中的值没有变化(从true仍旧设置为true),因此底层(message-board.vue 和 el-dialog)的组件也就无法感知变化,从而导致功能问题。

我们可以有两种方式来修复这个问题(本质上都是通过自顶向下的方式来修改visible):

  1. mesage-board.vue在@close中,继续通过 update:visible 抛出,父组件使用 .sync语法
  2. mesage-board.vue在@close中,通过自定义事件抛出,父组件定义处理函数

    ```javascript // header.vue

    <div class=”header>

// message-board.vue

javascript // header.vue <div class=”header>