QML组件范围拼图

时间:2012-07-05 07:33:20

标签: scope obfuscation qml

拿这段代码:

import QtQuick 1.1

Rectangle {
    width:  100
    height: 100

    property color fromColor: "red"
    property color toColor:   "blue"

    gradient: Gradient {
        property color fromColor: "yellow"
        property color toColor:   "green"

        GradientStop { position: 0; color: fromColor }
        GradientStop { position: 1; color: toColor }
    }
}

为什么Gradient从封闭元素中选择其fromColortoColor属性到底是什么?

这在哪里记录(至少在源代码评论中,在官方文档中更好)?

注意:这个“QML混淆示例来自Girish Ramakrishnan的演讲Qt Quick Best Practices and Design Patterns(倒带到第25分钟),他确实说这件事非常复杂,并且必须具有组件范围等等,但没有时间解释原因。

[UPDATE]

因此,正如MartinJ在下面所述,element-property(不仅是element-child)层次结构中的顶级组件的属性对所有属性都是可见的,但是深层嵌套,优先级是属性的属性,并且“中间”项目的所有属性都没有看到。

这是一个小例子:

import QtQuick 1.1

Item {
    Item {
        property string s: "parent-str"
        Item { Component.onCompleted: console.log(s) }
    }
}

这给出:"ReferenceError: Can't find variable: s"

这可以按预期工作:

import QtQuick 1.1

Item {
    property string s: "parent-str"
    Item { Component.onCompleted: console.log(s) }
}

,输出"parent-str"

请参阅下面的MartinJ的评论。

2 个答案:

答案 0 :(得分:7)

乍一看这看起来并不直观,但在组件根项目中注释掉fromColortoColor,原因就变得明显了。从QML Scope docs您可以看到范围包括:

  • 在Component中定义的所有id
  • 当地物业
  • Component
  • 的根对象的属性

上例中的GradientStop {}没有定义本地属性。根组件可以,它们是fromColortoColor解析的属性。 Gradient {}中的属性根本不在GradientStop {}的范围内。

答案 1 :(得分:0)

另见:

import QtQuick 1.1

Item {
    property string s: "outer"

    Item {
        property string s: "middle"

        property Item it: Item {
            property string dummy: function() { console.log("(5) s: "+s); "" }()
            Component.onCompleted: console.log("(1) s: " + s)
        }

        Item {
            property string dummy: function() { console.log("(4) s: "+s); "" }()

            function f() {
                console.log("(2) s: " + s)
            }

            Component.onCompleted: {
                console.log("(3) s: " + s)
                f()
            }
        }
    }
}

此代码输出:

(5) s: outer
(4) s: outer
(3) s: outer
(2) s: outer
(1) s: outer

注意,但是(对于Children属性或不是)和我们绑定的任何(元素或javascript代码片段),永远不会找到“middle”属性。

名称查找因此是:

  1. 在项目或组件中定义的id(参见3)
  2. 本地物业
  3. 顶级项目的属性(或组件,如果它是内联定义的,即使省略了“组件”名称,例如方便定义委托时)。
  4. 此外,当在组件中引用属性但未在其中定义属性时,它仍然可以在“自定义”组件中引入,并且可以看到:

    //OverrideInner.qml
    import QtQuick 1.1
    
    Item {
        Component.onCompleted: console.log(s)
    }
    

    //OverrideOuter.qml
    import QtQuick 1.1
    
    Item {
        property string s: "overriden-outer"
    
        Item {
            property string s: "overriden-middle"
    
            OverrideInner {
                property string s: "overriden-inner"
            }
        }
    }
    

    运行“OverrideOuter.qml”会产生:

    overriden-inner
    

    再次,请参阅Martin的评论以及澄清此事的文档。相关文档是: