一、先下载引入element-plus
//直接冲官网指南
https://element-plus.gitee.io/zh-CN/guide/installation.html
//我这边用的scss预处理,直接下载就好了
npm install sass

二、子组件实现代码
//html代码
<template>
    <div>
        <el-dialog v-model="dialogVisible" :show-close="false" :close-on-click-modal="false">
            <div class="dialog">
                <div class="fs-16 bold c-0">选择好友<span class="fs-12 c-80">{{ contactList.length }}/{{ contacts.length
                }}</span><span style="margin-left: 200px;cursor:pointer" @click="chooses()">{{ choose == 1 ? '单选' : '多选'}}</span></div>
                <el-input v-model="contact" placeholder="搜索" clearable :prefix-icon="Search" @input="search" />
                <div class="list">
                    <el-scrollbar height="420px">
                        <div class="li" v-for="(item, index) in contacts" :key="index" @click="forwarding(item)">
                            <img :src="item.choose ? 'https://pic.imgdb.cn/item/6426503fa682492fcc5e327d.png' : 'https://pic.imgdb.cn/item/64265063a682492fcc5e65ad.png'"
                                alt="" class="li-left">
                            <div class="li-right">
                                <img src="https://pic.imgdb.cn/item/64265077a682492fcc5e7d6f.gif" alt="">
                                <!-- <img :src="item.img" alt=""> -->
                                <div class="fs-14 c-3">{{ item.name }}</div>
                            </div>
                        </div>
                    </el-scrollbar>
                </div>
                <div class="bottom">
                    <el-button type='primary' text @click="cancel">取消</el-button>
                    <el-button type='primary' text @click="determine">确认</el-button>
                </div>
            </div>
        </el-dialog>
    </div>
</template>
//组件通过dialog控制和scrollbar滚动条实现,所以先引用这2个组件
import { ref, toRefs, watch } from 'vue'
import { ElScrollbar, ElMessage, } from 'element-plus';
import { Search } from '@element-plus/icons-vue'

//然后定义组件的初始值,组件状态以及组件接受的参数等
let props = defineProps({
    dialogShow: {
        type: Boolean,
        default: false,
    },
});
const refProps = toRefs(props)
const emit = defineEmits(['getContact', 'contactShow'])
let dialogVisible = ref(props.dialogShow)//本地组件状态
watch(refProps.dialogShow, (val, old) => {
    dialogVisible.value = val
}, { deep: true })//监听修改本地
let contact = ref('')//联系人搜索
let contactList = ref([] as any)//选中转发的联系人
let choose = ref(2)//单选为1 多选为2
let contacts: any = ref([{
    img: '',
    name: 'Lingzi',
    choose: false,
    id: 1,
}, {
    img: '',
    name: 'zhangsan0',
    choose: false,
    id: 2,
}, {
    img: '',
    name: 'lisi',
    choose: false,
    id: 3,
}, {
    img: '',
    name: 'Wanger',
    choose: false,
    id: 4,
}, {
    img: '',
    name: 'yangyu',
    choose: false,
    id: 5,
}, {
    img: '',
    name: '007',
    choose: false,
    id: 6,
}, {
    img: '',
    name: 'YangyuS',
    choose: false,
    id: 7,
},])
let contactsCopy: any = ref(contacts.value)
//相关逻辑和方法
const chooses = () => {//单选多选切换
    choose.value = choose.value == 1 ? 2 : 1
    contacts.value.forEach((i:any)=>{
        i.choose=false
    })
    contactList.value=[]
}
const forwarding = (item: any) => {//选择
    if (choose.value == 1) {//单选
        if (!item.choose) {
            let y = contacts.value.some((i: any) => {
                return i.choose
            })
            if (y) {//有选中的
                contacts.value.forEach((item: any) => {
                    item.choose = false
                    contactList.value = []
                })
            }
        }
        item.choose = !item.choose
        if (item.choose) {
            contactList.value.push(item.name)
        } else {
            contactList.value = []
        }
    } else {//多选
        item.choose = !item.choose
        if (item.choose && contactList.value.indexOf(item.name) == -1) {
            contactList.value.push(item.name)
        } else if (!item.choose && contactList.value.indexOf(item.name) != -1) {
            contactList.value.splice(contactList.value.indexOf(item.name), 1)
        }
    }
};
const cancel = () => {//取消操作
    emit('contactShow', false)//通过emit传值给父组件
    contactList.value = []
    contacts.value.forEach((item: any) => {
        item.choose = false
    })
}
const determine = () => {//确定操作
    if (contactList.value && contactList.value.length) {
        emit('getContact', contactList.value)//把选中的信息传递给父组件
        cancel()
    } else {
        ElMessage.error('请选择转发的对象')
    }
}
const search = () => {//搜索
    if (contact.value == '') {
        contacts.value = contactsCopy.value
    }
    let arr = ref([] as any)
    contactsCopy.value.map((item: any) => {
        if (item.name.toLowerCase().indexOf(contact.value.toLowerCase()) != -1) {
            return arr.value.push(item)
        }
    })
    contacts.value = arr.value
}

