to initComponent () or not To initComponent ()

Eu luto ao construir um aplicativo em ExtJS 4, e parte disso é a confusão sobre quando configurar algo em seu computador() e quando não para...

por exemplo, na própria arquitectura de aplicações do Sencha MVC doc, ao criar pela primeira vez a área da grelha, eles definiram o armazenamento em linha no método intcomponent (). (Ver secção" Definir uma vista")

Mais para baixo, quando viram a loja numa classe separada, mudaram a definição. fora da sua competência(). Há um comentário útil que chama a atenção para este fato, mas não há explicação.

Acho que a razão devia ser óbvia, mas estou a perdê-la. Alguma dica?

Author: romacafe, 2013-01-24

4 answers

Se você não tem uma compreensão profunda de como funciona o sistema de classes ExtJS, você pode querer seguir isto:

Declare todos os tipos não primitivos em {[[0]}.

Terminologia

  • tipos primitivos - cadeias, booleanos, inteiros, etc.
  • não primitivos - arrays & objects.

Explicação

Se o componente que extende for criado mais de uma vez, quaisquer configurações não primitivas serão declaradas como um a opção de configuração (fora de initComponent) será partilhada entre todas as instâncias.

Por causa disso, muitas pessoas experimentaram problemas quando um componente estendido (tipicamente uma grade estendida) é criado em mais de um tab.

Este comportamento é explicado na resposta da sra abaixo e no artigo deste Skirtle's Den. Você também pode querer ler esta pergunta assim .

 44
Author: Izhaki, 2020-06-20 09:12:55

Em Primeiro Lugar, vou tomar posição sobre os meus comentários.:

@AlexanderTokarev não me interpretes mal. Eu não falo sobre configurações de componentes, ou muito pior de instâncias e movê-los para initComponent(), Esse não é o meu ponto.

Agora o que eu penso sobre isso.

initComponent () deve resolver qualquer coisa necessária no tempo de uma instância desta classe é criada. Nem mais, nem menos.

Podes estragar uma carga quando definir classes e a maior parte disso acontece porque as pessoas não entendem como funciona o sistema de classes ExtJS. Como se trata de componentes, o seguinte vai se concentrar neles. Também será um exemplo simplificado que só deve mostrar uma espécie de erro que eu vi muitas vezes.

Vamos começar, temos um painel personalizado que faz muitas coisas engraçadas. Isso traz a necessidade de uma configuração personalizada, nós a chamamos de foo. Adicionamo-lo, juntamente com a nossa opção de configuração predefinida, à classe definição para que possamos acessá-lo:
Ext.define('Custom', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.custpanel',

    foo: {
        bar: null  
    },

    initComponent: function() {
        this.callParent(arguments);
    }
});
Mas as coisas ficam estranhas depois dos testes. Os valores das nossas configurações parecem mudar magicamente. Aqui está um JSFiddle O que aconteceu é que todas as instâncias criadas estão se referindo à mesma instância foo. Mas ultimamente tenho feito isso.
store: {
    fields: [ ... ],
    proxy: {
        type: 'direct',
        directFn: 'Direct.Store.getData'
    }
}
Com uma loja e isso funcionou. Então porque não funciona?

A maioria das pessoas não vê nenhuma diferença entre este pequeno objeto foo e uma configuração (ExtJS) que é basicamente correto porque ambos são objetos (instâncias). Mas a diferença é que todas as classes enviadas pelo sencha sabem perfeitamente quais as propriedades de configuração que eles esperam e cuidar deles.

Por exemplo, a propriedade da loja de uma grelha é resolvida pelo StoreManager e pode, portanto, ser:

  • storeId fio, ou
  • conservar instância ou
  • guardar o objecto de configuração.
Durante a inicialização da grelha, qualquer um destes fica resolvido. e substituído por uma loja a sério. Uma loja é apenas um exemplo. Acho que o mais conhecido é o conjunto de itens. Este é um array no tempo de definição e ele fica sobreposto para cada instância com uma coleção Mixed (se não estou enganado).

Sim, há uma diferença entre uma definição de classe e a instância criada a partir dela. Mas precisamos cuidar de qualquer nova propriedade que contenha uma referência como o foo de cima e que não seja tão complicado. Eis o que precisamos para o Corrigir para o exemplo foo

Ext.define('Custom', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.custpanel',

    foo: {
        bar: null  
    },

    initComponent: function() {
        this.foo = Ext.apply({}, this.foo);
        this.callParent(arguments);
    }
});
Aqui está o JSFiddle

Agora tratamos da configuração foo Quando uma instância é criada. Agora este exemplo foo é simplificado e nem sempre será tão fácil resolver uma configuração.

Conclusão

Escreva sempre a sua definição de classe como configurações! Não devem conter todas as instâncias referidas, excepto a configuração simples e deve Cuide-se destes para resolvê-los quando uma instância é criada.

Declaração de exoneração de Responsabilidade

não pretendo cobrir tudo com esta escrita muito curta!

 22
Author: sra, 2013-04-04 21:02:30

