我真的没有区分反应路由器中的路由器中的渲染和组件道具,在文档中它表示渲染不会创建新元素但组件确实如此,我试图回溯历史但我发现当我调用componentWillMount时在Route中使用render,它们是什么意思“如果你为组件属性提供内联函数,你将在每次渲染时创建一个新组件 . 这会导致现有组件卸载和新组件安装,而不仅仅是更新现有组件“ .
The source code说明不同之处:
if (component) return match ? React.createElement(component, props) : null if (render) return match ? render(props) : null
当您使用 component prop时,每次调用 Route#render 时都会实例化该组件 . 这意味着,对于传递给Route的 component prop的组件,构造函数, componentWillMount 和 componentDidMount 将在每次呈现路径时执行 .
component
Route#render
componentWillMount
componentDidMount
例如,如果你有
<Route path="/:locale/store" component={Store} />
并且用户导航到/ en / store,然后转到其他地方,然后导航回/ en / store,Store组件将被挂载,然后卸载,然后再次挂载 . 它类似于做
<Route path="/:locale/store"> <Store /> </Route>
与此相比,如果使用 render prop,则会在每个 Route#render 上评估该组件 . 请记住,每个组件都是一个功能?此函数将按原样执行,无需任何生命周期方法 . 所以当你拥有它时
render
<Route path="/:locale/store" render={Store} />
你可以把它想象成
<Route path="/:locale/store"> {Store()} </Route>
它可以节省您的运行时间,因为没有运行生命周期方法,但它也有一个缺点,Store Store组件有一些post-mount生命周期方法,如shouldComponentUpdate,也可以提高性能 .
有a good post on Medium about this performance hack,请看一下 . 它编写得非常好,也适用于React 16 .
所以我对这部分文档感到困惑,但我终于明白了 .
理解这一点的关键是声明“ provide an inline function to the component prop ”
我们都知道Route组件会在位置发生变化时重新渲染,并且react会比较旧的和新的虚拟DOM树,得到一些diff结果并应用于真正的DOM .
并且react会尝试最好重用DOM节点,除非新的ReactElement的 type 或 key prop被更改 .
所以
// 1. const componentA = React.createElement(App, props) const componentB = React.createElement(App, props) console.log(componentA.type === componentB.type) // true // 2. const componentA = React.createElement(() => <App />, props) const componentB = React.createElement(() => <App />, props) console.log(componentA.type === componentB.type) // false
通过方式1创建的所有ReactElements都具有相同的类型(App组件),但如果它们都是通过方式2创建的,则它们不具有相同的类型 .
为什么?
因为当父组件(包含Route组件的组件)render方法被调用时,总是会以2的方式创建一个新的匿名函数,所以 type of new&old ReactElement 是匿名函数的两个不同实例
() => <App />
所以在React的观点中,有不同的类型元素,应该用 unmount old > mount new 操作来处理,这意味着每次重新呈现父组件时,每个状态或对旧组件所做的更改都会丢失 .
但为什么渲染道具避免了卸载和挂载行为?这也是一个匿名函数!?
在这里,我想引用@Rishat Muhametshin发布的代码,这是Route组件的render方法的核心部分:
if (component) // We already know the differences: // React.createElement(component) // React.createElement(() => <component/>) return match ? React.createElement(component, props) : null if (render) return match ? render(props) : null
render prop是一个在调用时返回ReactElement的函数,返回元素的类型是什么?
<Route render={() => <AppComponent />}></Route>
它是AppComponent,而不是匿名函数包装器!因为在jsx编译之后:
render = () => React.createElement(AppComponent) render() = React.createElement(AppComponent) React.createElement(render) = React.createElement(() => React.createElement(AppComponent)) React.createElement(render()) = React.createElement(React.createElement(AppComponent))
所以当你使用render而不是组件prop时, render prop 函数返回的元素类型在每次渲染时都不会改变,即使总是在每个parentElement.render()上创建一个新的匿名函数实例
在我看来,你可以通过给匿名函数命名来存档渲染道具与组件道具相同的行为:
// Put this line outside render method. const CreateAppComponent = () => <AppComponent /> // Inside render method render(){ return <Route component={CreateAppComponent}/> }
所以结论是,如果你直接使用component = ,那么组件和渲染道具之间的性能不同,如果你想为AppComponent分配一些道具,请使用 render={() => <AppComponent {...props}/> } 而不是 component={() => <AppComponent {...props}/> }
render={() => <AppComponent {...props}/> }
component={() => <AppComponent {...props}/> }
2 回答
The source code说明不同之处:
当您使用
component
prop时,每次调用Route#render
时都会实例化该组件 . 这意味着,对于传递给Route的component
prop的组件,构造函数,componentWillMount
和componentDidMount
将在每次呈现路径时执行 .例如,如果你有
并且用户导航到/ en / store,然后转到其他地方,然后导航回/ en / store,Store组件将被挂载,然后卸载,然后再次挂载 . 它类似于做
与此相比,如果使用
render
prop,则会在每个Route#render
上评估该组件 . 请记住,每个组件都是一个功能?此函数将按原样执行,无需任何生命周期方法 . 所以当你拥有它时你可以把它想象成
它可以节省您的运行时间,因为没有运行生命周期方法,但它也有一个缺点,Store Store组件有一些post-mount生命周期方法,如shouldComponentUpdate,也可以提高性能 .
有a good post on Medium about this performance hack,请看一下 . 它编写得非常好,也适用于React 16 .
所以我对这部分文档感到困惑,但我终于明白了 .
理解这一点的关键是声明“ provide an inline function to the component prop ”
我们都知道Route组件会在位置发生变化时重新渲染,并且react会比较旧的和新的虚拟DOM树,得到一些diff结果并应用于真正的DOM .
并且react会尝试最好重用DOM节点,除非新的ReactElement的 type 或 key prop被更改 .
所以
通过方式1创建的所有ReactElements都具有相同的类型(App组件),但如果它们都是通过方式2创建的,则它们不具有相同的类型 .
为什么?
因为当父组件(包含Route组件的组件)render方法被调用时,总是会以2的方式创建一个新的匿名函数,所以 type of new&old ReactElement 是匿名函数的两个不同实例
所以在React的观点中,有不同的类型元素,应该用 unmount old > mount new 操作来处理,这意味着每次重新呈现父组件时,每个状态或对旧组件所做的更改都会丢失 .
但为什么渲染道具避免了卸载和挂载行为?这也是一个匿名函数!?
在这里,我想引用@Rishat Muhametshin发布的代码,这是Route组件的render方法的核心部分:
render prop是一个在调用时返回ReactElement的函数,返回元素的类型是什么?
它是AppComponent,而不是匿名函数包装器!因为在jsx编译之后:
所以当你使用render而不是组件prop时, render prop 函数返回的元素类型在每次渲染时都不会改变,即使总是在每个parentElement.render()上创建一个新的匿名函数实例
在我看来,你可以通过给匿名函数命名来存档渲染道具与组件道具相同的行为:
所以结论是,如果你直接使用component = ,那么组件和渲染道具之间的性能不同,如果你想为AppComponent分配一些道具,请使用
render={() => <AppComponent {...props}/> }
而不是component={() => <AppComponent {...props}/> }