我们这里一封装一个抽屉组件为例子。
环境:element-plus,windicss
1.定义一个vue文件用于存放我们的dom。
FormDrawer.vue:
把抽屉组件扔进去,给它设置宽高,并暴露出打开和关闭方法
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<el-drawer v-model="showDrawer" title="修改密码" size="45%"
:close-on-click-modal="false">
</el-drawer>
</template>
<script setup>
import { ref } from 'vue';
const showDrawer = ref(false)
const open = () => { showDrawer.value = true }
const close = () => { showDrawer.value = false }
defineExpose({
open,
close,
})
</script>
2.在我们的父组件中引用我们的子组件,并设置它的开启和关闭
<script setup>
import FormDrawer from '../../../../components/FormDrawer.vue'
//设置它的开启和关闭
const formDrawerRef = ref(null)
const button = ()=>{
formDrawerRef.value.open()
}
</script>
<template>
<button @click="button">成功</button>
<form-test ref="formDrawerRef">
</form-test>
</template>
效果
3.再回来设置自定义组件的样式
我们给它点样式:
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<el-drawer v-model="showDrawer" title="修改密码" size="45%" class="formDrawer"
:close-on-click-modal="false">
<div class="DrawerForm">
<div class="body">
<!-- 这是插槽,<slot></slot> 是 HTML 的一个重要特性,也是 Web 组件(Web Components)的一部分。
它允许开发者在自定义组件中插入占位符,以便在将来使用时,可以在这些占位符中填充内容。 -->
<slot></slot>
</div>
<div class="actions">
<el-button type="primary" @click="submit">确认</el-button>
<el-button type="default" @click="close">取消</el-button>
</div>
</div>
</el-drawer>
</template>
<script setup>
import { ref } from 'vue';
const showDrawer = ref(false)
const open = () => { showDrawer.value = true }
const close = () => { showDrawer.value = false }
defineExpose({
open,
close,
})
</script>
<style>
.formDrawer {
@apply ;
}
.DrawerForm {
width: 100%;
height: 100%;
position: relative;
/* flex-col垂直排布 */
@apply flex flex-col;
}
.body {
/* 超出部分是滚动 */
overflow-y: auto;
@apply ;
}
/* margin-top:auto就是会自动至于底部,但是很重要的是!父和子组件都要是块级组件 */
.actions {
height: 50px;
@apply mt-auto flex items-center;
}</style>
4.在父组件就可以给插槽里面加东西了
我加了一些表单组件
<script setup>
import FormDrawer from '../../../../components/FormDrawer.vue'
import { ref, reactive } from 'vue'
//设置它的开启和关闭
const formDrawerRef = ref(null)
const button = ()=>{
formDrawerRef.value.open()
}
//修改密码
const ruleForm = reactive({
oldpassword:"",
pasword: "",
repassword: ""
})
const rules = reactive({
oldpassword: {
required: true,
message: '旧密码不能为空',
trigger: 'blur'
},
password: {
required: true,
message: '不要为空',
trigger: 'blur'
},
repassword: {
required: true,
message: '新密码不能为空',
trigger: 'blur'
}
})
//这是表单验证查看是否正确,在validate会返回true,否则返回false
const formRef = ref(null)
</script>
<template>
<button @click="button">成功</button>
<form-test ref="formDrawerRef">
<form-test ref="formDrawerRef">
<el-form :model="ruleForm" :rules="rules" label-width="120px" ref="formRef">
<el-form-item label="旧密码" prop="oldpassword">
<el-input v-model="ruleForm.oldpassword" show-password placeholder="请输入旧密码" />
</el-form-item>
<el-form-item label="新密码" prop="password">
<el-input v-model="ruleForm.password" show-password placeholder="请输入新密码" />
</el-form-item>
<el-form-item label="确认密码" prop="repassword">
<el-input v-model="ruleForm.repassword" show-password placeholder="请输入确认密码" />
</el-form-item>
</el-form>
</form-test>
</form-test>
</template>
5.把子组件的属性暴露出去
现在就基本样式出来了,但是吧,我们不止需要这些呀。我们还要动态设置他的标题(“修改密码”),还有按钮样式,按钮的方法。
所以这时候我们要把他当方法暴露出去。
在这里要使用:size="size"等响应式的写法
完整代码了:
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<el-drawer v-model="showDrawer" :title="title" :size="size" class="formDrawer"
:close-on-click-modal="false">
<div class="DrawerForm">
<div class="body">
<!-- 这是插槽,<slot></slot> 是 HTML 的一个重要特性,也是 Web 组件(Web Components)的一部分。
它允许开发者在自定义组件中插入占位符,以便在将来使用时,可以在这些占位符中填充内容。 -->
<slot></slot>
</div>
<div class="actions">
<el-button type="primary" @click="submit">{{ comfirmText }}</el-button>
<el-button type="default" @click="close">取消</el-button>
</div>
</div>
</el-drawer>
</template>
<script setup>
import { ref } from 'vue';
const showDrawer = ref(false)
const open = () => { showDrawer.value = true }
const close = () => { showDrawer.value = false }
defineExpose({
open,
close,
})
// 动态暴露我们的组件属性
const prop = defineProps({
title: String,
size: {
type: String,
default: "45%",
},
destroyOnClose: {
type: Boolean,
default: false
},
comfirmText: {
type: String,
default: "提交"
}
})
//获取到父组件的方法
const emit = defineEmits(["submit"])
//将父组件方法添加到本组件
const submit = ()=>emit("submit")
</script>
<style>
.formDrawer {
@apply ;
}
.DrawerForm {
width: 100%;
height: 100%;
position: relative;
/* flex-col垂直排布 */
@apply flex flex-col;
}
.body {
/* 超出部分是滚动 */
overflow-y: auto;
@apply ;
}
/* margin-top:auto就是会自动至于底部,但是很重要的是!父和子组件都要是块级组件 */
.actions {
height: 50px;
@apply mt-auto flex items-center;
}</style>
6.在父组件使用
完整代码了:
<script setup>
import FormDrawer from '../../../../components/FormDrawer.vue'
import { ref, reactive } from 'vue'
//设置它的开启和关闭
const formDrawerRef = ref(null)
const button = ()=>{
formDrawerRef.value.open()
}
//修改密码
const ruleForm = reactive({
oldpassword:"",
pasword: "",
repassword: ""
})
const rules = reactive({
oldpassword: {
required: true,
message: '旧密码不能为空',
trigger: 'blur'
},
password: {
required: true,
message: '不要为空',
trigger: 'blur'
},
repassword: {
required: true,
message: '新密码不能为空',
trigger: 'blur'
}
})
//这是表单验证查看是否正确,在validate会返回true,否则返回false
const formRef = ref(null)
</script>
<template>
<button @click="button">成功</button>
<form-test ref="formDrawerRef" title="成功超过超过" size="50%" comfirmText="提交" @submit="submit">
<el-form :model="ruleForm" :rules="rules" label-width="120px" ref="formRef">
<el-form-item label="旧密码" prop="oldpassword">
<el-input v-model="ruleForm.oldpassword" show-password placeholder="请输入旧密码" />
</el-form-item>
<el-form-item label="新密码" prop="password">
<el-input v-model="ruleForm.password" show-password placeholder="请输入新密码" />
</el-form-item>
<el-form-item label="确认密码" prop="repassword">
<el-input v-model="ruleForm.repassword" show-password placeholder="请输入确认密码" />
</el-form-item>
</el-form>
</form-test>
</template>