vue3封装一个基于element-plus的弹窗组件

10,523 阅读1分钟

vue3中自定义组件双向绑定语法的改变,使得写法和vue2大为不同。我们以element-plus的dialog组件为例。基于它。封装一个自己的对话框,同时介绍两种实现思路:

思路一:数据驱动型

我们封装一个test-dialog组件:

<el-button @click="open">打开</el-button>

<test-dialog  ref="testDom"  v-model:visible="flag" ></test-dialog>

import TestDialog from "@/components/Dialogs/TestDialog"

import { reactive, toRefs, ref, onMounted, watch } from "vue"

setup() {undefined

const state = reactive({

      flag: false

    })

 const open = () => {

      state.flag = true

    }

 watch(() => state.flag, (val) => {

      console.log("父组件监听flag:", val)

    })

}
子组件(弹窗组件):

<template>

  <el-dialog

    title="提示"

    v-model="dialogVisble"

    width="30%"

    :before-close="close"

  >

    <span>这是一段信息</span>

    <template #footer>

      <span class="dialog-footer">

        <el-button @click="close">取 消</el-button>

        <el-button

          type="primary"

          @click="close"

        >确 定</el-button>

      </span>

    </template>

  </el-dialog>

</template>

<script>

import { ref, watch } from "vue"

export default {undefined

  name: "TestDialog",

  components: {},

  props: {undefined

    visible: {

      type: Boolean,

      default: false

    }

  },

  setup(props, ctx) {

    const dialogVisble = ref(false)

    const close = () => {undefined

      ctx.emit("update:visible", false)

    }

    watch(() => dialogVisble.value, (val) => {

      ctx.emit("update:visible", val)

    })

    watch(() => props.visible, (val) => {

      dialogVisble.value = val

    })

    return {

      dialogVisble,

      open,

      close

    };

  },

};

</script>

<style scoped>

</style>

``

第二种思路:

类似直接操作dom,我们先通过ref拿到test-dialog组件的引用,每次点击打开按钮时,直接通过子组件去操作他内部的变量让它显示和隐藏

父页面:

<el-button @click="openByParentMethod ">打开</el-button>

<test-dialog  ref="testDom"  v-model:visible="flag" ></test-dialog>

import TestDialog from "@/components/Dialogs/TestDialog"

 setup() {

     const testDom = ref(null)

     const openByParentMethod = () => {

        testDom.value.dialogVisble = true

    }

    const closeByParentMethod= () => {

      testDom.value.dialogVisble = false

    }

   return {
      testDom,
      openByParentMethod,
      closeByParentMethod,

   }

}

<template>

  <el-dialog

    title="提示"

    v-model="dialogVisble"

    width="30%"

    :before-close="close"

  >

    <span>这是一段信息</span>

    <template #footer>

      <span class="dialog-footer">

        <el-button @click="close">取 消</el-button>

        <el-button

          type="primary"

          @click="close"

        >确 定</el-button>

      </span>

    </template>

  </el-dialog>

</template>

 setup(props, ctx) {

    const dialogVisble = ref(false)

    const open = () => {

      dialogVisble.value = true

    }

    const close = () => {

      dialogVisble.value = false

    }

  return {

      dialogVisble,

      open,

      close

    };
  },