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>

其实也简单

相关推荐
matlab_xiaowang11 小时前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
前端摸鱼匠13 小时前
Vue 3 的v-bind合并行为:讲解v-bind与普通属性合并的规则
前端·javascript·vue.js·前端框架·ecmascript
REDcker13 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
Linsk15 小时前
Java和JavaScript的关系真是雷峰和雷峰塔的关系吗?
java·javascript·oracle
当时只道寻常15 小时前
浏览器文本复制到剪贴板:企业级最佳实践
javascript
Alice-YUE16 小时前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
是上好佳佳佳呀17 小时前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记
莎士比亚的文学花园17 小时前
Linux驱动开发(3)——设备树
开发语言·javascript·ecmascript
01漫游者18 小时前
JavaScript函数与对象增强知识
开发语言·javascript·ecmascript
threelab20 小时前
Three.js 代码云效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能