vue按钮弹框

在Vue中实现按钮点击后弹出对话框(弹框)的功能,通常可以使用一些Vue的UI组件库,如Element UI、Vuetify、BootstrapVue等,这些库提供了丰富的组件,包括对话框(Dialog)、模态框(Modal)等,可以很方便地实现这个功能。但如果你不想使用任何UI库,也可以自己手写一个简单的弹框组件。

<template>
	<el-button type="primary" plain @click="dialogFormVisible = true">新建专辑
	</el-button>
	<el-dialog v-model="dialogFormVisible" title="新建专辑" class="el-dialog__header" style="z-index: 2065;">
		<el-form :model="form">
			<el-form-item label="名称" :label-width="formLabelWidth" style=" width: 460px;margin-top: 20px;" >
				<el-input v-model="form.name" autocomplete="off" />
			</el-form-item>
			<el-form-item label="创建人" :label-width="formLabelWidth" style=" width: 460px">
				<el-select v-model="form.region">
					<el-option label="不限" value="不限" />
				</el-select>
			</el-form-item>
			<el-form-item label="创建人" :label-width="formLabelWidth" style=" width: 460px">
				<el-select v-model="form.region">
					<el-option label="不限" value="不限" />
				</el-select>
			</el-form-item>
			<el-form-item label="权限" :label-width="formLabelWidth">
				<el-radio-button label="left">所有人可见</el-radio-button>
				<el-radio-button label="right">指定人员可见</el-radio-button>
				<el-radio-button label="top">项目人员可见</el-radio-button>
			</el-form-item>
			<div class="mt16">
				<el-form-item :label-width="formLabelWidth" style=" width: 550px">
					<el-input v-model="input" placeholder="请输入内容" :suffix-icon="Search"></el-input>
				</el-form-item>
				<div class="cascader-container left" style="margin-left: 140px;">
					<div class="cascader-title">
						<div class="tab-label "  :class="!showUser ?'action':''">部门</div>
						<div class="tab-label "  :class="showUser ?'action':''">人员</div>
<!--						<el-tabs v-model="activeName" @tab-click="handleClick">-->
<!--							<el-tab-pane label="部门" name="first" class="tab-label ">-->
<!--								1-->
<!--							</el-tab-pane>-->
<!--							<el-tab-pane label="人员" name="second" class="tab-label ">人员</el-tab-pane>-->
<!--						</el-tabs>-->

					</div>
					<div class="cascader-list">
						<div class="cascader-list member-parent">
							<div class="member-left" >
								<el-tree
									style="width: 100%;"
									:props="props"
									:load="loadNode"
									lazy
									show-checkbox
									@check-change="handleCheckChange"
								/>
							</div>
							<div class="member-right" >
								<el-checkbox v-model="checked1" label="公司" size="large" class="member-right-text"/>
							</div>
						</div>
					</div>
				</div>
				<div class="cascader-container right">
					<div class="cascader-title">
						<span>已选可见人员(0)</span>
					</div>
					<div class="cascader-list"></div>
				</div>
			</div>

<!--			<el-form-item :label-width="formLabelWidth">-->
<!--				<el-transfer-->
<!--					filterable-->
<!--					:filter-method="filterMethod"-->
<!--					filter-placeholder="请输入城市拼音"-->
<!--					v-model="value"-->
<!--					:data="data">-->
<!--				</el-transfer>-->
<!--			</el-form-item>-->
			<el-form-item label="备注(非必填)" :label-width="formLabelWidth" style="margin-top: 20px;">
				<el-input
					v-model="textarea"
					style="width: 360px; height: 64px;"
					type="textarea"
					placeholder="请输入一个备注"
				/>
			</el-form-item>

		</el-form>
		<template #footer>
			<div class="dialog__footer">
				<el-button @click="dialogFormVisible = false">取消</el-button>
				<el-button type="primary" @click="dialogFormVisible = false">
					保存
				</el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script lang="ts" setup>
import { reactive, ref } from "vue";
import { Search } from "@element-plus/icons-vue";
import type Node from 'element-plus/es/components/tree/src/model/node'
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
const textarea = ref("");
const form = reactive({
	name: "",
	region: "",
	date1: "",
	date2: "",
	delivery: false,
	type: [],
	resource: "",
	desc: ""
});

const showUser = ref(false)

let count = 1

interface Tree {
	name: string
}

const props = {
	label: 'name',
	children: 'zones',
}

const handleCheckChange = (
	data: Tree,
	checked: boolean,
	indeterminate: boolean
) => {
	console.log(data, checked, indeterminate)
}

