需求:在页面的代码太多,想把弹窗代码提取为子组件,复用也方便。
 
这里涉及到弹窗el-dialog的一个属性show-close:
show-close="false"是设置不显示关闭按钮,因为弹窗显示状态值(:visible.sync)是从父组件传递的参数,如果使用自带的关闭按钮,会报出一个错误:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "visible"
虽然弹窗会关闭,但却会导致弹窗的显示状态没有及时修改为false,需要点击两次触发弹窗click事件才能再打开弹窗。
所以,为了避免这个错误,这里提供两个方案:
1.关闭按钮另外添加,因为要触发click事件来触发父组件修改变量(使用$emit通知父组件来操作)。
2.使用自带关闭按钮,给弹窗添加before-close事件(这是elementUI提供的),在这个方法里也是使用$emit修改父组件的visible状态。
 
第一种方案:
 
父组件:
<template>
<div class="main-wrap">
<el-button type="primary" @click="add('addOrder')">添加</el-button>
<add-order ref="addOrder" v-if="addOrderVisible" :visible.sync="addOrderVisible"></add-order>
</div>
</template>
<script>
import Add from './add.vue'
export default {
data(){
return {
addOrderVisible: false
}
},
methods: {
add(refForm){
if(this.$refs[refForm]){
this.$refs[refForm].initForm();
}
this.addOrderVisible= true;
}
},
components: {
'add-order': Add
}
}
</script>
 
子组件:
<template>
<el-dialog :visible.sync="visible" :show-close="false" width="600px" :modal="true" :close-on-click-modal="false" :close-on-press-escape="false">
<h2 slot="title">添加订单</h2>
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click.stop="cancelModal"><i class="el-dialog__close el-icon el-icon-close"></i></button>
<el-form class="form-wrapper" ref="orderForm" :model="orderForm" :rules="addRules" label-width="110px">
<el-form-item label="联系人:" prop="fromContact">
<el-input v-model="orderForm.fromContact" type="text" placeholder="请输入联系人名称"></el-input>
</el-form-item>
<el-form-item label="联系电话:" prop="fromPhone">
<el-input v-model="orderForm.fromPhone" type="text" placeholder="请输入联系电话"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="buttons-wrap">
<el-button type="primary">确定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
props: {
visible: {
type: Boolean,
default: false
}
},
data(){
return {
orderForm: {},
addRules: {
fromContact: [{ required: true, message: "请输入联系人姓名", trigger: 'blur'}],
fromPhone: [{required: true, message: "请输入", trigger: 'blur'}]
}
}
},
methods: {
initForm(){
this.orderForm = {
fromContact: '',
fromPhone: ''
};
if(this.$refs.orderForm){
this.$refs.orderForm.resetFields();
}
},
cancelModal(){
// 关闭弹窗,触发父组件修改visible值
this.$emit('update:visible', false);
}
}
}
</script>
<style lang="scss" scoped>
.buttons-wrap { .el-button {
margin-right: 20px;
min-width: 100px;
}
}
</style>
 
第二种方案:(添加before-close)

父组件:

<template>
<div class="main-wrap">
<el-button type="primary" @click="toAdd">添加</el-button>
<add-order ref="orderAdd" v-if="addOrderVisible" :visible.sync="addOrderVisible"></add-order>
</div>
</template>
<script>
import Add from './add.vue'
export default {
data(){
return {
addOrderVisible: false
}
},
methods: {
toAdd() {
this.addOrderVisible = true;
}
},
components: {
'add-order': Add
}
}
</script>

子组件:

<template>
<el-dialog
title="添加"
v-loading="loading"
:visible.sync="visible"
width="600px"
:before-close="modalClose"
:close-on-click-modal="false"
:close-on-press-escape="false">
<div>弹窗内容</div>
</el-dialog>
</template>
<script>
export default {
data() {
return {
loading: false
}
},
props: {
visible: {
type: Boolean,
default: false
}
},
methods: {
modalClose() {
this.$emit('update:visible', false); // 直接修改父组件的属性
}
}
}
</script>

这里提另外一种情况:

在只需要显示详情内容的情况下,也可以采取只把内容放到子组件中,头部和底部按钮都放在父组件中,这就不需要考虑弹窗显示状态的问题,把需要显示的参数传到子组件中即可。
 
父组件:
<template>
<div class="main-wrap">
<el-button type="primary" @click="showDetail()">详情</el-button>
<el-dialog v-if="detailVisible" :visible.sync="detailVisible" width="600px" :modal="true">
<h2 slot="title">详情</h2>
<detail ref="newOrderDetail" :newOrderDetail="newOrderDetail"></detail>
<div slot="footer" class="detail-wrap-bottom">
<el-button type="primary">确认</el-button>
<el-button type="default">退回</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import detail from './detail'
export default {
data(){
return {
detailVisible: false,
newOrderDetail: {}
}
},
methods: {
showDetail(){
this.newOrderDetail = {id: 8, fromContact: 'Thomas', fromPhone: '15812345678'};
this.detailVisible= !this.detailVisible;
}
},
components: {
detail: detail
}
}
</script>
子组件:
<template>
<div class="detail-wrap" :data="newOrderDetail">
<ul>
<li><span>用车联系人:</span><div>{{newOrderDetail.fromContact}}</div></li>
<li><span>联系人电话:</span><div>{{newOrderDetail.fromPhone}}</div></li>
</ul>
</div>
</template>
<script>
export default {
props: {
newOrderDetail: {
type: Object,
default: null
}
},
data() {
return {
loading: false
}
}
}
</script>
<style lang="scss" scoped>
.detail-wrap ul {
max-height: 400px;
overflow: auto; li {
position: relative;
padding: 8px;
font-size: 1rem; span {
position: absolute;
width: 90px;
} & > div {
margin-left: 90px;
}
}
}
</style>
 

