这才是我想要的答案…
另外,我想说官方例子真的不是个好例子,一直都是“className"来取,否则也不会有这种疑惑
真的是办法比问题多
这里第一个组件有可能是ui组件,这就有一些规则限定了,在多人开发的时候会带来一些成本
这就错了,一般这种脚本是不会被require的,都是挂到节点上的
你可以定义一个组件 Script,项目里所有需要快速获取的组件,都继承自这个组件,这个组件注册为插件脚本,保证全局变量会被先注册
window.Script = cc.Class({
extends: cc.Component
});
cc.js.get(cc.Node.prototype, 'script', function () {
return this.getComponent(Script);
});
然后把项目里继承自 cc.Component 的地方全部改成 Script。(为了让你避免获取到 UI 组件)
需要获取组件时,
var node = cc.instantiate(prefab);
node.script.init();
这样就行啦,零 require,零所谓的硬代码
我十分认同 @zxh19821 的 uikiller 这类封装,但是不太赞同把这种封装这么早集成到引擎里。 正如大家所回复的,JS 是门十分灵活的语言,一千个人可能有一千种封装,封装的越抽象可能副作用越大,大家各取所需即可。如果社区将来摸索出了一套统一的,经受住时间考验的框架(类似 jQuery),那引擎也是会欢迎作者提交 PR 集成进来的。
赞同这个,没有统一的标准,弄的太乱,让新手更摸不着头脑
更喜欢这样的代码,动态语言的优雅。
刚测试了下,可行,原理其实就是把getComponent函数注册到node上,通过这种方式来快速获取脚本组件,这种方案目前来看确实是最优的
这个方法只能获得一个脚本。局限性比较大。其实方法还有很多,大家可以自己变通。
上面说的方法只能获得一个脚本,主要是满足了这个同学的需要,局限性比较大。其实方法还有很多,大家可以自己变通。
当然,程序员如果真的能假定节点上只有一个脚本,那允许 node.getComponent() 直接返回第一个组件似乎也没问题。
不过如果太依赖这种写法,似乎又容易自己坑到自己(谁知道场景会不会被其它人玩坏),所以还是像 @toddlxt 推荐的那样显式传入一个 node.getComponent(cc.Component) 吧。多写点难看的代码一般人会比较清楚自己在做什么。
这样的写法遇到一个bug,1.6.1,macOS Sierra 10.12.5
//NodeExtend.js
window._nodeExtendMath = {
// 随机一个int [min, max]
randomInt: function (min, max) {
if (min === max) return min;
return min + Math.floor(Math.abs(Math.random() * (max + 1 - min)));
}
};
cc.js.get(cc.Node.prototype, 'math', function () {
return _nodeExtendMath;
});
// console error
2017-09-15T03:41:16.886Z - normal: connected!
2017-09-15T03:41:20.986Z - normal: 1.6.1
2017-09-15T03:41:42.737Z - error: TypeError: Cannot redefine property: math
at Object.js.get (/Applications/CocosCreator.app/Contents/Resources/engine/cocos2d/core/platform/js.js:280:12)
at disable-commonjs:///Users/webb/Desktop/selfDoc/never-touch/assets/script/NodeExtend.js?002:8:7
at disable-commonjs:///Users/webb/Desktop/selfDoc/never-touch/assets/script/NodeExtend.js?002:11:3
问题是这样出现的,NodeExtend.js 勾选 导入为插件,允许web,允许浏览器,允许Native。
第一次打开creator不会有问题。当我修改_NodeExtend.js_ 再回到creator 必现这个报错。
不要允许 creator 即可,或者 cc.js.get(…, ‘math’, function () {…}, false, true);
我可以这样理解吗?这样动态添加属性到cc.Node上会影响编辑器的属性检查器?还是别的原因?
因为Creator是经常刷新的,比如你改了点代码,它就刷新一下,然后你的插件脚本就又执行了一次。估计cc.js.get内部使用Object.defineProperty定义你的math属性的时候,默认把configurable设置成了false(不能再次定义)。所以一旦Creator刷新,再次执行插件重新定义math,就会报错。@jare老师让你在cc.js.get后面多传一个false,true,应该就是设置configurable为true的意思。跟属性检查器没啥关系。你也可以把cc.js.get自己写成:
Object.defineProperty(cc.Node.prototype, 'math', {
get: function(){
return _nodeExtendMath;
},
configurable: true
});
@feijing566 参照@jare老师的写法,可以这样获取node上的第一个非cc脚本(不用改其它代码,直接用node.script即可):
Object.defineProperty(cc.Node.prototype, 'script', {
get: function(){
return this.getComponents(cc.Component).find(function(c) {
return c.__classname__.indexOf("cc.");
}
},
configurable: true
});
发现node上面有这么一个属性_components,里面的参数是目前节点上自己挂载的脚本
这样可以获取到脚本中的任意一个函数
谢谢你的思路了
这个问题其实就是组件带来的带副作用 没有统一的流程方法 ,比如init update close等
所谓鱼和熊掌不能兼得
新手,刚学习cocos,觉的这种写法很奇怪。
对编码来说,更应该对外暴露的不应该是“脚本”组件里的各种行为吗?UI组件理应都是通过脚本组件里的行为去进行操作的。所以理想的情况应该是Prefab对外可以直接调用所有的的脚本组件的公共方法。