const loadNode = (node: Node, resolve: (data: Tree[]) => void) => {
	if (node.level === 0) {
		return resolve([{ name: '全选' }, { name: '全选' }])
	}
	if (node.level > 3) return resolve([])

	let hasChild = false
	if (node.data.name === 'region1') {
		hasChild = true
	} else if (node.data.name === 'region2') {
		hasChild = false
	} else {
		hasChild = Math.random() > 0.5
	}

	setTimeout(() => {
		let data: Tree[] = []
		if (hasChild) {
			data = [
				{
					name: `zone${count++}`,
				},
				{
					name: `zone${count++}`,
				},
			]
		} else {
			data = []
		}

		resolve(data)
	}, 500)
}
</script>
<style>
.cl-dialog--large.el-dialog .el-dialog__header {
	padding: 16px 32px;
	border-bottom: 1px solid #e8eaec;
}

.el-dialog .el-dialog__header {
	box-sizing: content-box;
	height: 18px;
	padding: 24px 32px 14px;
	font-size: 18px;
	font-weight: 700;
	line-height: 18px;
	border-bottom: 1px solid #e8eaec;
}

.el-dialog__header {
	padding: 20px 20px 10px;
}

.cl-dialog--large.el-dialog .el-dialog__header {
	padding: 16px 32px;
	border-bottom: 1px solid #e8eaec;
}

.el-dialog .el-dialog__header {
	box-sizing: content-box;
	height: 18px;
	padding: 24px 32px 14px;
	font-size: 18px;
	font-weight: 700;
	line-height: 18px;
	border-bottom: 1px solid #e8eaec;
}

.el-dialog__header {
	padding: 20px 20px 10px;
}
.mt16 {
	margin-top: 16px;
}
.cascader-container.right {
	width: 200px;
}
.cascader-container.left {
	width: 400px;
	margin-right: 16px;
}
.cascader-container {
	display: inline-block;
	vertical-align: top;
	background-color: #fff;
	border: 1px solid #dee4f5;
}
.cascader-title {
	height: 40px;
	padding: 0 12px;
	font-size: 14px;
	line-height: 40px;
	color: #333;
	background-color: #fafafa;
	border-bottom: 1px solid #dee4f5;
}
.cascader-list {
	width: 100%;
	height: 236px;
	overflow: auto;
	font-size: 14px;
}

.tab-label{
	display: inline-block;
	margin: 10px;
	height: 40px;
	line-height: 20px;
}
.action{
	color:blue;
	height: 20px;
	border-bottom:1px solid blue
}
.member-parent .member-left {
	box-sizing: border-box;
	width: 200px;
	height: 100%;
	padding-top: 8px;
	padding-right: 10px;
	padding-left: 10px;
	overflow: auto;
}
.member-parent .member-right {
	flex: 1;
	height: 100%;
	width: 200px;
	padding-top: 8px;
	padding-right: 10px;
	padding-left: 10px;
	overflow: auto;
	border-left: 1px solid #dee4f5;
}
.member-parent{
	overflow:hidden;
	height: 100%;
	width: 100%;
}
.member-right-text{
	margin-left: 25px;
	width: 100px;
	float:left;
	padding: 15px;
	box-sizing: border-box;
	overflow: auto;
	height: 100%;
}
.cascader-list {
	display: flex;
	overflow: hidden; /* 隐藏溢出内容 */
}

.member-parent {
	display: flex;
	width: 100%;
}

.member-left {
	flex: 1;
	overflow-y: hidden; /* 隐藏左侧元素的垂直滚动条 */
}

.member-right {
	margin-left: 10px; /* 调整右侧元素与左侧元素之间的间距 */
}


</style>
相关推荐
天下无贼!19 分钟前
2024年最新版TypeScript学习笔记——泛型、接口、枚举、自定义类型等知识点
前端·javascript·vue.js·笔记·学习·typescript·html
计算机学姐1 小时前
基于SpringBoot+Vue的篮球馆会员信息管理系统
java·vue.js·spring boot·后端·mysql·spring·mybatis
小白小白从不日白1 小时前
react 高阶组件
前端·javascript·react.js
程序员大金1 小时前
基于SpringBoot+Vue+MySQL的智能物流管理系统
java·javascript·vue.js·spring boot·后端·mysql·mybatis
徐同保2 小时前
vue 在线预览word和excel
vue.js·word·excel
乐~~~3 小时前
el-tabs 自适应高度
elementui·scss
LJ小番茄3 小时前
Vue 常见的几种通信方式(总结)
前端·javascript·vue.js·html
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS在线文档管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
pan_junbiao6 小时前
Vue组件:模板引用ref属性的使用
前端·javascript·vue.js