请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于父子组件通讯, 以及ref的问题.

有这么一个场景, 一个页面的表单量很大, 所以, 我会倾向于, 将一整个大表单, 拆分成, 多个小表单, 每个表单作为一个组件, 每个表单组件的数据更改和校验逻辑都由各个组件自己处理.
在父组件(页面组件中)给每个小的组件添加ref, 提交的时候, 通过 this.refs[组件ref].func 完成校验, 校验通过后, 将子组件的state返回给父组件, 然后, 完成数据聚合.

父组件代码

import React, { Component } from 'react'
import TestComponent from '../components/TestComponent'

class MyTest extends Component {
	handleClick = (event) => { // 点击按钮, 获取表单组件的数据
		let data = this.refs.form.sendFormData()
		console.log('子组件表单数据:', data)
	} 
	render() {
		return (
			<div>
				<h1>测试页面</h1>
				<button onClick={this.handleClick}>获取表单数据</button>
				<TestComponent ref="form" />
			</div>
		)
	}
}

export default MyTest

子组件代码

import React, { Component } from 'react'

class TestComponent extends Component {
	constructor(props) {
		super(props)
		this.state = {
			name: '巴拉巴拉巴拉',
			age: 19,
		}
	}
	sendFormData = () => { // 让父组件调用, 将这里的state传递出去
		return this.state
	}
	render() {
		return (
			<div>假装是一个表单</div>
		)
	}
}

export default TestComponent

这是我的做法, 但是, 我看文档.

React支持一个可以附加到任何组件的特殊属性ref。ref属性可以是一个字符串或一个回调函数。当ref属性是一个回调函数时,函数接收底层DOM元素或类实例(取决于元素的类型)作为参数。这使你可以直接访问DOM元素或组件实例。
不要过度使用 Refs。如果你发现自己经常在应用程序中使用refs来“搞事情”,请考虑使用状态提升。

这让我很困惑, 不知道怎么做才好, 如果通过状态提升, 将整个表单数据放在父组件中管理, 那么, 数据太多, 不易维护, 我工作中的项目, 一个表单, 都是需要用户自己填写几十条信息的, 而且, 在初始化的时候, 需要自动给表单设置默认值, 这样下来, 父组件这块代码会非常的多, 还要考虑复用, 所以, 我还是倾向于讲大表单拆分成多个组件.

问题1: 为什么, 官方说尽量不要使用ref.
问题2: 如果是老师, 碰到, 这种动辄几十个表单元素的页面会怎么处理, 还有可能是分步表单(后台接口是一次性接受你所有的数据的, 所以, 每一步的表单都要自己保存好, 最后, 数据聚合好一起提交给后台).

正在回答

1回答

同学你好 你思考的方式非常棒 我会尽量解答你的问题

问题1: 使用 ref 管理数据流违背 React 的根本理念,React 核心理念是尽量不和 DOM 打交道,更新界面的唯一方法是使用 setState,ref 像是一个后门一样,可以偷偷的取得 DOM 节点,然后做事情,所以它建议使用 ref 的时候是做一些 DOM 节点应该做的事情,比如调用 focus 等等这些方法。


问题2: 我刚好做了一个类似的需求,我做了 70多个表单元素,你把这些 表单元素抽象成了 数据结构,就是一个大的 object,然后这些 object 的项里面就是这些表单选项,你可以定义他们的类型,属性等等,而且每个项里面还能定义各自的关系,然后我把这个大的 object 抽象成了 Redux 的 store,这样整个  store,action和 reducer 都可以单独测试的,这些数据的变化完全是可预测的,而且可以整体取出你想要的目前所有表单的值,显示的时候你不需要每次重复要手写的各种组件,只需要循环显示这个数据结构就可以了。 我给你贴一张当时我做的流程吧,你可以简单研究一下。

https://img1.sycdn.imooc.com//szimg/5c53d4ec0001634221521306.jpg


写了这么多,希望能帮助到你,学完课以后给个好评把,哈哈

1 回复 有任何疑惑可以回复我~
  • 提问者 iunicorn49 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2019-02-02 17:22:45
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信