2012-07-05 24 views
8

Tome este código:QML rompecabezas alcance componente

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 } 
    } 
} 

¿Por qué se hace exactamente la Gradient recoger sus propiedades fromColor y toColor del elemento envolvente?

¿Dónde está esto documentado (al menos dentro de los comentarios del código fuente, mejor dentro de los documentos oficiales)?

Nota: este "ejemplo ofuscación QML es de charla de Girish Ramakrishnan Qt Quick Best Practices and Design Patterns (rebobinar a 25 minutos), donde él dice que la cosa es muy complicada y tiene que con el alcance de los componentes y de esa manera, pero no tiene tiempo para explicar por qué.

[ACTUALIZACIÓN]

Así que, como MartinJ dice a continuación, el componente de nivel superior en el elemento de propiedad (no único elemento hijo) jerarquía tiene sus propiedades visibles a todas las propiedades sin embargo profundo anidado, con la precedencia de las propiedades de esas propiedades, y todos los pr operties de elementos "intermedios" no vistos en absoluto.

Aquí hay un pequeño ejemplo:

import QtQuick 1.1 

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

Esto da: "ReferenceError: Can't find variable: s"

Y esto funciona como se esperaba:

import QtQuick 1.1 

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

, la salida "parent-str".

Por favor, vea los comentarios de MartinJ a continuación.

+0

"si usted está interesado en saber por qué es como es ... simplemente no dude en tomar después de la charla. " (Girish Ramakrishnan en esa charla). Bueno, ratas. – cgmb

+0

@ Slavik81 Bueno, el simple hecho de señalar el tema fue muy útil, al menos. Además, siempre podemos enviarle un correo electrónico, si él no ha olvidado los detalles relevantes :) – mlvljr

+0

@ Slavik81 Se borró, respondió Martin, y actualicé mi pregunta con un (espero) ejemplo aclaratorio. – mlvljr

Respuesta

6

Esto ciertamente no parece intuitivo a primera vista, pero comente fromColor y toColor en el elemento raíz del componente y el motivo se pone de manifiesto. Desde el QML Scope docs se puede ver que el ámbito de aplicación incluye:

  • todos los id 's definidos dentro del componente.
  • propiedades locales
  • las propiedades del objeto raíz del Componente

A GradientStop {} en el ejemplo anterior no tiene propiedades locales definidas. El componente raíz sí lo hace, y son las propiedades que resuelven fromColor y toColor. Las propiedades en Gradient {} no están en el alcance del GradientStop {} en absoluto.

+0

Bien, lo pensaré de nuevo, aunque me gustaría hacer algunas preguntas de inmediato (dado que ya he leído la página del scoping doc varias veces, para 4.7, pero parece que nada ha cambiado desde entonces). – mlvljr

+0

1. En primer lugar, si las propiedades principales se ignoran durante la búsqueda de nombres desde dentro de los elementos secundarios (como Gradient es el padre de ambos objetos GradienStop), ¿por qué hacer ejemplos como 'Item {property string s:" parent-str "; El elemento {Component.onCompleted: console.log (s)}} 'funciona en absoluto (¿este produce" paren-str ")? – mlvljr

+0

2. Además, la otra mitad del puzzzle en la charla (vinculada arriba) fue que al colocar la definición de Degradado (como está) en un archivo separado, se encuentran ambas propiedades de color interno. – mlvljr

0

También vemos esto:

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() 
      } 
     } 
    } 
} 

este código salidas:

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

nota, que sin embargo (a la propiedad Los niños o no) y cualquiera que sea (un elemento o un fragmento de código JavaScript) que bind, la propiedad "middle" nunca se encuentra.así

La búsqueda de nombre es:

  1. de definido dentro del artículo o componente (ver 3)
  2. propiedades locales
  3. propiedades del elemento de nivel superior (o componente, en caso de que está definida en línea de la identificación, incluso cuando se omite el nombre "Componente", como cuando los delegados se definen convenientemente).

Además, cuando se hace referencia a una propiedad dentro del componente, pero no se define dentro de ella, todavía se puede introducir dentro del componente "a medida", y ser visto:

//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" 
     } 
    } 
} 

Running "OverrideOuter.qml" produce:

overriden-inner 

Una vez más, ver los comentarios de Martin y la documentación para aclarar el asunto. Los documentos relevantes son: