二次封装el-dialog组件,自定义组件应用v-model的实践

5 篇文章 0 订阅
4 篇文章 0 订阅

1.问题描述 

  • 在vue项目中,对于dialog弹框的使用频率较高,如果是增删改查页面,几乎是每个页面都需要用到;
  • 如果将dialog封装成一个组件,在利用slot插槽,每个页面应用起来会更加简单;
  • 查阅了vuejs官网,发现v-model也可以应用到自定义组件上,model属性就是获取到自定义组件的prop、event,考虑采用一下方式实现dialog的封装。

2. 最开始想到的dialog封装

<template>
<!-- 父组件 -->
  <div>
    <h3>自定义dialog组件</h3>
    <el-button type="primary" @click="openDialogHandler"
      >点击展开对话框</el-button
    >

    <!-- 封装的el-dialog组件 -->
    <detail-dialog :dialogVisible="dialogVisible" :title="title">
      <div slot="body">
        自定义组件v-model实践,可以直接应model,其中有prop、event两个属性
      </div>

      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">关闭</el-button>
      </div>
    </detail-dialog>
  </div>
</template>

<script>
import DetailDialog from "./components/dialog.vue";
export default {
  components: { DetailDialog },
  data() {
    return {
      dialogVisible: false,
      title: "",
    };
  },

  mounted() {},

  methods: {
    openDialogHandler() {
      this.dialogVisible = true;
      this.title = "查看自定义组件使用v-model";
    },
  },
};
</script>

<style scoped>
</style>
<template>
<!-- 子组件 -->
  <div>
    <el-dialog
      :title="title"
      :visible.sync="dialogVisible"
      width="600px"
    >
      <slot name="body"/>
      <span slot="footer">
        <slot name="footer"></slot>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  props: {
    dialogVisible: {
      type: Boolean,
      default: false
    },
    title:{
      type:String,
      default:'自定义组件提示'
    }
  },
  data() {
    return {};
  },

  mounted() {},

  methods: {},
};
</script>

<style lang="" scoped>
</style>

结果:

 

子组件是禁止直接修改props的,所以控制台会报错。 

这时候考虑新增一个中间变量innerVisible,来拦截props[visible]的修改和获取。注意:在父组件传值的时候需要加上.sync,这里可以查看vuejs官网

<!-- 父组件 -->
<detail-dialog :dialogVisible.sync="dialogVisible" :title="title">
      <div slot="body">
        自定义组件v-model实践,可以直接应model,其中有prop、event两个属性
      </div>

      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">关闭</el-button>
      </div>
    </detail-dialog>
<template>
    <!--子组件 -->
  <div>
    <el-dialog
      :title="title"
      :visible.sync="innerVisible"
      width="600px"
    >
      <slot name="body"/>
      <span slot="footer">
        <slot name="footer"></slot>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  props: {
    dialogVisible: {
      type: Boolean,
      default: false
    },
    title:{
      type:String,
      default:'自定义组件提示'
    }
  },
  data() {
    return {};
  },

  mounted() {},
  computed:{
    innerVisible:{
      get:function(){
        return this.dialogVisible;
      },
      set:function(val){
        this.$emit('update:dialogVisible', val);
      }
    }
  },

  methods: {},
};
</script>

<style lang="" scoped>
</style>

这样子就不会报错啦!!!!

查看vuejs官网会发现,自定义组件也可以应用v-model,然后在子组件中通过model中的prop、event操作实现props值的双向传递。

 <!-- 封装的el-dialog组件 -->
    <detail-dialog v-model="dialogVisible" :title="title">
      <div slot="body">
        自定义组件v-model实践,可以直接应model,其中有prop、event两个属性
      </div>

      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">关闭</el-button>
      </div>
    </detail-dialog>
<template>
  <div>
    <el-dialog
      :title="title"
      :visible.sync="innerVisible"
      width="600px"
    >
      <slot name="body"/>
      <span slot="footer">
        <slot name="footer"></slot>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  model:{
    prop:'dialogVisible',// 修改 v-model 绑定的props名称
    event:'toggle'  // 修改 v-model 绑定的自定义事件名
  },
  props: {
    dialogVisible: {
      type: Boolean,
      default: false
    },
    title:{
      type:String,
      default:'自定义组件提示'
    }
  },
  data() {
    return {};
  },

  mounted() {},
  computed:{
    innerVisible:{
      get:function(){
        return this.dialogVisible;
      },
      set:function(val){
        this.$emit('update:toggle', val);
      }
    }
  },

  methods: {},
};
</script>

<style lang="" scoped>
</style>

继续优化,将dialog的相关方法封装到mixins里,以后页面用就可以直接引入mixin就可以了!

<template>
<!--dialog子组件-->
  <div>
    <el-dialog
      :title="title"
      :visible.sync="innerVisible"
      width="600px"
    >
      <slot name="body"/>
      <span slot="footer">
        <slot name="footer"></slot>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import dialog from '@/mixins/dialog.js'
export default {
  mixins:[dialog],//引入mixin
  data() {
    return {};
  },

  mounted() {},
  computed:{
  },

  methods: {},
};
</script>

<style lang="" scoped>
</style>
mixins.js
export default {
  model: {
    prop: 'dialogVisible',
    event: 'toggle'
  },
  props: {
    dialogVisible: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: '自定义组件提示'
    }
  },
  computed: {
    innerVisible: {
      get: function () {
        return this.dialogVisible;
      },
      set: function (val) {
        this.$emit('update:toggle', val);
      }
    }
  },

}

这样就可以很简单的控制mixin的显示与隐藏啦!(具体有参考juejin:漓漾li)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值