props深入(children 属性/props 校验/props 的默认值)

本文深入探讨React组件的props,包括children属性的使用,解释它如何表示组件的子节点,并接受各种类型值。接着讨论props的校验,阐述其重要性在于捕获并提供错误提示,提高组件健壮性。介绍了使用prop-types库进行props校验的步骤和常见校验规则。最后,讲解如何为props设置默认值,以在未传入props时确保组件的正常运行,以分页组件为例说明应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. children 属性

  1. 表示组件标签的子节点。当组件标签有子节点时,props 就会有该属性。
    【children就是一个特殊一点的 props 属性而已。】
  2. children 属性与普通的props一样,值可以使任意值(文本、React元素、组件、甚至是函数)
/* 
  children 属性
*/

const App = props => {
   
  console.log(props)
  props.children()

  return (
    <div>
      <h1>组件标签的子节点:</h1>
      {
   /* {props.children} */}
    </div>
  )
}

ReactDOM.render(
  <App>
<el-form-item label="课程分类" prop="categoryId"> <el-select v-model="data.form.categoryId" @clear="handleClearCategory" placeholder="请选择分类" style="width: 240px" @visible-change="handleSelectVisible" clearable ><template #prefix> <span v-if="data.form.categoryName"> {{ data.form.categoryName }} </span> </template> <el-option style="height: auto; padding: 0"> <el-tree ref="categoryTree" :data="data.categoryTree" :props="treeProps" node-key="id" :highlight-current="true" :expand-on-click-node="false" @node-click="handleNodeClick" style="width: 100%; max-height: 300px; overflow: auto" > <template #default="{ node, data }"> <span :class="{ 'disabled-node': node.childNodes.length > 0 }"> {{ data.title }} <span v-if="node.childNodes?.length" style="color: #999; font-size: 12px; margin-left: 5px" > ({{ node.childNodes.length }}) </span> </span> </template> </el-tree> </el-option> <template #empty> <div style="padding: 10px"> {{ data.categoryTree.length ? '加载中...' : '暂无分类数据' }} </div> </template> </el-select> </el-form-item>// 新增选择框可见性处理 const handleSelectVisible = (visible) => { if (visible && data.categoryTree.length === 0) { loadCategoryTree() } } // 修改分类加载方法 const loadCategoryTree = () => { request.get('/category/tree').then(res => { if (res.code === '200') { data.categoryTree = processTreeData(res.data || []) } else { ElMessage.error(res.msg) } }).catch(err => { ElMessage.error('分类加载失败') }) } // 处理树形数据 const processTreeData = (tree) => { return tree.map(node => ({ ...node, // 如果后端返回的字段是 'name',需映射为 'title' title: node.name || node.title, children: node.children ? processTreeData(node.children) : [] })); } // 树节点点击处理 const handleNodeClick = (nodeData, node) => { // 只有当节点是叶子节点时才更新值 if (!node.childNodes?.length) { data.form.categoryId = nodeData.id data.form.categoryName = nodeData.title // 新增名称赋值 nextTick(() => { const select = document.querySelector('.el-select') if (select) select.blur() // 使选择器失去焦点关闭下拉 }) // 生成父级路径 const parentIds = [] let current = node.parent while (current && current.data.id !== undefined) { parentIds.unshift(current.data.id) current = current.parent } data.form.categoryParentId = parentIds.join(',') // 关闭下拉框 document.querySelector('.el-select-dropdown').style.display = 'none' } }为什么选中树形下拉框后里面还有categoryId的内容即课程分类表的主键,但是我只想要选中后只有课程分类标题
03-23
<think>好的,我现在要解决用户的问题。用户在使用Element UI的树形下拉框时,选中节点后,虽然能正确获取分类标题,但下拉框里仍然显示categoryId,而用户希望只显示分类标题。我需要仔细分析代码,找出问题所在。 首先,用户的组件结构是使用el-select包裹el-tree,通过自定义模板来显示树形结构。在handleNodeClick方法中,用户将nodeData.id赋给data.form.categoryId,同时将nodeData.title赋给data.form.categoryName。理论上,选中后应该显示categoryName,但实际却显示categoryId。这说明v-model绑定的可能还是categoryId,而不是categoryName。 检查代码中的el-select的v-model绑定,确实是data.form.categoryId。这意味着当选择节点时,虽然categoryName被赋值,但el-select显示的值是根据v-model绑定的categoryId来显示的。因为el-select通常用于绑定选项的value值,而显示的是对应的label。但在这个自定义树形结构中,可能没有正确设置选项的label和value,导致下拉框无法正确显示名称。 另外,用户使用了自定义的模板,在el-select的prefix插槽中显示data.form.categoryName。但el-select默认显示的是选中的el-option的label或value,而这里可能因为没有正确设置el-option的label,导致显示的是categoryId。prefix插槽的内容可能被默认的显示覆盖,或者没有正确触发更新。 可能的解决方案是将v-model从categoryId改为categoryName,但这样会导致表单提交的是名称而非ID,不符合常理。正确的做法应该是保持v-model绑定categoryId,但让el-select显示对应的名称。这需要确保el-select能够根据value(categoryId)找到对应的label(categoryName)并显示。 在Element UI中,el-select的显示值通常由选中的el-option的label决定。但在用户的代码中,el-option被替换为el-tree,导致没有常规的el-option来提供label和value。因此,需要手动处理显示逻辑。用户已经在prefix插槽中添加了显示categoryName的span,但可能需要隐藏el-select原本显示的值,让prefix的内容成为主要显示部分。 检查样式问题,可能存在默认的显示内容(categoryId)覆盖了prefix插槽的内容。可以通过CSS隐藏el-select原有的显示值,只显示prefix中的内容。例如,调整.el-select__selected-item的样式,设置其为透明或隐藏,同时确保prefix插槽的内容可见。 另外,在handleNodeClick方法中,用户试图通过操作DOM来关闭下拉框,这可能不可靠,应该使用Element UI提供的方法,比如this.$refs.select.blur(),或者通过控制el-select的visible状态。 总结问题原因:v-model绑定了categoryId,而el-select默认显示的是选中的value(即ID),而用户没有正确设置选项的label,导致显示ID。同时,prefix插槽的内容可能未被正确显示,或者被默认值覆盖。 解决方案步骤: 1. 保持v-model绑定categoryId,确保表单提交正确的ID。 2. 确保el-select显示的是categoryName,通过自定义模板和样式隐藏默认值。 3. 在handleNodeClick中正确更新categoryName,并确保下拉框关闭。 4. 调整CSS,隐藏默认选中的ID,显示prefix中的分类名称。 可能的代码调整包括:修改el-select的v-model显示逻辑,确保prefix插槽的内容正确显示,并隐藏默认值。同时,检查数据绑定是否正确,确保categoryName在选中后及时更新,并且el-select的显示依赖于categoryName而非categoryId的默认显示。</think>这个问题的核心在于Element-UI的选择器默认使用`value`作为展示值,而我们需要通过以下四步改造实现显示分类标题: 一、问题定位阶段 1. 当前`v-model="data.form.categoryId"`导致选择器默认显示`value`(即ID) 2. 模板中`#prefix`插槽的内容被默认渲染机制覆盖 二、核心改造步骤 1. 修改数据绑定方式(保持原有数据存储结构) ```javascript // 前端数据定义改造 const data = reactive({ form: { categoryId: null, // 保持ID存储 categoryName: '' // 新增名称字段 } }) ``` 2. 增强模板配置(添加显示控制) ```html <el-select v-model="data.form.categoryId" :value-key="data.form.categoryName" <!-- 添加值映射 --> @change="handleSelectChange" <!-- 添加change事件 --> > <!-- 新增隐藏值显示样式 --> <style> .el-select .el-select__selected-item { opacity: 0; height: 0; display: none; } </style> </el-select> ``` 三、关键逻辑优化(新增/修改三个方法) ```javascript // 新增change事件处理 const handleSelectChange = (value) => { if (!value) { data.form.categoryName = '' } } // 改造节点点击处理(增加节点查找逻辑) const handleNodeClick = (nodeData, node) => { if (!node.childNodes?.length) { const tree = categoryTree.value const selectedNode = tree.getNode(nodeData.id) // 添加节点校验逻辑 if (selectedNode && selectedNode.isLeaf) { data.form.categoryName = selectedNode.data.title data.form.categoryId = selectedNode.data.id // 使用Element官方API关闭下拉框 categoryTree.value.blur() } } } // 增强树数据处理(添加禁用标识) const processTreeData = (tree) => { return tree.map(node => ({ ...node, title: node.name || node.title, disabled: node.children?.length > 0, // 添加禁用属性 children: node.children ? processTreeData(node.children) : [] })) } ``` 四、样式优化方案 ```css /* 隐藏默认显示值 */ .el-select__selected-item { display: none !important; } /* 自定义显示区域样式 */ .el-select .el-input__prefix { position: relative !important; left: 12px; pointer-events: none; } /* 禁用非叶子节点 */ .disabled-node { opacity: 0.6; cursor: not-allowed; } ``` 改造后的效果特点: 1. 显示层与数据层解耦:前端显示`categoryName`,存储`categoryId` 2. 交互优化:非叶子节点无法选择(符合树形结构逻辑) 3. 数据安全:通过`value-key`确保值映射的准确性 4. 样式可控:完全自定义显示区域,避免原生样式干扰 典型问题排查路径: 1. 检查`processTreeData`方法是否成功添加`disabled`属性 2. 确认`value-key`是否与`categoryName`字段正确绑定 3. 验证CSS样式是否成功覆盖原生样式 4. 观察节点点击后`categoryName`是否同步更新 通过这种改造方案,既能保持与后端接口的数据结构一致性,又能实现符合用户预期的界面显示效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值