CocosCreator编码贴士:组件不等于Node

一开始的时候会搞不清楚这两者的关系,但是在经历多次报错的教育之后终于铭记住了这两者之间的不同。先看下图所示的组件


新建一个渲染节点->Sprite并命名为'Item'后在右侧属性检查器里面会发现该节点所有属性被分为了两个类别,位于上方的是Node(含有x,y,anchor等定位属性及color, opacity等颜色透明度属性),位于下方的是Sprite(含有纹理及混合模式等属性)。为什么'Item'的属性会被分为Node和Sprite两个类别呢?因为在cocosCreator里面所有节点都不是独立存在的,它们是由若干个组件堆砌在一起的,每堆砌一个组件就多一个功能。如果我们在creator的编辑器里面新建一个空节点,那么该节点仅由Node组件组成,如果新建一个Sprite节点,那么该节点将会由Node组件(每个节点的根组件均为Node组件)和Sprite组件组成,就像我们刚才新建的'Item'节点一样。
因此,在写代码对节点进行操作的时候必须时刻记得我们要操作的属性是属于哪个组件的。下图中,我们新建了一个Script命名为Item,并将其挂载到刚才新建的Item节点上面。

下面是Item这个Script文件的代码:

cc.Class({
    extends: cc.Component,
    
    onLoad: function () {
        this.node.spriteFrame = xx;
    },
});

我们在这个脚本中企图对节点Item的纹理进行更改,于是在onLoad中使用了this.node.spriteFrame = xx;这样的代码,但是最终执行时并无法得到我们预想的结果。原因在于我们操作的属性spriteFrame并不在Node组件上,而是在Sprite组件上。所以,要想达到预期效果,就必须使用getComponent方法先获取到我们要操作属性所属的组件后再进行属性修改动作:

cc.Class({
    extends: cc.Component,
    
    onLoad: function () {
        this.node.getComponent(cc.Sprite).spriteFrame = xx;
    },
});

代码改成上面这样就一切OK了。再接下来看另一个例子,假如我们在Item这个Script文件里面需要持有另一个文本节点的引用,并在onLoad里面对此文本节点进行更改显示的文字的操作,那么代码如下:

cc.Class({
    extends: cc.Component,

    properties: {
        label: {
            default: null,
            type: cc.Node
        }
    },
    
    onLoad: function () {
        this.label.string = 'xxx';
    }
});

然后在creator编辑器里面新建一个Label节点到舞台上并把他拖拽进Item节点的Item这个脚本组件的label属性里面去


运行项目后发现无法达到预期效果,这是什么原因呢?有同学可以回答我吗?这位同学回答得非常好,原因和刚才我们举的例子一样,是因为我们操作的属性string属于cc.Label组件,而不属于cc.Node组件,而我们在onLoad方法里获取到的this.label其实上是一个cc.Node组件,因为我们在属性声明语句里声明了它的类型就是cc.Node:

  properties: {
        label: {
            default: null,
            type: cc.Node //声明了其类型为cc.Node
        }
    }
});

要解决此问题,有两种方法,其一就是在声明label属性时规定其类别为cc.Label

  properties: {
        label: {
            default: null,
            type: cc.Label //声明了其类型为cc.Label
        }
    }
});

其二就是和之前举的例子一样,使用getComponent方法先,然后再操作属性

    onLoad: function () {
        this.label.getComponent(cc.Label).string = 'xxx';
    }
});

具体使用什么方式主要还是看哪一种比较方便,如果你在Item这个脚本组件中需要频繁修改label的string属性,那么就把label声明成cc.Label类型,如果需要频繁修改label的位置,那么就声明成cc.Node(因为x,y属性属于cc.Node组件),如果你把label声明成了cc.Label类型后想修改其位置,需要使用this.label.node.x = 123这样的代码,不能漏掉.node,这一段,因为需要先取到cc.Node组件后才能操作x属性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • (三)访问节点和组件 你可以在 属性检查器 里修改节点和组件,也能在脚本中动态修改。动态修改的好处是能够在一段时间...
    菜鸟_一枚阅读 822评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,099评论 19 139
  • 一、基本内容: 1.cc.Label相关: (1)动态创建cc.Label : var node = new cc...
    工匠良辰阅读 1,327评论 0 1
  • main {width:220px;height:300px;border:1px solid black;dis...
    jh2k15阅读 346评论 0 0
  • 群里是几个因爱书而识但从未见过的朋友,很喜欢一个姑娘说“书签就像是书的伴侣”的说法,我的每本书都有一个书签,最近就...
    奴隶主阅读 387评论 1 2