三、父组件实现代码
//html代码
<el-button type="primary" @click="show()">打开弹框</el-button>
    <Dialog :dialogShow="dialogShow" @contactShow="contactShow" @getContact="getContact"></Dialog>

//js代码
import {ref} from 'vue'
import Dialog from '../components/forwarding.vue';
let dialogShow=ref(false)
const show=()=>{//控制子组件状态
    dialogShow.value=true
}
const contactShow = (e: boolean) => {//接受子组件传递过来的状态
  dialogShow.value = e
}
const getContact = (e: object) => {//接受子组件传递过来的状态
  console.log(e)
}
四、相关效果图

 


五、整体代码

//父组件
<template>
    <el-button type="primary" @click="show()">打开弹框</el-button>
    <Dialog :dialogShow="dialogShow" @contactShow="contactShow" @getContact="getContact"></Dialog>
</template>

<script setup lang="ts">
import {ref} from 'vue'
import Dialog from '../components/forwarding.vue';
let dialogShow=ref(false)
const show=()=>{//控制子组件显示
    dialogShow.value=true
}
const contactShow = (e: boolean) => {//接受子组件传递过来的状态
  dialogShow.value = e
}
const getContact = (e: object) => {//接受子组件传递过来的状态
  console.log(e)
}
</script>
<style scoped lang="scss"></style>

//子组件
<template>
    <div>
        <el-dialog v-model="dialogVisible" :show-close="false" :close-on-click-modal="false">
            <div class="dialog">
                <div class="fs-16 bold c-0">选择好友<span class="fs-12 c-80">{{ contactList.length }}/{{ contacts.length
                }}</span><span style="margin-left: 200px;cursor:pointer" @click="chooses()">{{ choose == 1 ? '单选' : '多选'}}</span></div>
                <el-input v-model="contact" placeholder="搜索" clearable :prefix-icon="Search" @input="search" />
                <div class="list">
                    <el-scrollbar height="420px">
                        <div class="li" v-for="(item, index) in contacts" :key="index" @click="forwarding(item)">
                            <img :src="item.choose ? 'https://pic.imgdb.cn/item/6426503fa682492fcc5e327d.png' : 'https://pic.imgdb.cn/item/64265063a682492fcc5e65ad.png'"
                                alt="" class="li-left">
                            <div class="li-right">
                                <img src="https://pic.imgdb.cn/item/64265077a682492fcc5e7d6f.gif" alt="">
                                <!-- <img :src="item.img" alt=""> -->
                                <div class="fs-14 c-3">{{ item.name }}</div>
                            </div>
                        </div>
                    </el-scrollbar>
                </div>
                <div class="bottom">
                    <el-button type='primary' text @click="cancel">取消</el-button>
                    <el-button type='primary' text @click="determine">确认</el-button>
                </div>
            </div>
        </el-dialog>
    </div>
