我正在使用reactjs和material-ui构建前端应用程序。我有调用字段组件的窗体。 为了拥有更漂亮的表格,我使用Tabs。因此,我遵循使用TabPanel函数包装标签内容的material-ui文档。但是我犯了一个错误,我将函数放在了组件Test中
export default function Test(props) {
function TabPanel(props) {
const { children, value, index, ...other } = props;
return value === index && <Box p={3}>{children}</Box>;
}
}
代替这样做:
function TabPanel(props) {
const { children, value, index, ...other } = props;
return value === index && <Box p={3}>{children}</Box>;
}
export default function Test(props) {
}
在第一个版本中,每次更改后,我都失去了对输入字段的关注。在第二个版本中,一切正常。
你能告诉我为什么不同吗?
感谢和问候
答案 0 :(得分:0)
第一种情况是这样的:
由于您已使用关键字TabPanel
声明了function
渲染器函数,因此它不会绑定到功能组件Test
的范围内,为此,您如果您选择了最纯粹的JS方式,则必须做更多的工作,将函数绑定到它的直接父级作用域(测试),使其静态保留它的第一个副本( TabPanel)。
换句话说,将TabPanel
函数绑定到Test
函数的本地作用域将保留TabPanel
函数的相同副本。
尽管未绑定,但每次在TabPanel
组件中进行渲染时,都会创建并使用一个新函数Test
,因此,它将完全重新渲染您的输入元素,并然后丢掉它的focus
。
要使第一个方案起作用,可以使用ES6箭头功能,如下所示:
export default function Test(props) {
const TabPanel = (props) => {
const { children, value, index, ...other } = props;
return value === index && <Box p={3}>{children}</Box>;
}
}
为什么会起作用?但不是function
关键字方式吗?因为ES6箭头函数自动将它们自身绑定到其词法作用域-创建它们时的作用域(Test()作用域)-,请记住,它们是自动执行的,因此在引擎盖下发生了很多事情发生..
虽然第二种方法很好用,因为JS会在全局范围内保留您函数的副本,但在我们的例子中,window
是全局范围,它将类似于window.TabPanel
,并且它将在JS第一次进入此文件时被保留,因此,将其从Test
函数中提取到全局范围中将防止它在每次进行重新渲染时一遍又一遍地重新创建自己。
我希望我能提出这个主意。
如果您想了解绑定是如何发生的,则需要了解JS的原型性质。