组件查询找到静态配置但未以编程方式添加

Component Query finds static config but not programmatically added

在我们的 ExtJs 5.0.1 项目中,我们创建组件并在 运行时 添加额外的 css 类 有条件的。 我们想通过组件查询找到它们,但是对于以编程方式添加的 css 类.

但是当我们在组件配置中硬编码定义它们时,查询 returns 预期结果。

我们如何获取对以编程方式添加的组件的引用 css 类?

示例视图:

Ext.define('T.view.Main',{
    extend: 'Ext.panel.Panel',
    title: 'test',
    cls: 'working', // static config

    initComponent: function(){
        this.callParent(arguments);
        this.addCls('notworking'); // added at runtime
    }
});

示例应用程序:

Ext.application({
    name : 'T',
    autoCreateViewport: 'T.view.Main',

    launch: function(){
        // the cls "working" assigned as config to the Main View is found by 
        // the ComponentQuery
        var working = Ext.ComponentQuery.query('[cls~=working]');
    
        // the cls "notWorking" assigned by addCls during runtime to the Main View 
        // is not found by the ComponentQuery
        var notWorking = Ext.ComponentQuery.query('[cls~=notworking]');
    
        Ext.Msg.alert('Static vs Dynamic', 'working: ' + working.length + ' notWorking: ' + notWorking.length);
    }
});

更新

@Alexander 建议在调用 callParent 之前添加额外的 cls,这听起来像是一个显而易见的解决方案,但现在组件查询甚至找不到 .working cls。

Ext.define('T.view.Main',{
    extend: 'Ext.panel.Panel',
    title: 'test',
    cls: 'working', // static config

    initComponent: function(){
        this.cls += ' notworking';
        this.callParent(arguments);
    }
});

查看更新后的 Sencha Fiddle

更新 2

我可能在 Component.js 代码中发现了问题,在构造函数中发生了以下情况

constructor: function (config) {
    ...
    me.setupProtoEl();

    // initComponent, beforeRender, or event handlers may have set the style or `cls` property since the `protoEl` was set up
    // so we must apply styles and classes here too.
    if (me.cls) {
        me.initialCls = me.cls;
        me.protoEl.addCls(me.cls);
    }
    if (me.style) {
        me.initialStyle = me.style;
        me.protoEl.setStyle(me.style);
    }

    me.renderData = me.renderData || {};

    me.initComponent();
    ...
  1. proto el 由 me.setupProtoEl();
  2. 用一些 css 类 初始化
  3. 检查是否设置了cls,然后将其应用于原型元素并保存到initialCls 属性
  4. initComponent 函数被调用,当cls在其中改变时,构造函数不再注意到它

在我看来,第 2 步和第 3 步需要互换,以便识别 initComponent 函数中 cls 的变化。

cls是一个配置属性,供你指定CSSclass。但是 addCls 不会更新它 - 它只是更新基础 DOM 元素上的 class 属性。

addCls: function(cls) {
    var me = this,
        el = me.rendered ? me.el : me.protoEl;

    el.addCls.apply(el, arguments);
    return me;
},

(source)

因为 addCls 不更新 cls 属性,您的 ComponentQuery 调用无法通过这种方式找到它。

至于你如何解决你的问题:最简单的方法是在你更新的 class 上添加你自己的 属性,同时添加 [=25] =].然后您可以对您的自定义 属性 进行组件查询。尽管我会包括您的 class 的 xtype,以避免潜在的命名空间冲突。

正如@RobertWatkins 指出的那样,组件的 cls 没有被 addCls 改变,它只是更新了 DOM 元素。

在运行时设置 cls 配置的解决方案是在组件构造函数中执行。然后将 cls 应用于 DOM 元素和组件。组件查询现在可以找到它。

cls: 'working',
constructor: function (config) {
    this.cls += ' nowworking';
    this.callParent(arguments);
},

对应的应用程序片段

// the component is retrieved 
var working = Ext.ComponentQuery.query('[cls~=working]');
// the component is retrieved aswell
var nowWorking = Ext.ComponentQuery.query('[cls~=nowworking]');

工作 fiddle.