</template>
<!-- 多选组件---------------- -->
<script setup lang="ts">
import { ref, toRefs, watch } from 'vue'
import { ElScrollbar, ElMessage, } from 'element-plus';
import { Search } from '@element-plus/icons-vue'
let props = defineProps({
    dialogShow: {
        type: Boolean,
        default: false,
    },
});
const refProps = toRefs(props)
const emit = defineEmits(['getContact', 'contactShow'])
let dialogVisible = ref(props.dialogShow)//本地组件状态
watch(refProps.dialogShow, (val, old) => {
    dialogVisible.value = val
}, { deep: true })//监听修改本地
let contact = ref('')//联系人搜索
let contactList = ref([] as any)//选中转发的联系人
let choose = ref(2)//单选为1 多选为2
let contacts: any = ref([{
    img: '',
    name: 'Lingzi',
    choose: false,
    id: 1,
}, {
    img: '',
    name: 'zhangsan0',
    choose: false,
    id: 2,
}, {
    img: '',
    name: 'lisi',
    choose: false,
    id: 3,
}, {
    img: '',
    name: 'Wanger',
    choose: false,
    id: 4,
}, {
    img: '',
    name: 'yangyu',
    choose: false,
    id: 5,
}, {
    img: '',
    name: '007',
    choose: false,
    id: 6,
}, {
    img: '',
    name: 'YangyuS',
    choose: false,
    id: 7,
},])
let contactsCopy: any = ref(contacts.value)
const chooses = () => {//单选多选切换
    choose.value = choose.value == 1 ? 2 : 1
    contacts.value.forEach((i:any)=>{
        i.choose=false
    })
    contactList.value=[]
}
const forwarding = (item: any) => {//选择
    if (choose.value == 1) {//单选
        if (!item.choose) {
            let y = contacts.value.some((i: any) => {
                return i.choose
            })
            if (y) {//有选中的
                contacts.value.forEach((item: any) => {
                    item.choose = false
                    contactList.value = []
                })
            }
        }
        item.choose = !item.choose
        if (item.choose) {
            contactList.value.push(item.name)
        } else {
            contactList.value = []
        }
    } else {//多选
        item.choose = !item.choose
        if (item.choose && contactList.value.indexOf(item.name) == -1) {
            contactList.value.push(item.name)
        } else if (!item.choose && contactList.value.indexOf(item.name) != -1) {
            contactList.value.splice(contactList.value.indexOf(item.name), 1)
        }
    }
};
const cancel = () => {//取消操作
    emit('contactShow', false)//通过emit传值给父组件
    contactList.value = []
    contacts.value.forEach((item: any) => {
        item.choose = false
    })
}
const determine = () => {//确定操作
    if (contactList.value && contactList.value.length) {
        emit('getContact', contactList.value)//把选中的信息传递给父组件
        cancel()
    } else {
        ElMessage.error('请选择转发的对象')
    }
}
const search = () => {//搜索
    if (contact.value == '') {
        contacts.value = contactsCopy.value
    }
    let arr = ref([] as any)
    contactsCopy.value.map((item: any) => {
        if (item.name.toLowerCase().indexOf(contact.value.toLowerCase()) != -1) {
            return arr.value.push(item)
        }
    })
    contacts.value = arr.value
}
</script>
<style scoped lang="scss">
.fs-16 {
    font-size: 16px;
    font-family: Source Han Sans CN;
    font-weight: 400;
    color: #333333;
}

.fs-12 {
    font-size: 12px;
    font-family: SourceHanSansSC;
    font-weight: 400;
    color: #999999;
}

.fs-14 {
    font-size: 14px;
    font-family: Source Han Sans CN;
    font-weight: 400;
    color: #FFFFFF;
}

.fs-20 {
    font-size: 20px;
    font-family: Source Han Sans CN;
    font-weight: 500;
    color: #333333;
}

.c-0 {
    color: #000000;
}

.c-3 {
    color: #333333;
    font-weight: 500;
}

.c-80 {

    color: #808080;
}

.bold {
    font-weight: bold;
}

:deep(.el-dialog) {
    width: 362px;
    height: 580px;
    background: #FFFFFF;
    border-radius: 6px;
    position: absolute;
    top: 2%;
    left: 40%;

    .el-dialog__header {
        padding: 0;
    }

    .el-dialog__body {
        padding: 0;
    }

    .dialog {
        padding: 20px;
        text-align: left;

        .el-input__wrapper {
            margin-top: 30px;
            padding: 0;
            border-bottom: 1px solid #f2f2f2;
            box-shadow: none
        }

        .list {
            margin-top: 2px;

            .li {
                display: flex;
                align-items: center;
                padding: 10px 0;

                // padding:0 20px;
                .li-left {
                    width: 18px;
                    height: 18px;
                    margin-right: 10px;
                }

                .li-right {
                    display: flex;
                    align-items: center;

                    img {
                        width: 46px;
                        height: 46px;
                        border-radius: 50%;
                        margin-right: 12px;
                    }
                }
            }

            .li:hover {
                background: #e6eaf2;
            }
        }

        .bottom {
            display: flex;
            margin-top: 10px;
            justify-content: flex-end;
        }
    }
}</style>

六、总结
一个简单的转发弹框,有相同业务逻辑的项目可以直接copy现用,代码写的有点渣,有相关代码优化的地方还望各位大佬能指点一二。

Logo

前往低代码交流专区

更多推荐