【问题标题】:Creating Custom Components and Nesting them创建自定义组件并嵌套它们
【发布时间】:2017-02-03 04:38:47
【问题描述】:

我有兴趣在我的 React 应用程序中执行以下操作,即创建我的自定义组件并将它们嵌套在 return 语句中:

例如:

render(){
    return(
        <ShoppingApp>
            <Products>
                <ProductDetail productID={product_id} />
            </Products>
        </ShoppingApp>
    );
}

问题:

  1. 以上使用 ReactJS 是否可行/可行?

  2. 如果对 1 的回答是肯定的,那么可以使用这种结构/好处的实际场景是什么(一个例子有助于理解)

  3. 如何用自定义组件实现这种嵌套?

PS:我已经知道我们可以在 JSX 中将组件包含在 div、table 中的语法。 . . ,但这里的问题是如何在层次结构中实现嵌套自定义组件(如上所述)。

提前致谢。

【问题讨论】:

    标签: javascript reactjs react-jsx


    【解决方案1】:

    如果我正确理解您的问题,您正在寻找类似 @​​987654322@ React 传递给每个组件的特殊道具(来自文档)

    这特别适用于您不知道组件的子项将提前做什么的情况。

    在你的情况下,这可以大致如下实现 -

     class Products extends React.Component {
       render() {
         /* this.props.children here will be an array of all 
          * the children which can be custom components
          * enclosed within the <Products> component 
          * when it is rendered 
          */
         return (
           <div className='products'> 
             {this.props.children}
           </div>
         )
       }
     }
    

    在实际场景中,如果您想将 ProductDetail 组件嵌套在 Products 组件内,因为您希望 Products 以某种方式将一些 prop 传递给它包含的每个 ProductDetail,您可以使用React.Children (docs) 提供的各种有据可查的实用程序

    所以一个实际的例子如下 -

     class Products extends React.Component {
       getTransformedChildren() {
         return React.Children.map(this.props.children, child => {
           // if child is of type ProductsDetail, clone it so you can 
           // pass your own prop to it else return the child
           const newChild = (child.type === ProductsDetail) ? 
             React.cloneElement(child, { category: this.props.category }) :
             child
           return newChild
       }
       render() {
         return (
           <div className='products'> 
             {this.getTransformedChildren()}
           </div>
         )
       }
     }
    

    所以你的渲染语句如下所示:

    <Products category='groceries'>
       <ProductDetails id='1' />
       <ProductDetails id='2' />
       <HelloWorld />
    </Products>
    

    在这种情况下,所有内部 ProductDetails 子级将有一个属性 categories 设置为 groceries。但是,内部的HelloWorld 组件不会被传递categories 属性,因为它不是ProductDetails 类型。

    使用此范例的另一个实际应用是,如果您希望父自定义组件将内联样式传递给它的全部或部分子组件,并且如果您正在编写自己的库,这将非常有用。

    【讨论】:

      【解决方案2】:

      是的,上述结构是可能的。在这里,您将ProductDetail 作为Products 组件的子级传递,然后将Products 作为ShoppingApp 的子级传递。

      当您拥有通用且可重用的组件时,这种情况很有帮助。假设ShoppingApp有10个Products,每个ProductsProductDetails,在这种情况下你可以使用ProductsProductDetailcomponents 10次,通过使用循环你可以创建10个ProductsProductDetail 组件。由于所有Products 都将具有相同的属性,例如名称、价格等,因此您可以轻松编写可重用的组件并将组件内的数据作为道具传递。

      像这样:

      _createProductList(){
          let products = this.state.products;
          return products.map((product,i)=>{
              return <Products key={i} data={product}>
                         <ProductDetail data={product}>
                         </ProductDetail>
                     </Products>
          })
      }
      
      <ShoppingApp>
          {this._createProductList()}
      </ShoppingApp>
      

      但是在场景中你可以让它更通用,因为ProductDetailProduct的属性,所以你可以直接在Product中使用ProductDetail而不是像这样使用:

      _createProductList(){
          let products = this.state.products;
          return products.map((product,i)=>{
              return <Products key={i} data={product}/>
          })
      }
      
      <ShoppingApp>
          {this._createProductList()}
      </ShoppingApp>
      

      Products 内部,在渲染中使用ProductDetails。无需将其作为Product 的子级传递。

      希望它能帮助你理解:)

      【讨论】:

        猜你喜欢
        • 2011-03-31
        • 1970-01-01
        • 2017-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-03
        • 1970-01-01
        • 2017-08-14
        相关资源
        最近更新 更多