使用CocosCreator已經(jīng)一年了斋枢,在此期間一直在摸索帘靡,如何才是組件化編程的最優(yōu)實(shí)踐。Shawn屬于半野生的路子瓤帚,水平不高描姚,但不時(shí)會(huì)陷入一些問(wèn)題瞎琢磨。我根據(jù)自己的經(jīng)驗(yàn)戈次,總結(jié)了一套組件化編程模型:法寶與結(jié)界模型轩勘。
但在介紹法寶、結(jié)界組件模型之前怯邪,先回顧一下控件和組件的概念赃阀。
一、控件與組件
在Cocos2d-x/lua/js的年代擎颖,UI元素都以控件類(lèi)的形式存在。只有cc.Node的子類(lèi)才能在界面上顯示观游,例如:cc.Image搂捧、cc.Button、cc.Text懂缕。我們編寫(xiě)的界面代碼也屬于cc.Node的子類(lèi)或系統(tǒng)控件的子類(lèi)允跑。
在Creator中我們自己編寫(xiě)的cc.Component的子類(lèi)腳本,能稱(chēng)之為控件嗎?
1.我所理解的控件
我覺(jué)得要能稱(chēng)的上控件聋丝,必須是能夠被界面編輯器和代碼所控制索烹,并能相對(duì)獨(dú)立完成一項(xiàng)或多項(xiàng)任務(wù)的程序模塊。而且控件具有一定范圍的通用性弱睦,可以獨(dú)立運(yùn)行百姓,可以被獨(dú)立測(cè)試。
我們要自定控件况木,一類(lèi)是cc.Componet子類(lèi)腳本 + 預(yù)制體的結(jié)合垒拢;第二類(lèi)是純cc.Componet的子類(lèi)腳本(不含預(yù)制體),也可以是系統(tǒng)組件的派生類(lèi)火惊。不含預(yù)制體的腳本其實(shí)是引擎自動(dòng)幫我們生成的求类,當(dāng)拖入一個(gè)組件腳本到場(chǎng)景編輯器,Creator會(huì)自動(dòng)生成一個(gè)節(jié)點(diǎn)屹耐,并將腳本掛載到這個(gè)節(jié)點(diǎn)上尸疆。
這兩類(lèi)控件有什么不同呢?
腳本+預(yù)制體:控制的是預(yù)制體中的節(jié)點(diǎn)和子節(jié)點(diǎn)惶岭,以及節(jié)點(diǎn)上的控件寿弱。
純腳本: 只能控制當(dāng)前節(jié)點(diǎn),也可以控制當(dāng)前節(jié)點(diǎn)上的其它組件俗他。
可以看出脖捻,這兩類(lèi)組件代碼在他們控制的范圍上是不同的。
2. 組件的悲劇
cc.Componet的子類(lèi)都是組件兆衅,但他們要想要上升成為控件卻很難地沮。因?yàn)榇蠖嘟M件代碼,都無(wú)法像系統(tǒng)控件那樣獨(dú)立完成一項(xiàng)目任務(wù)羡亩,其原因之一是濫用組件的properties可視化編輯功能摩疑,將本職范圍內(nèi)的節(jié)點(diǎn)做為成員變量,目的僅僅是為了方便訪(fǎng)問(wèn)畏铆。
[圖片上傳失敗...(image-346e88-1518414298577)]
從Creator范例工程中的TestList首場(chǎng)景為例雷袋,Menu.js組件腳本掛載到Menu節(jié)點(diǎn)上,最后一個(gè)Menu.testList屬性設(shè)置是非當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn)辞居,控制權(quán)延生到了外面去了楷怒。前面幾個(gè)屬性(Text, Readme...)都是通過(guò)編輯器拖拽將Menu節(jié)點(diǎn)下的幾個(gè)子節(jié)點(diǎn)配置到了組件腳本上,他們對(duì)于Menu.js應(yīng)該屬于私有成員變量瓦灶,也變成了公開(kāi)的了鸠删。
通過(guò)簡(jiǎn)單拖拽配置成員屬性確實(shí)讓程序開(kāi)發(fā)變的簡(jiǎn)單,但如果濫用會(huì)有一個(gè)嚴(yán)重的問(wèn)題:控件屬性由原來(lái)的點(diǎn)狀(控制自身節(jié)點(diǎn))或線(xiàn)性(控制子節(jié)點(diǎn)或成員節(jié)點(diǎn))關(guān)系贼陶,變成了網(wǎng)狀關(guān)系(控制自身以外的節(jié)點(diǎn))刃泡。
這將導(dǎo)致組件腳本難以獨(dú)立完成任務(wù)和測(cè)試巧娱,必須通過(guò)編輯器正確配置才能工作,就像在一個(gè)模塊代碼中訪(fǎng)問(wèn)了全局變量一樣烘贴。要讓Menu.js成為控件的辦法禁添,最好是將TestList節(jié)點(diǎn)放到Menu節(jié)點(diǎn)內(nèi)部。把Menu節(jié)點(diǎn)拖到資源管理器中成為一個(gè)prefab桨踪。
不知道如何下手老翘,設(shè)置這些屬性
不知道大家有沒(méi)有遇到過(guò),在屬性檢查器上密密麻麻的屬性配置馒闷,不知道該如何下手酪捡?更讓人頭痛的是,不小心代碼沖突纳账,導(dǎo)致組件屬性配置丟了逛薇,再看代碼,腳本中的屬性變量與節(jié)點(diǎn)名字又對(duì)應(yīng)不上疏虫,就連編寫(xiě)這個(gè)模塊代碼的人都搞不懂是怎么會(huì)事永罚!
網(wǎng)狀關(guān)系的程序組織結(jié)構(gòu),會(huì)導(dǎo)至模塊之間相互依賴(lài)卧秘,可重用性極低呢袱。如何規(guī)范組件的編寫(xiě)方式,確保模塊的內(nèi)聚性值得我們多多思考翅敌。
二羞福、法寶與結(jié)界
下面來(lái)聊聊我總結(jié)的法寶與結(jié)界模型,假想一個(gè)完整的世界蚯涮,為了維護(hù)這個(gè)世界的有序運(yùn)行治专,設(shè)置了一個(gè)結(jié)界。結(jié)界中有無(wú)數(shù)的法寶參與到世界的運(yùn)行之中遭顶,貢獻(xiàn)出力量张峰。
1.法寶型組件
法寶型組件:以裝飾宿主節(jié)點(diǎn)為己任,從不控制其它節(jié)點(diǎn)棒旗。
法寶型的特點(diǎn)是通用性強(qiáng)喘批,可掛載任意節(jié)點(diǎn)運(yùn)行,Creator內(nèi)置的組件絕大多數(shù)屬于這類(lèi)铣揉。例如有Sprite饶深、Label、Button逛拱、Widget等粥喜,可以看出純腳本的組件就屬于法寶型。
2.結(jié)界型組件
結(jié)界型組件:管理和控制其它節(jié)點(diǎn)及節(jié)點(diǎn)上的組件橘券,通常會(huì)根據(jù)上層業(yè)務(wù)要求,調(diào)用其它節(jié)點(diǎn)的屬性方法完成任務(wù)。
結(jié)界型的特點(diǎn)是業(yè)務(wù)邏輯性強(qiáng)旁舰,通用性差锋华,通常是對(duì)法寶型組件的指揮和管理。組件+prefab就屬于這類(lèi)箭窜,由于結(jié)界型組件大多是定制的毯焕,它并且不能隨便掛載到別的節(jié)點(diǎn)上(更多的是只能掛載到唯一的節(jié)點(diǎn)上)。
3. 結(jié)界的秘密
話(huà)說(shuō)天有九重磺樱,九只是個(gè)虛數(shù)纳猫,其實(shí)是很多的意思。一個(gè)結(jié)界型組件竹捉,對(duì)于它的上層結(jié)界來(lái)說(shuō)芜辕,他又是一個(gè)法寶型組件,這就形成了模塊化块差。
比如有一個(gè)名為A的prefab侵续,將組件腳本A.js掛載到prefab的根結(jié)點(diǎn)。當(dāng)另一個(gè)場(chǎng)景或預(yù)制體中實(shí)例化這個(gè)A.prefab時(shí)憨闰,A.js就上升為一個(gè)控件状蜗,他管理了A.prefab下的所有節(jié)點(diǎn),但對(duì)于當(dāng)前場(chǎng)景來(lái)說(shuō)鹉动,它又體現(xiàn)為一個(gè)法寶型組件轧坎,而成為了一個(gè)控件。
對(duì)內(nèi)是結(jié)界泽示,從根節(jié)點(diǎn)開(kāi)始自下而下管理所有子節(jié)點(diǎn)态坦;對(duì)外是法寶,從根節(jié)點(diǎn)獲取法寶暴露的屬性方法铝量。這樣以?xún)?nèi)部線(xiàn)性秃症、總體樹(shù)狀的程序結(jié)構(gòu),是不是要比網(wǎng)狀的結(jié)構(gòu)更好些呢变姨?
三族扰、小結(jié)
uikiller庫(kù)是我在組件化編程上的一點(diǎn)成果,可以方便管理prefab下的任意節(jié)點(diǎn)和組件定欧,以及節(jié)點(diǎn)上的觸摸事件渔呵。奉上一段uikill的使用視頻 ,結(jié)束這篇分享砍鸠。
http://v.youku.com/v_show/id_XMzMxNzUxMzYzMg==.html?spm=a2hzp.8244740.0.0