vue3 使用v-model开发弹窗组件

我又来写这方面的东西了说实话 我用这个少 想着多记录一下

子组件

复制代码
<template>
	<el-dialog v-model="promiseVisible" title="修改起始上架章节" width="700px">
		<!-- 添加作品弹窗内容保持不变 -->
		<div class="diolag-applyUp-container">
			<div class="item">
				<div class="title">分卷</div>
				<div class="value">
					<el-select v-model="volumeValue" @change="volumeChange" placeholder="请选择分卷">
						<el-option v-for="item in volumeList" :key="item.volumeID" :label="item.volumeName" :value="item.volumeID" />
					</el-select>
				</div>
			</div>
			<div class="item">
				<div class="title">章节</div>
				<div class="value">
					<el-select v-model="chacaterValue" filterable :filter-method="filterMethod" :disabled="!volumeValue" placeholder="请选择章节">
						<el-option v-for="item in filteredOptions" :key="item.chapterID" :label="item.chapterName" :value="item.chapterID" />
					</el-select>
				</div>
			</div>
		</div>

		<template #footer>
			<div class="dialog-footer">
				<el-button @click="onCancelDiolag">取消</el-button>
				<el-button type="primary" @click="onConfirm"> 确定修改 </el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script setup>
import { ref, toRefs, onMounted, watch } from 'vue';
import { useChacaterApi } from '/@/api/chacater/index';
import { ElMessage } from 'element-plus';

const { getVolumeList, getChacaterList } = useChacaterApi();
const volumeValue = ref('');
const chacaterValue = ref('');
const volumeList = ref([]);
const chacaterList = ref([]);

// Props
const props = defineProps({
	// 控制弹窗显示
	modelValue: {
		type: Boolean,
		default: false,
	},
	novelID: {
		type: Number,
		required: true,
	},
});

const filteredOptions = ref([]); // 过滤后显示的选项列表
// 搜索过滤方法
const filterMethod = (query) => {
	if (query) {
		// 将输入和标签都转为小写进行不区分大小写的匹配
		filteredOptions.value = chacaterList.value.filter((item) => item.chapterName.toLowerCase().includes(query.toLowerCase()));
	} else {
		// 输入为空时,重置为全部选项
		filteredOptions.value = [...chacaterList.value];
	}
};
const emit = defineEmits(['update:modelValue', 'submit']);

const { novelID } = toRefs(props);
const promiseVisible = ref(false);

// 监听外部显示状态
watch(
	() => props.modelValue,
	(newVal) => {
		promiseVisible.value = newVal;
		if (newVal) {
			GetvolumeList();
		}
	}
);

// 监听内部弹窗状态,同步到父组件
watch(
	() => promiseVisible.value,
	(newVal) => {
		emit('update:modelValue', newVal);
		if (!newVal) {
			// 当弹窗关闭时,重置表单
			resetForm();
		}
	}
);

const volumeChange = (e) => {
	console.log(e, 'e');
	chacaterListByid(e);
};

const onCancelDiolag = () => {
	promiseVisible.value = false;
};

const onConfirm = () => {
	// 这里添加确认逻辑
	if (!volumeValue.value || !chacaterValue.value) {
		ElMessage.warning('请选择分卷和章节');
		return;
	}

	// 提交数据给父组件
	emit('submit', {
		volumeID: volumeValue.value,
		chapterID: chacaterValue.value,
	});

	// 关闭弹窗
	promiseVisible.value = false;
};

// 重置表单
const resetForm = () => {
	volumeValue.value = '';
	chacaterValue.value = '';
	volumeList.value = [];
	chacaterList.value = [];
};

onMounted(() => {
	// GetvolumeList();
});

//获取分卷
const GetvolumeList = async () => {
	try {
		const res = await getVolumeList({
			novelID: novelID.value,
		});
		if (res.code == 200) {
			volumeList.value = res.data.infos;
			console.log(res, 'res');
		} else {
			ElMessage.error(res.message);
			volumeList.value = [];
		}
	} catch (error) {
		ElMessage.error('获取书籍分卷失败~');
	}
};

//根据分卷的id 获取对应的章节
const chacaterListByid = async (volumeID) => {
	try {
		const res = await getChacaterList({
			novelID: novelID.value,
			volumeID,
			type: 1,
			sortord: 1,
			pageIndex: 1,
			pageSize: 0,
		});
		if (res.code == 200) {
			chacaterList.value = res.data.infos;
			filteredOptions.value = [...res.data.infos];
		} else {
			chacaterList.value = [];
			ElMessage.error(res.message);
		}
	} catch (error) {
		ElMessage.error('获取图书章节失败~');
	}
};
</script>

<style scoped lang="less">
.diolag-applyUp-container {
	.item {
		display: flex;
		align-items: center;
		.title {
			width: 80px;
		}
		.value {
			flex: 1;
		}
		&:nth-child(n + 2) {
			margin-top: 15px;
		}
	}
}
</style>

这是一个弹窗的组件 很多地方使用的同一个组件 所以我写了一个固定的组件

这个就是v-model绑定 双向。

跟普通的传递标识说一样吧 也一样 说不一样吧 的确有不同的地方

父组件使用

复制代码
		<ApplyModal v-model="showApplyModal" @submit="ApplySUbmit" :novelID="userInfos.novel.novelID"></ApplyModal>

其实也简单

相关推荐
脾气有点小暴12 小时前
H5 跳转方式
前端·javascript
Doris89312 小时前
【JS】JS进阶--作用域、函数、解构赋值、数组方法
开发语言·前端·javascript
黑客思维者12 小时前
核弹级漏洞突袭React生态:RSC反序列化何以成为RCE通道?
前端·javascript·react.js·远程代码执行漏洞
AndrewHZ12 小时前
【GIS数据处理】什么是Cesium?从零入门Web端三维地理可视化工具
javascript·gis·web开发·cesium·gis前端·三维地理可视化
GISer_Jing12 小时前
Next.js 15 全栈开发实战指南
开发语言·javascript·ecmascript
+VX:Fegn089512 小时前
计算机毕业设计|基于springboot + vue服装商城系统(源码+数据库+文档)
数据库·vue.js·spring boot
JIngJaneIL12 小时前
基于Java在线考试管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot
凌康ACG12 小时前
c++使用quickjs执行JavaScript
javascript·c++·quickjs
JIngJaneIL12 小时前
基于Java音乐管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
接着奏乐接着舞12 小时前
react hooks
前端·javascript·react.js