我在Vue動(dòng)態(tài)組件上的坑上重復(fù)踩了兩次蹂风,一模一樣的兩次思考過(guò)程。
我想乾蓬,這個(gè)重復(fù)思考的過(guò)程并不是偶然惠啄,說(shuō)明是很有必要討論一下這個(gè)問(wèn)題的。
那么為了這個(gè)意義,我來(lái)說(shuō)一下最近遇到的問(wèn)題撵渡,有關(guān)于『 Vue動(dòng)態(tài)組件 』的問(wèn)題融柬。
由于本人平時(shí)經(jīng)常做的事就是操作表單,Vue的數(shù)據(jù)綁定和樣式綁定等特別適合我現(xiàn)在的開(kāi)發(fā)模式趋距。但是表單常出現(xiàn)的CURD粒氧,就不是簡(jiǎn)單的雙向綁定那么簡(jiǎn)單的操作了。
首先對(duì)想要實(shí)現(xiàn)的功能進(jìn)行簡(jiǎn)短的描述:由于模板數(shù)據(jù)的Keyword是動(dòng)態(tài)添加的节腐,需要寫一條就增加一條keyword記錄并輸出外盯,而輸出的keyword需要可以進(jìn)行修改和刪除操作;在進(jìn)行修改操作的時(shí)候铜跑,選中的記錄會(huì)綁定到輸入框中门怪,在輸入框中進(jìn)行修改后,能實(shí)現(xiàn)雙向綁定到列表中的數(shù)據(jù)上锅纺;刪除操作掷空,就是刪除當(dāng)前選中的記錄;最后點(diǎn)擊提交的時(shí)候要能夠把所有的keyword的作為一個(gè)數(shù)組囤锉,添加到目標(biāo)對(duì)象中去坦弟。
這是最簡(jiǎn)單不過(guò)的增刪查改,用jQuery來(lái)解決的時(shí)候官地,考驗(yàn)的就是對(duì)數(shù)組結(jié)構(gòu)的操作酿傍。但是如果要把他寫成組件,將面臨『動(dòng)態(tài)組件』的問(wèn)題驱入。
我一開(kāi)始思考這個(gè)問(wèn)題的時(shí)候赤炒,并不是打算將所有的keyword作為一個(gè)列表輸出,然后在列表上進(jìn)行修改和刪除操作亏较。而是打算只要點(diǎn)擊“添加關(guān)鍵字”莺褒,就動(dòng)態(tài)插入輸入框,并為每個(gè)輸入框綁定v-model雪情,這樣就能夠?qū)崿F(xiàn)實(shí)時(shí)的刪除和修改操作遵岩。
--------------------!!!然而這樣的思路是錯(cuò)誤的!!!--------------------
因?yàn)樗悸肥清e(cuò)誤的,所以按照錯(cuò)誤的思路巡通,第一步想要實(shí)現(xiàn)的就是動(dòng)態(tài)生成組件尘执。?
這是html部分, 在父級(jí)宴凉,主要是一個(gè)div用來(lái)插入組件誊锭,一個(gè)button用來(lái)觸發(fā)插入事件。
在組件部分弥锄,主要是一個(gè)header用來(lái)觸發(fā)一個(gè)測(cè)試點(diǎn)擊事件炉旷,用來(lái)測(cè)試是否能夠調(diào)用組件的methods签孔,并且有一個(gè)img標(biāo)簽,用來(lái)測(cè)試是否能夠讀取構(gòu)造組件時(shí)候的data窘行。
這是js部分饥追,先是創(chuàng)建了一個(gè)組件about的構(gòu)造器,它對(duì)應(yīng)的組件id是html中的#about罐盔,構(gòu)造組件的data只能是一個(gè)function但绕,真正的data可以作為一個(gè)對(duì)象寫在function的return中。我們現(xiàn)在構(gòu)造的這個(gè)about組件中的data返回的是一個(gè)img的src惶看,它的methods是點(diǎn)擊之后log捏顺。
在model中注冊(cè)了組件about,使用構(gòu)造函數(shù)new了一個(gè)about纬黎。并將new出來(lái)的about組件手動(dòng)掛載($mount)到model實(shí)例中去幅骄,然后再在相應(yīng)的dom結(jié)構(gòu)(#main)中插入($appendTo)組件。這樣每次點(diǎn)擊“添加組件”按鈕的時(shí)候就能夠本今,新注冊(cè)一個(gè)about組件拆座,并手動(dòng)掛載后插入。
這樣就實(shí)現(xiàn)動(dòng)態(tài)生成組件冠息,但是這樣生成的組件只是簡(jiǎn)單的進(jìn)行數(shù)據(jù)渲染挪凑,而并不存在表單操作。所以離一開(kāi)始我的錯(cuò)誤思路只差一步逛艰,那就是給插入的組件進(jìn)行雙向綁定躏碳。
這里順便一提,對(duì)于上傳到七牛上的圖片文件的在線鏈接散怖,能夠利用在鏈接后面增加參數(shù)菇绵,達(dá)到壓縮圖片的效果。如上圖镇眷,關(guān)鍵字就是『 ?imageView2/1 』咬最,之后的參數(shù)『w』『h』和『q』是設(shè)置寬、高和圖片質(zhì)量的參數(shù)偏灿。
這就是實(shí)現(xiàn)的效果丹诀,一開(kāi)始只有一個(gè)按鈕钝的,點(diǎn)擊按鈕之后翁垂,動(dòng)態(tài)插入了組件about。
利用extend 硝桩、$mount沿猜、 $appendTo實(shí)現(xiàn)了動(dòng)態(tài)插入組件,之后我又新建了一個(gè)demo用于實(shí)現(xiàn)動(dòng)態(tài)組件的雙向綁定碗脊。
先上一下效果圖啼肩,然后就會(huì)知道這樣做的思路是多么的愚蠢。
輸入框中的內(nèi)容純粹是為了測(cè)試用,下同~
第一步祈坠,頁(yè)面自帶一個(gè)原始的表單害碾,表單包括兩個(gè)項(xiàng)目,學(xué)校名稱和學(xué)校網(wǎng)址赦拘。這個(gè)表單綁定的是我的數(shù)組對(duì)象的第0個(gè)元素慌随。
第二步,當(dāng)我點(diǎn)擊“添加組件”按鈕之后躺同,我會(huì)動(dòng)態(tài)插入一個(gè)表單阁猜,在數(shù)組對(duì)象中push一個(gè)空對(duì)象,并log出我的對(duì)象蹋艺。
我插入的表單組件中的項(xiàng)目依然是學(xué)校名稱和學(xué)校網(wǎng)址剃袍,并且我讓插入的表單組件的輸入框綁定我數(shù)組的第(length-1)個(gè)元素。這樣我在輸入框中進(jìn)行的數(shù)據(jù)操作能夠通過(guò)雙向綁定寫入目標(biāo)對(duì)象捎谨。在這一步民效,我在輸入框輸入的是“集美大學(xué)”和"www.hao123.com"。到這里看上去似乎一切都是正常的侍芝,接下來(lái)研铆,肯定會(huì)需要再次進(jìn)行push操作。
第三步州叠,再次點(diǎn)擊“添加組件”按鈕之后棵红,依然是動(dòng)態(tài)插入了一個(gè)數(shù)組,并且數(shù)組對(duì)象中push了一個(gè)空對(duì)象咧栗。數(shù)組長(zhǎng)度為3逆甜。
我們可以從控制臺(tái)看出,我的數(shù)組對(duì)象是正確的致板。第0個(gè)元素是“廈門大學(xué)”交煞,第1個(gè)元素是“集美大學(xué)”。值得一提的是由于log的操作是在點(diǎn)擊“添加組件”斟或,然后插入空對(duì)象之后觸發(fā)的素征,所以我現(xiàn)在新輸入的數(shù)組的第三個(gè)元素“123”并沒(méi)有在控制臺(tái)中輸出,但是我只要在輸入框中進(jìn)行數(shù)據(jù)操作萝挤,實(shí)際上它是寫入目標(biāo)數(shù)組的御毅,并不是數(shù)組對(duì)象的第3個(gè)元素沒(méi)有寫入。
同時(shí)怜珍,注意頁(yè)面上動(dòng)態(tài)組件的變化端蛆,當(dāng)我在第三個(gè)表單中填寫“123”和“456”的時(shí)候,第二個(gè)表單的內(nèi)容也發(fā)生的相應(yīng)的變化酥泛,一方面說(shuō)明今豆,我的雙向綁定是有成功寫入目標(biāo)數(shù)組的嫌拣,另一方面,說(shuō)明表單組件的輸入框如果綁定的是第(length-1)個(gè)的數(shù)組元素的話呆躲,length的值也是隨著數(shù)組變化而變化的异逐。所以會(huì)出現(xiàn)第二個(gè)表單的內(nèi)容會(huì)跟隨我在第三個(gè)表單的輸入框中的輸入值進(jìn)行動(dòng)態(tài)變化。
這里會(huì)有幾個(gè)疑問(wèn):
1.有人會(huì)認(rèn)為插掂,【反正提交給后臺(tái)的數(shù)組是正確的不就好了嗎】应役,那么要做到這樣的前提就是【每一次的操作都是準(zhǔn)確無(wú)誤的操作】。因?yàn)楝F(xiàn)在這樣燥筷,已經(jīng)無(wú)法做到刪除和修改箩祥。
2.有人會(huì)認(rèn)為,【只要每次給輸入框綁定事先經(jīng)過(guò)計(jì)算的(length-1)的結(jié)果不就好了嗎】肆氓,那么為了這個(gè)要求袍祖,需要重新構(gòu)造對(duì)象的屬性。這個(gè)對(duì)象會(huì)在原來(lái)的“學(xué)校名稱”和“學(xué)校網(wǎng)址”的基礎(chǔ)上再多一個(gè)屬性比如叫“currentLength”谢揪,專門用來(lái)記錄創(chuàng)建對(duì)象那個(gè)時(shí)刻的(length-1)的結(jié)果蕉陋,比如“集美大學(xué)”的兄弟屬性“currentLength”就應(yīng)該為1,“123”的兄弟屬性“currentLength”就應(yīng)該為2拨扶。但是我在傳json給后臺(tái)的時(shí)候凳鬓,并不需要這個(gè)“currentLength”,那么又要重新創(chuàng)建一個(gè)對(duì)象患民。這樣就失去雙向綁定可以不用構(gòu)造對(duì)象的意義了缩举。
3.有人會(huì)認(rèn)為,【可能會(huì)需要一個(gè)提交當(dāng)前表單的操作】匹颤,這個(gè)是沒(méi)有必要的操作仅孩,因?yàn)殡p向綁定,本身就是動(dòng)態(tài)寫入的印蓖。只要你在綁定的輸入框中輸入相應(yīng)的數(shù)據(jù)辽慕,原先的數(shù)組對(duì)象的元素都會(huì)改變的。
我們來(lái)看下這個(gè)實(shí)現(xiàn)動(dòng)態(tài)綁定組件的代碼吧~
這是html的代碼赦肃,父級(jí)#main中本身就有一個(gè)section存放表單溅蛉,表單的輸入框綁定的是目標(biāo)對(duì)象companies的第0個(gè)元素。組件部分綁定的是目標(biāo)對(duì)象的第(length-1)個(gè)對(duì)象他宛。
這是js的代碼船侧,構(gòu)建組件的data的時(shí)候,要先讓companies從model實(shí)例中傳過(guò)來(lái)堕汞,用一個(gè)新的對(duì)象com來(lái)存勺爱。在父級(jí)#main的button觸發(fā)了點(diǎn)擊事件之后晃琳,先push了一個(gè)空對(duì)象讯检,然后用之前的$mount進(jìn)行手動(dòng)掛載琐鲁,最后打印當(dāng)前數(shù)組。
思考這個(gè)問(wèn)題人灼,思考了好幾個(gè)小時(shí)围段,連次晚飯的時(shí)候都在想啊M斗拧D卫帷!依稀記得那天吃的西北拉面灸芳。就連跟柯哲吃飯的時(shí)候涝桅,柯哲問(wèn)我,”明天學(xué)校的考試是最后一科嗎“烙样,我都懶得回答冯遂,只是點(diǎn)了個(gè)頭。我想谒获,柯哲當(dāng)時(shí)肯定心想(′???`) “這個(gè)傻×”
--------------------!!!然而接下來(lái)的思路是正確的!!!--------------------
發(fā)現(xiàn)不能利用動(dòng)態(tài)組件來(lái)解決表單的問(wèn)題蛤肌,所以就換一個(gè)思路,固定一個(gè)表單批狱,而不需要?jiǎng)討B(tài)添加表單裸准。另外設(shè)置一個(gè)表單顯示目標(biāo)數(shù)組,然后把需要進(jìn)行操作的對(duì)象綁定到那個(gè)固定的表單中去赔硫。
話不多說(shuō)炒俱,舉一個(gè)例子,<動(dòng)態(tài)添加單項(xiàng)選擇題的選項(xiàng)> 爪膊,先上效果圖向胡。
我在第一個(gè)紅框中輸入我要錄入的信息,點(diǎn)擊“添加一個(gè)選項(xiàng)”按鈕惊完,然后能夠第二個(gè)紅框中進(jìn)行動(dòng)態(tài)渲染我的目標(biāo)對(duì)象中的每一個(gè)元素僵芹。在點(diǎn)擊“修改”按鈕后,能夠?qū)Ⅻc(diǎn)擊的這個(gè)元素動(dòng)態(tài)渲染到第一個(gè)紅框中的表單中小槐,這樣就能夠通過(guò)輸入框進(jìn)行實(shí)時(shí)更新數(shù)據(jù)操作拇派。在點(diǎn)擊“刪除”按鈕后,能夠刪除當(dāng)前元素凿跳。需要明確的一點(diǎn)就是件豌,第二個(gè)紅框中的列表顯示的每一個(gè)框,就是我【當(dāng)前目標(biāo)數(shù)組中的實(shí)時(shí)元素】控嗜。
如圖茧彤,我先添加了B和C兩個(gè)選項(xiàng)。具體的操作就是在輸入框中輸入數(shù)據(jù)疆栏,然后點(diǎn)擊“新增一個(gè)選項(xiàng)”曾掂,就能夠在底下的顯示區(qū)域動(dòng)態(tài)渲染每個(gè)選項(xiàng)惫谤。
如果我點(diǎn)擊了”編輯“按鈕,當(dāng)前元素就會(huì)被動(dòng)態(tài)渲染到輸入框中珠洗。如果我在輸入框進(jìn)行修改溜歪,底下的顯示區(qū)域也是實(shí)時(shí)動(dòng)態(tài)修改的。
如果我點(diǎn)擊了”刪除“按鈕许蓖,當(dāng)前元素就會(huì)從目標(biāo)對(duì)象中移除蝴猪。
接下來(lái)看下代碼:
這是html代碼,父級(jí)中的兩個(gè)輸入框綁定的對(duì)象是newoption膊爪,這個(gè)對(duì)象就像是一個(gè)中介自阱,如果需要push新對(duì)象到目標(biāo)數(shù)組,就先把值寫入newoption米酬,然后把newoption的值push到目標(biāo)數(shù)組中去动壤。如果需要修改目標(biāo)數(shù)組的元素,就把需要修改的元素的值傳給newoption淮逻,然后通過(guò)和newoption綁定的輸入框進(jìn)行數(shù)據(jù)渲染和修改琼懊。
其中#table的作用就是用一個(gè)v-for循環(huán)來(lái)動(dòng)態(tài)輸出目標(biāo)對(duì)象的每個(gè)元素,目標(biāo)對(duì)象就是list.options爬早。并且每個(gè)元素都有”編輯“和”刪除“操作哼丈。
這是js代碼中的數(shù)據(jù)部分,其中options是我的目標(biāo)數(shù)組對(duì)象筛严。而newoption是我的中介對(duì)象醉旦。
newoption對(duì)象會(huì)動(dòng)態(tài)存儲(chǔ)我在輸入框中輸入的數(shù)據(jù)。
這是在點(diǎn)擊”增加一個(gè)選項(xiàng)“的時(shí)候觸發(fā)的事件桨啃。
把newoption中的值push進(jìn)目標(biāo)數(shù)組车胡。此時(shí)的this的指向是model實(shí)例。注意push的寫法照瘾。當(dāng)push成功后匈棘,選項(xiàng)列表是能夠馬上動(dòng)態(tài)渲染options的元素的(這個(gè)點(diǎn)我強(qiáng)調(diào)了好幾次,Vue的雙向綁定)析命。插入之后不需要對(duì)newoption進(jìn)行初始化主卫。
這是在點(diǎn)擊”編輯“的時(shí)候觸發(fā)的事件。
把options對(duì)應(yīng)下標(biāo)的元素傳給newoption鹃愤,用于進(jìn)行動(dòng)態(tài)修改簇搅。$index.指的就是循環(huán)中的”op“的下標(biāo)。此時(shí)的newoption和options[$index]都是指向同一個(gè)元素软吐。
這是在點(diǎn)擊”刪除“的時(shí)候觸發(fā)的事件瘩将。
”op“指的是當(dāng)前在循環(huán)中渲染的元素,把當(dāng)前的元素對(duì)象$remove了,就完成了刪除的操作姿现。
表單中的其他的數(shù)據(jù)渲染不存在數(shù)組的增刪查改肠仪,所以就不詳細(xì)說(shuō)明了。點(diǎn)擊網(wǎng)頁(yè)上的”提交“按鈕的操作只需要把data中的list對(duì)象通過(guò)ajax傳給后臺(tái)就好建钥,并不需要自己構(gòu)造數(shù)組對(duì)象。
這樣才能算是實(shí)現(xiàn)了一個(gè)表單最基本的動(dòng)態(tài)綁定虐沥。
嗯熊经。這就是在動(dòng)態(tài)組件上的思考過(guò)程。初次發(fā)文欲险,謝謝大家镐依。差不多了,我去吃個(gè)草莓天试。