分享记录vue3+ts基于element-plus通过父子组件交互实现聊天窗口的转发弹框,支持多选、单选、搜索等基础功能。开整
一、先下载引入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现用,代码写的有点渣,有相关代码优化的地方还望各位大佬能指点一二。
更多推荐
所有评论(0)