是否可以创建为父组件提供配置的子节点
Is it possible to create children nodes that provide configuration to the parent component?
我希望这样做的场景是创建一个通用的数据网格组件。我想使用子元素来定义网格的列,但是我不希望这些子元素进行渲染,因为渲染逻辑被抽象为网格结构的表示(下面的视图属性)
。
<MyDataGrid data={myData} view={myTableView}>
<MyCol fieldName='asdf' sortable />
</MyDataGrid>
因为列向网格提供呈现信息,所以它们需要在网格的呈现函数中可以访问,而不需要首先呈现它们自己。从我可以告诉这是不可能的,我目前只是通过列配置作为支柱在网格上。这个策略很有效,但肯定不是最好看的策略。
我知道你可以构建可以使用的内在元素,但我认为React仍然希望将它们作为DOM节点进行管理。我想要的是react忽略我组件的子元素的DOM,让我逐字解析子元素(即作为MyCol { fieldName: string, sortable: boolean }
的数组)。
这可能吗?计划在路线图上吗?甚至考虑过吗?
我知道这是一个有点奇怪的问题,我很高兴继续使用我到目前为止所采用的策略。但是如果可以选择创建这些无渲染的"哑"节点就更好了。
当然!看一看React Router中这种配置风格的例子。也就是说,我认为它更适合嵌套的东西(如路由配置);否则,我建议使用更以javascript为中心的定义对象或对象数组的风格来配置网格。
在您的示例中,MyCol
不需要呈现,您只需要内省创建它的属性。下面是一个例子:
var MyDataGrid = React.createClass({
render: function() {
var options = React.Children.map(this.props.children, (child) => {
return {
type: child.type.displayName,
sortable: !!child.props.sortable,
fieldName: child.props.fieldName
};
});
return <pre>{JSON.stringify(options, null, " ")}</pre>
}
});
var MyCol = React.createClass({
render: function() {
return null;
}
});
var app = (
<MyDataGrid>
<MyCol fieldName='asdf' sortable />
<MyCol fieldName='anotherColumn' />
</MyDataGrid>
);
ReactDOM.render(app, document.getElementById("app"));
示例:https://jsbin.com/totusu/edit?js输出
处理子组件进行配置的主要问题是,当你在父组件中接收到子组件道具时,react组件类不会调用它的构造函数。如果需要应用任何与配置节点/组件相关的逻辑,这会使事情变得复杂。
我现在使用的模式如下所示(并且已确认如您所期望的那样工作)。我使用ES6类的组件,但该模式也适用于功能React.create*
风格。
- 创建props接口(这定义了哪些props可以在配置子节点中使用)
- 创建一个虚拟组件类,使用你创建的道具(这个组件实际上只是一个定义,不包含代码)
- 创建一个带有构造函数的配置类,该构造函数使用所有的道具并执行任何初始化逻辑。
- 在配置类中添加一个静态
create
函数,该函数使用ReactElement
并返回配置类的新实例(该元素将具有在jsx/tsx 中定义的props)。 - 使用
React.Children.map
将子道具转换为父元素中的配置实例数组(这可以在componentWillMount
中完成并保存到实例变量,除非您的列定义是可变的)。
简化示例(Typescript)
interface IDataGridColumnProps {
fieldName: string;
header?: string;
sortable?: boolean;
}
export class DataGridColumn extends React.Component<IDataGridColumnProps, any> {}
class Column {
constructor(public fieldName: string, public header?: string, public sortable = false) {
if (this.header == null) {
this.header = this.fieldName;
}
}
public static create(element: React.ReactElement<IDataGridColumnProps>) {
return new Column(element.props.fieldName, element.props.header, element.props.sortable);
}
}
export class DataGridView /* ... */ {
private columns: Column[];
componentWillMount() {
this.columns = React.Children.map(this.props.children, (x: React.ReactElement<IDataGridColumnProps>) => {
return Column.create(x);
});
}
}
上面使用的模式本质上是将组件节点转换为父组件上的配置实例。原始子节点被抛出,它们提供的配置保留在父组件中的实例数组中。
- 选择<李>使用普通JavaScript的子节点,而不是孙节点
- js循环遍历单击的元素子节点
- 如何将数据添加到json的子节点
- 删除HTML节点而不删除其子节点
- 如何在javascript DOM api中获取具有给定条件的子节点
- 仅使用某些子节点访问xml中父节点的子节点
- 检测单击子节点并发送槽事件处理程序
- 从 d3.js 中的树中选择节点的子节点
- 访问所选剑道树视图节点的子节点
- 为什么正文标记后的脚本标记在子节点中计数
- 难以获取使用属性选择的节点的子节点
- 使用Javascript设置带有子节点的父节点的类's文本等于.
- 如何确定父节点是否有子节点
- 在没有 jquery 的情况下更改子节点(父节点具有 ID)中的链接文本
- Javascript - 子节点计数
- 在子节点上重复
- 如何在D3.js基于力的标签布局图中获取公共子节点
- 如何访问React中的子节点
- js初学者-如何在比网页中的DOM节点低一个级别上立即解析所有子节点
- 是否可以创建为父组件提供配置的子节点