惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
SecWiki News
SecWiki News
酷 壳 – CoolShell
酷 壳 – CoolShell
爱范儿
爱范儿
量子位
M
MIT News - Artificial intelligence
GbyAI
GbyAI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
TaoSecurity Blog
TaoSecurity Blog
博客园 - 【当耐特】
H
Heimdal Security Blog
腾讯CDC
The Last Watchdog
The Last Watchdog
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News: Ask HN
Hacker News: Ask HN
S
Schneier on Security
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
博客园 - 司徒正美
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
Cybersecurity and Infrastructure Security Agency CISA
S
SegmentFault 最新的问题
大猫的无限游戏
大猫的无限游戏
Application and Cybersecurity Blog
Application and Cybersecurity Blog
F
Full Disclosure
有赞技术团队
有赞技术团队
T
Tailwind CSS Blog
Engineering at Meta
Engineering at Meta
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Threatpost
月光博客
月光博客
A
Arctic Wolf
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
雷峰网
雷峰网
T
Troy Hunt's Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
D
DataBreaches.Net
O
OpenAI News
L
LINUX DO - 最新话题
宝玉的分享
宝玉的分享
小众软件
小众软件
V
Vulnerabilities – Threatpost
A
About on SuperTechFans
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
Martin Fowler
Martin Fowler
美团技术团队
P
Privacy International News Feed

博客园 - 码农张3

MySQL创建用户且只能访问指定数据库表 自定义跨字段校验必填注解 Element Plus SCSS 变量覆盖用法 leaflet-canvasmarker添加的marker旋转问题 SpringBoot项目控制台打印sql设置 Windows 远程桌面复制粘贴突然无效 SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。 右键用vscode打开文件夹 nodemon: 无法加载文件 C:\DevSoft\nodejs\node_global\nodemon.ps1 - 码农张3 EasyUI Datagrid添加右键导出菜单并导出数据 个人所得税App住房贷款利息解读 JavaScript学习笔记—DOM:操作class JavaScript学习笔记—DOM:通过属性读取样式 SQLServer数据库导出指定表里所有数据成insert语句 解决Mybatis xml文件中执行mysql语句时,语句后携带分号实现多语句执行报异常问题 JS去除字符串前面所有0 Redis启动服务报错:服务没有及时响应启动或者控制请求 JavaScript学习笔记—DOM:元素的添加、修改、删除 JavaScript学习笔记—全选、取消、反选、提交 JavaScript学习笔记—DOM:事件 JavaScript学习笔记—DOM:属性节点
Vue3 父组件引用子组件并控制子组件显隐及数据传递
码农张3 · 2026-06-16 · via 博客园 - 码农张3

子组件 UserFormDialog.vue

<!-- 用户新增和修改组件 -->
<template>
  <!-- 弹窗 -->
  <el-dialog v-model="visible" :title="title" width="60%" @close="handleClose">
    <el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="80px">      
      ......
    </el-form>

    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" :loading="loading" @click="handleSubmit">确 定</el-button>
        <el-button @click="handleClose">取 消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import {ref, reactive, watch, nextTick} from 'vue'
import { ElMessage } from 'element-plus'

// 1.使用 Vue 3.4+ 的 defineModel 定义了一个名为 visible 的双向绑定变量。父组件通过 v-model 传入该值,子组件修改它会自动同步到父组件,常用于控制弹窗显示/隐藏
const visible = defineModel({
  type: Boolean,
  default: false
})

// 定义属性
const props = defineProps({
  // 弹窗类型 add: 新增 edit: 修改
  title: {
    type: String,
    default: ''
  },
  // 表单数据
  initData: {
    type: Object,
    default: () => ({})
  }
})

// 2.定义事件
const emit = defineEmits(['success'])

const loading = ref(false)
const dataFormRef = ref()

// 本地表单数据(用于双向绑定和验证)
const formData = reactive({});

// 表单校验
const rules = {
  ......
};
// 监听外部传入的显示状态,当 visible 为 true 时填充表单数据
watch(visible, (val) => {
  if (val) {
    // 打开时填充表单数据
    nextTick(() => {
      Object.assign(formData, props.initData || {})
      dataFormRef.value.clearValidate()
    })
  }
})

// 关闭弹窗
const handleClose = () => {
  visible.value = false
}

// 提交表单
const handleSubmit = () => {
  dataFormRef.value.validate(async (valid) => {
    if (valid) {
      try {
        loading.value = true;
        const submitData = {...formData}
        // 新增或修改
        if (submitData.userId) {
          await UserAPI.update(submitData)
          ElMessage.success("修改成功");
        } else {
          await UserAPI.add(submitData)
          ElMessage.success("新增成功");
        }
        // 3.通知父组件刷新列表
        emit('success') 
        handleClose();
      } catch (error) {
        ElMessage.error(error?.message || '操作失败');
      } finally {
        loading.value = false;
      }
    }
  });
}
</script>

<style lang="scss" scoped>

</style>

父组件 index.vue

<template>
  <div class="app-container-row">
    <el-button type="success" icon="plus" @click="handleAddOrUpdate(undefined)">新增</el-button>
    <!-- 1.子组件 
        v-model="dialog.visible"  对应子组件的 const visible = defineModel({type: Boolean,  default: false})
        @success="handleQuery"    对应子组件的 const emit = defineEmits(['success']); emit('success') 
	-->
    <UserFormDialog
        v-model="dialog.visible"
        :title="dialog.title"
        :init-data="initFormData"
        @success="handleQuery"
    />
  </div>
</template>

<script setup>
import {onMounted, reactive, ref, toRaw} from 'vue'
import UserFormDialog from "@/views/system/user/UserFormDialog.vue";

/**
 * 定义组件名称:在调试工具(如 Vue DevTools)中会显示为组件名称,便于识别和调试
 * 支持<keep-alive>缓存
 */
defineOptions({
  name: 'User'
})

//==============用户表单=================
// 2.初始化子组件标题和显隐
const dialog = reactive({
  title: "",
  visible: false,
});

const defaultFormData = {
  userId: undefined,
  loginName: '',
  nickName: '',
  gender: 1,
  deptId: undefined,
  phone: '',
  email: '',
  remark: ''
}

const initFormData = reactive({ ...defaultFormData })

// 新增或修改页面
function handleAddOrUpdate(rowData) {
  ......
  dialog.visible = true;
}
    
// 查询
function handleQuery() {
  
}
</script>

<style lang="scss" scoped>

</style>