# 嵌套的Container组件

> container组件能够为子级组件传递数据， 同样， container也可以给container传递数据

结合上面的几个章节，我们已经清楚。一个`container`组件的子级组件，都可以获取到来自父级的`$data`属性。

可是， 如果遇到子级的组件也是一个`container`组件的时候，这个情况就需要专门来解释了。

## 数据模型的优先级

多层的`container`组件的出现， 必然会牵扯出优先级顺序的问题。 数据模型的优先级决定着当父级的`container`和子级的`container`中含有相同属性值冲突的时候， 相互之间merge的顺序。

### 子级优先

在RCRE中，子级container组件的数据拥有最高的优先级，父级container的数据不会对子级container的数据进行覆盖。

如果想在子级的container中访问父级container的数据的话，可以通过$parent这个变量来访问，当然，如果想访问父级的父级的话，也可以使用#ES{$parent.$parent}来访问。

例如:

## 多级嵌套

多个嵌套的container示例

```json
{
    "body": [{
        "type": "container",
        "model": "root",
        "data": {
            "name": "root"
        },
        "children": [{
            "type": "container",
            "model": "left-1",
            "data": {
                "name": "left-1"
            },
            "children": [{
                "type": "container",
                "model": "left-1-1",
                "data": {
                    "name": "left-1-1"
                },
                "children": [{
                    "type": "text",
                    "style": {
                        "display": "block"
                    },
                    "text": "model: left-1-1, private name: #ES{$data.name}"
                }, {
                    "type": "text",
                    "style": {
                        "display": "block"
                    },
                    "text": "model: left-1-1, parent name: #ES{$parent.name}"
                }, {
                    "type": "text",
                    "style": {
                        "display": "block"
                    },
                    "text": "model: left-1-1, parent parent name: #ES{$parent.$parent.name}"
                }]
            }]
        }]
    }]
}
```

这个例子展示了连续3层`container`嵌套的场景。 最顶层的`container`组件， 中间的`container`组件和最底层的`container`组件。

外层的container组件不会对内部的container组件的数据造成任何影响，内部的container组件可以通过$parent来获取父级container的值

## 嵌套状态的属性映射

container不仅应持有私有属性，也得持有私有的字段名称。这样才有利于配置组件化开发。

对于多级container嵌套的情况，可以在container组件上使用props属性，来实现跨container组件传值。

如果通过props传入的key和当前container中已有的key存在冲突的话，可以配置`priority`属性来决定是父级覆盖子级，还是子级覆盖父级。

如果props直接设置成字符串的话，`priority`默认为parent。

| priority 的值 | 说明   |
| ------ | ------ |
| child   | 子级 > 父级，只要字级中存在的key，都不会被父级所覆盖 |
| parent   | 子级 < 父级, 父级传入的任何属性都会无条件覆盖到子级 |

**注意：当priority为parent的时候，就无法在当前container组件中修改值了。**

```json
{
    "body": [
        {
            "type": "container",
            "model": "component",
            "data": {
                "name": "andycall",
                "age": 22
            },
            "children": [
                {
                    "type": "row",
                    "style": {
                        "margin": 10
                    },
                    "children": [
                        {
                            "type": "text",
                            "gridWidth": 300,
                            "text": "outer container name: #ES{$data.name}"
                        },
                        {
                            "type": "text",
                            "gridWidth": 300,
                            "text": "outer container age: #ES{$data.age}"
                        }
                    ]
                },
                {
                    "type": "row",
                    "width": 500,
                    "children": [
                        {
                            "type": "text",
                            "text": "设置父级的name值: "
                        },
                        {
                            "type": "input",
                            "name": "name",
                            "style": {
                                "width": 200
                            }
                        }
                    ]
                },
                {
                    "type": "row",
                    "width": 500,
                    "children": [
                        {
                            "type": "text",
                            "text": "设置父级的age值: "
                        },
                        {
                            "type": "input",
                            "name": "age",
                            "inputType": "number",
                            "style": {
                                "width": 200
                            }
                        }
                    ]
                },
                {
                    "type": "container",
                    "model": "childContainer",
                    "style": {
                        "marginTop": 30
                    },
                    "props": {
                        "name": {
                            "prop": "#ES{$parent.name + ' is children'}",
                            "priority": "child"
                        },
                        "age": "#ES{$parent.age + $parent.age}",
                        "ageCopy": {
                            "prop": "#ES{$parent.age + 1}",
                            "priority": "parent"
                        }
                    },
                    "children": [
                        {
                            "type": "text",
                            "text": "inner container name: #ES{$data.name}"
                        },
                        {
                            "type": "text",
                            "text": "inner container age: #ES{$data.age}"
                        },
                        {
                            "type": "text",
                            "text": "inner container ageCopy: #ES{$data.ageCopy}"
                        },
                        {
                            "type": "row",
                            "width": 500,
                            "children": [
                                {
                                    "type": "text",
                                    "text": "设置字级name的值: "
                                },
                                {
                                    "type": "input",
                                    "name": "name",
                                    "style": {
                                        "width": 200
                                    }
                                }
                            ]
                        },
                        {
                            "type": "row",
                            "width": 500,
                            "children": [
                                {
                                    "type": "text",
                                    "text": "设置字级的age值"
                                },
                                {
                                    "type": "input",
                                    "name": "age",
                                    "style": {
                                        "width": 200
                                    }
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}
```

## 子级数据自动同步到父级
除了使用trigger这样较为麻烦的方式，如果有必要自动把子级的一些数据自动向上同步到父级，可以使用bind这个功能。

在子级的container组件设置如下的配置，就能把当前container组件的某个值，自动根据parent属性写入到父级container的数据模型中。

**注意：如果子级被hidden或者show属性隐藏，数据同步将不会起任何作用。请用dataCustomer来完成数据传输**

```json
{
    "body": [{
        "type": "container",
        "model": "outerBindContainer",
        "children": [{
            "type": "text",
            "text": "value from child container: #ES{$data.name}"
        }, {
            "type": "container",
            "model": "childBindContainer",
            "bind": [{
                "child": "childName",
                "parent": "name"
            }],
            "children": [{
                "type": "input",
                "name": "childName",
                "placeholder": "子级的数据源"
            }]
        }]
    }]
}
```


## 向后兼容
早期版本的RCRE是采取父级优先的合并策略，在0.15.0版本之前都是采取父级优先的策略进行合并。

如果你想启动兼容模式，使用原有的合并策略，可以使用下面的方式来运行RCRE。

```javascript
var engine = React.createElement(RCRE.Render, {
    code: JSON.stringify(config),
    options: {
        oldNestContainerCompatible: true
    }
});
```