Normalmente defendo que se tenha o máximo de configuração possível nas opções de configuração da classe, porque lê-se melhor e é mais fácil de sobrepor nas subclasses. Além disso, há uma forte possibilidade de que, no futuro, o CMD do Sencha tenha Otimizado o compilador para que, se você mantiver o seu código declarativo, ele possa se beneficiar de otimizações.

Comparar:

Ext.define('MyPanel', {
    extend: 'Ext.grid.Panel',

    initComponent: function() {
        this.callParent();
        this.store = new Ext.data.Store({
            fields: [ ... ],
            proxy: {
                type: 'direct',
                directFn: Direct.Store.getData
            }
        });
        this.foo = 'bar';
    }
});

...

var panel = new MyPanel();

E:

Ext.define('MyPanel', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.mypanel',

    foo: 'bar',

    store: {
        fields: [ ... ],
        proxy: {
            type: 'direct',
            directFn: 'Direct.Store.getData'
        }
    }
});

...

var panel = Ext.widget({
    xtype: 'mypanel',
    foo: 'baz'
});

Note como estas abordagens são muito diferentes. No primeiro exemplo, estamos hardcoding a lote: valores da propriedade do objeto, configuração da loja, Nome da classe MyPanel quando é usado; estamos praticamente matando a idéia de uma classe porque ela se torna inextensível. No segundo exemplo, estamos criando um modelo que pode ser reutilizado muitas vezes com configuração possivelmente diferente-basicamente, é disso que se trata todo o sistema de classes.

No entanto, a diferença real é mais profunda. No primeiro caso, estamos efetivamente adiando a configuração da classe até o tempo de execução, enquanto que no segundo caso, estamos a definira configuração da classe e a aplicarem fases muito distintas. Na verdade, podemos facilmente dizer que a segunda abordagem introduz algo que o JavaScript não possui: compilar a fase de tempo. E isso nos dá uma infinidade de possibilidades que são exploradas no próprio código-quadro; Se você quiser alguns exemplos, dê uma olhada em Ext.app.Controller e Ext.app.Application no mais recente 4.2 beta. Do ponto de vista mais prático, a segunda abordagem é: melhor porque é mais fácil ler e lidar com isso. Assim que perceberes a ideia, vais encontrar-te a escrever todo o teu código assim, porque é mais fácil assim.

Veja as coisas desta forma: se você escrevesse uma aplicação Web de estilo antigo, gerando HTML e coisas do lado do servidor, você tentaria não ter nenhum HTML misturado com o código, não é? Modelos à esquerda, Código à direita. Isso é praticamente o mesmo que dados hardcoding em initComponent: claro que funciona, até certo ponto. Então ... torna-se uma tigela de esparguete, difícil de manter e estender. E testando tudo isso! Que nojo.

Agora, há são vezes em que você precisa fazer algo com uma instância em tempo de execução, em oposição a um tempo de definição de classe - o exemplo clássico é aplicar ouvintes de eventos, ou chamar control em Controladores. Você terá que tomar referências reais da função da instância objeto, e você tem que fazer isso em initComponent ou init. No entanto, estamos a trabalhar para aliviar este problema. - não deve haver nenhum requisito difícil para hardcode tudo isso; Observable.on() já suporta nomes de ouvintes de texto e coisas MVC irá também, em breve.

Como eu disse nos comentários acima, terei que escrever um artigo ou guia para os documentos, explicando as coisas. Isso provavelmente teria que esperar até que 4.2 seja liberado; entretanto, esta resposta deveria lançar alguma luz sobre o assunto, esperamos.
 14
Author: Alex Tokarev, 2013-01-25 19:36:50
Tenho andado à procura de uma resposta para a mesma pergunta quando vim aqui parar e ver estas respostas deixou-me desapontado. Nenhuma destas respostas responde à pergunta: initComponent () ou constructor?

É bom saber que os objetos da opção class config são compartilhados e você precisa inicializá-los/processá-los por exemplo, mas o código pode ir para o construtor, bem como para a função initComponent ().

O meu palpite era que o construtor das chamadas da classe componente initComponent () somewhere in the middle and I was not very wrong: Just had to look at the source code, it's actually Abstractcomponent's constructor {[[10]}. Então é assim:
AbstractComponent/ctor:
- stuffBeforeIC()
- initComponent()
- stuffAfterIC()
Agora se você estender um componente, você vai ter algo assim:
constructor: function () {
  yourStuffBefore();
  this.callParent(arguments);
  yourStuffAfter();
},
initComponent: function () {
  this.callParent();
  yourInitComp()
}

A ordem final que estes recebem é:

- yourStuffBefore()
- base's ctor by callParent:
  - stuffBeforeIC()
  - initComponent:
    - base's initComponent by callParent
    - yourInitComp()
  - stuffAfterIC()
- yourStuffAfter()

Por isso, no fim de contas, tudo depende se quer / precisa de injectar o seu código entre o stuffBeforeIC e o stuffAfterIC, que pode procurar no construtor da classe que você vai estender.

 12
Author: Szilveszter Safar, 2013-05-01 11:29:16