• ElementUI对话框(dialog)提取为子组件


    需求:在页面的代码太多,想把弹窗代码提取为子组件,复用也方便。
     
    这里涉及到弹窗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指令,因为这个指令是动态渲染内容的(文中有用到)。

     
     
     
  • 相关阅读:
    百度地图API开发----手机地图做导航功能
    手机端列表做异步加载!
    onethink判断是否是手机访问?
    PHP中文字数限制:中文字符串截取(mb_substr)
    onethink封装arclist调用文章列表!
    问答项目---提问回答采纳处理!
    问答项目---面包削导航的处理!
    问答项目---处理待解决/已回答/高悬赏/零回答!
    问答项目---格式化输出提问时间!
    问答项目---提问按钮如何做!
  • 原文地址:https://www.cnblogs.com/yeqrblog/p/9141701.html
Copyright © 2020-2023  润新知