温馨提示:

如果弹窗内容较多,出现了滚动条,需要每次打开还原到顶部,则需要添加v-if指令,因为这个指令是动态渲染内容的(文中有用到)。

 
 
 

ElementUI对话框(dialog)提取为子组件的更多相关文章

  1. elementUI 的el-dialog作为子组件,父组件如何控制其关闭的按钮

    这里有三点需要说明: 1. 使用:before-close="closeHandle" 将其 $emit() 出去 2. 取消按钮 也需要$emeit出去 3. 控制对话框显示隐藏 ...

  2. vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值。

    vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值. vue 父组件与子组件相互通信 一.父组件给子组件传值 props 实现父组件向子组件传值. 1父组件里: ...

  3. java 图形化小工具Abstract Window Toolit 常用组件:对话框Dialog FileDialog

    对话框 Dialog是Window类的子类,是1个容器类,属于特殊组件,对话框是可以独立存在的顶级窗口,因此用法与普通窗口的用法几乎完全一样.但对话框有如下两点需要注意. (1),对话框通常依赖于其他 ...

  4. element-ui(或者说Vue的子组件)绑定的方法中传入自定义参数

    比如el-upload中的 :on-success= fn,其实是给组件el-upload传递一个prop,这样写的话fn只能接受upload组件规定的参数,如果想自己传递父组件中的参数比如b,要写成 ...

  5. 对话框Dialog

    QMainWindow QMainWindow是 Qt 框架带来的一个预定义好的主窗口类. 主窗口,就是一个普通意义上的应用程序(不是指游戏之类的那种)最顶层的窗口.通常是由一个标题栏,一个菜单栏,若 ...

  6. vue实现element-ui对话框可拖拽功能

    element-ui对话框可拖拽及边界处理 应业务需求,需要实现对话框可拖拽问题,应element-ui没有提供官方支持,于是便参考大神的文章,得出了适合业务需要的解决方案.很多大神给出的代码是没有解 ...

  7. vue:父子组件间通信,父组件调用子组件方法进行校验子组件的表单

    参考: ElementUI多个子组件表单的校验管理:https://www.jianshu.com/p/541d8b18cf95 Vue 子组件调用父组件方法总结:https://juejin.im/ ...

  8. vue父组件向子组件传对象,不实时更新解决

    vue报错:void mutating a prop directly since the value will be overwritten whenever the parent componen ...

  9. 实现element-ui对话框可拖拽功能

    element-ui对话框可拖拽及边界处理 应业务需求,需要实现对话框可拖拽问题,应element-ui没有提供官方支持,于是便参考大神的文章,得出了适合业务需要的解决方案.很多大神给出的代码是没有解 ...

随机推荐

  1. SemaphoreSlim 实现

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/dz45693/article/deta ...

  2. Android输入法遮挡了输入框,使用android:fitsSystemWindows="true"后界面顶部出现白条解决方案

    我的最外层是LinearLayout,自定义CustomLinearLayout继承LinearLayout,重写fitSystemWindows和onApplyWindowInsets两个方法: p ...

  3. stringstream用法

    stringstream用法 1.头文件:#include<sstream> 2.stringstream是C++提供的串流(stream)物件,其中: clear()重置流的标志状态:s ...

  4. Flutter TextField详解

    原文地址:https://www.jianshu.com/p/54419a143d70 实现TextField说简单也简单,说有坑,坑也不小,下面从易到难介绍一下使用 1.最简单的就是无参数调用构造方 ...

  5. 报错:Error while fetching metadata with correlation id 67 : {alarmHis=LEADER_NOT_AVAILABLE}

    报错背景: 单机安装了kafka,创建完成主题,启动生产者的时候产生报错现象.报错时持续不断打印日志信息. 报错现象: [-- ::,] WARN [Producer clientId=console ...

  6. JS正则匹配邮箱格式

    观察一些邮箱格式,有些邮箱格式简单,有些复杂,在网上找了个邮箱的正则表达式,分析一下邮箱的规则.该表达式:/^\w+([\.\-]\w+)*\@\w+([\.\-]\w+)*\.\w+$/ 拆分:[1 ...

  7. SpringBoot学习笔记:自定义拦截器

    SpringBoot学习笔记:自定义拦截器 快速开始 拦截器类似于过滤器,但是拦截器提供更精细的的控制能力,它可以在一个请求过程中的两个节点进行拦截: 在请求发送到Controller之前 在响应发送 ...

  8. IntelliJ IDEA 下搭建vue项目工程

    Vue 项目:运行 npm run dev  后报错 “'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件.” 前提: 电脑已经安装了node 和 npm, ...

  9. 按键板的原理和实现--基于GPIO的按键板

    上篇介绍简单的ADC实现,需要IC提供一个额外的ADC.但出于IC成本的考虑,无法提供这个的ADC时,但提供了多个额外的GPIO(General Purpose Input Output:双向的:可以 ...

  10. mybatis xml动态语句写法

    mapper.java: /** * @Description: 根据摄像机Id查询出入记录 * @Param: * name 姓名 * monitorId 布控ID * starttime 开始时间 ...