看了《JavaScript高級(jí)程序設(shè)計(jì)》和網(wǎng)上的一些博客栏笆,感覺對(duì)函數(shù)節(jié)流和函數(shù)防抖的概念是反的森渐,以下我寫的關(guān)于防抖和節(jié)流的概念取決于多數(shù)人的概念吧,并且基于倫敦前端工程師David Corbacho的客座文章冒晰。文章寫的很好同衣,并且有對(duì)應(yīng)的代碼可以操作,更容易理解壶运。其實(shí)我覺得叫什么不重要乳怎,這個(gè)方法叫節(jié)流還是這個(gè)方法叫防抖,只要你能說明白前弯,并且在生產(chǎn)中能用上就可以蚪缀,一個(gè)名字,不用太去糾結(jié)恕出。
《復(fù)仇者聯(lián)盟4:終局之戰(zhàn)》代表著一個(gè)時(shí)代的結(jié)束询枚,從2008年高二看300多MB的《鋼鐵俠》開始,漫威電影宇宙也像哈利波特的魔法世界一樣一路伴我前行浙巫。一個(gè)時(shí)代的落幕金蜀,必將開始一個(gè)新的時(shí)代。End Game的畴?渊抄?No!
ILOVE YOU THREE THOUSANDS TIMES
IAM IRON MAN
banner獻(xiàn)給復(fù)仇者聯(lián)盟的超級(jí)英雄們:pray::pray::pray:
為什么要防抖和節(jié)流丧裁?护桦?
防抖和?節(jié)流?是兩個(gè)相似的技術(shù),都是為了減少一個(gè)函數(shù)無用的觸發(fā)次數(shù)煎娇,以便提高性能或者說避免資源浪費(fèi)二庵。我們都知道js在操作DOM的時(shí)候,代價(jià)非常昂貴催享,相對(duì)于非DOM操作需要更多的內(nèi)存和和CPU時(shí)間,假如我們一個(gè)函數(shù)是在滾動(dòng)滾動(dòng)條或者更改更改窗口大小的時(shí)候頻繁觸發(fā)哟绊,還是會(huì)出現(xiàn)頁面卡頓因妙,如果是一套復(fù)雜的操作DOM邏輯,可能還會(huì)引起瀏覽器崩潰票髓。所以我們需要控制一下觸發(fā)的次數(shù)攀涵,來優(yōu)化一下代碼執(zhí)行情況。
口說無憑炬称,大家可能也不了解到底是怎樣操作汁果,那就來個(gè)例子::arrow_down:
<!DOCTYPE html>我要節(jié)流body{height:3000px; }#centerNum{width:100px;height:100px;line-height:100px;text-align: center;position: fixed;left:50%;top:50%;transform:translate(-50%, -50%); }0varnum =0;window.onscroll =function(){varroot =document.getElementsByTagName('body'),? ? ? h =document.getElementById('centerNum');? ? ? h.innerHTML = num;? ? ? num ++;? ? }復(fù)制代碼
我們來一個(gè)?window.onscroll?的函數(shù),只要滾動(dòng)玲躯,就改變一次?<h1>?標(biāo)簽中的數(shù),在上面的圖中,我們能看到這個(gè)觸發(fā)是非常頻繁的跷车,如果我們不加以干涉的話棘利,讓這個(gè)函數(shù)肆意觸發(fā),豈不是要上天了:rage:
進(jìn)群:697699179可以獲取Java各類入門學(xué)習(xí)資料朽缴!
這是我的微信公眾號(hào)【編程study】各位大佬有空可以關(guān)注下善玫,每天更新Java學(xué)習(xí)方法,感謝密强!
學(xué)習(xí)中遇到問題有不明白的地方茅郎,推薦加小編Java學(xué)習(xí)群:697699179內(nèi)有視頻教程 ,直播課程 或渤,等學(xué)習(xí)資料系冗,期待你的加入
Debounce 防抖
什么是防抖
啥是防抖呢?我自己的理解就是薪鹦,當(dāng)連續(xù)觸發(fā)一個(gè)方法的時(shí)候掌敬,方法并不執(zhí)行,而是在連續(xù)觸發(fā)結(jié)束的時(shí)候再執(zhí)行這個(gè)方法池磁。
舉個(gè)例子:一部直梯奔害,陸續(xù)往上上人(連續(xù)觸發(fā)),當(dāng)不再上人的時(shí)候(停止連續(xù)觸發(fā))地熄,電梯才會(huì)關(guān)門并動(dòng)起來(執(zhí)行方法)华临。
如何實(shí)現(xiàn)呢
上面是我模擬電梯上人的例子做出來的,可能這樣看的比較直觀一些端考,下面有我實(shí)現(xiàn)的代碼银舱,大概意思就是當(dāng)我上人以后,電梯啟動(dòng)跛梗,當(dāng)我一直在上人的時(shí)候寻馏,電梯不動(dòng)直到不再上人了,才會(huì)關(guān)門啟動(dòng)
<!DOCTYPE html>電梯上人? 電梯上人核偿,人數(shù)+1重置電梯人數(shù):0(假設(shè)電梯可以無限裝人)電梯统锨罚靠varpersonNum =0;// 電梯人數(shù)varcloseDoor =null;// 電梯啟動(dòng)延時(shí)程序varaddBtn =document.getElementById('addBtn');// 獲取添加人數(shù)按鈕varpersonNumP =document.getElementById('personNum');// 獲取顯示人數(shù)的標(biāo)簽varresetBtn =document.getElementById('resetBtn');// 獲取重置按鈕varelevatorStatus =document.getElementById('elevatorStatus');// 獲取電梯狀態(tài)標(biāo)簽/**
? ? * @method 電梯內(nèi)添加人數(shù)
? ? * @description 點(diǎn)擊一次電梯內(nèi)增加一人,增加完人數(shù)電梯啟動(dòng)初始化
? ? */functionaddPerson(){? ? ? personNum ++;? ? ? personNumP.innerHTML =`電梯人數(shù):${personNum}(假設(shè)電梯可以無限裝人)`initElevatorStart();? ? }/**
? ? * @method 電梯啟動(dòng)
? ? * @description 電梯啟動(dòng)漾岳,置灰添加人數(shù)按鈕轰绵,禁止上人
? ? */functionelevatorStart(){? ? ? elevatorStatus.innerHTML ='電梯啟動(dòng)';? ? ? addBtn.disabled =true;? ? }/**
? ? * @method 電梯啟動(dòng)初始化
? ? * @description 清除之前的關(guān)門延時(shí),并重新計(jì)算關(guān)門延時(shí)500ms尼荆,意思是當(dāng)不在觸發(fā)電梯啟動(dòng)初始化函數(shù)時(shí)左腔,500ms后啟動(dòng)電梯
? ? */functioninitElevatorStart(){? ? ? clearTimeout(closeDoor);? ? ? closeDoor = setTimeout(function(){? ? ? ? elevatorStart();? ? ? },500);? ? }/**
? ? * @method 重置電梯
? ? */functionreset(){? ? ? personNum =0;? ? ? personNumP.innerHTML =`電梯人數(shù):${personNum}(假設(shè)電梯可以無限裝人)`elevatorStatus.innerHTML ='電梯停靠';? ? ? addBtn.disabled =false;? ? }? ? addBtn.addEventListener('click', addPerson);? ? resetBtn.addEventListener('click', reset);復(fù)制代碼
上面的代碼意思就是我電梯上一個(gè)人捅儒,就需要關(guān)閉電梯門(觸發(fā)?initElevatorStart()?方法)液样,然后電梯啟動(dòng)振亮。但是我一直在點(diǎn)擊上人的按鈕,電梯是不會(huì)觸發(fā)關(guān)門啟動(dòng)電梯的?elevatorStart()?方法鞭莽。
代碼的核心是?initElevatorStart()?方法,這個(gè)方法在實(shí)際需要執(zhí)行的關(guān)門啟動(dòng)電梯方法?elevatorStart()?外面添加了一層?setTimeout?方法澎怒,也就是為了在調(diào)用這個(gè)方法的時(shí)候我們過500毫秒再去執(zhí)行真正需要執(zhí)行的方法褒搔。如果這500毫秒之內(nèi),又重新觸發(fā)了?initElevatorStart()?方法喷面,就需要重新計(jì)時(shí)星瘾,要不不就夾到人了嘛,要賠錢的惧辈。琳状。。咬像。
這是防抖最粗糙的實(shí)現(xiàn)了:flushed::flushed::flushed:
基本形式
下面是這個(gè)防抖實(shí)現(xiàn)的最基本的形式算撮,也是我們?cè)凇禞avaScript高級(jí)程序設(shè)計(jì)》中看到的樣子:arrow_down:
varprocessor = {timeoutId:null,// 相當(dāng)于延時(shí)setTimeout的一個(gè)標(biāo)記,方便清除的時(shí)候使用// 實(shí)際進(jìn)行處理的方法// 連續(xù)觸發(fā)停止以后需要觸發(fā)的代碼performProcessiong:function(){// 實(shí)際執(zhí)行的代碼// 這里實(shí)際就是需要在停止觸發(fā)的時(shí)候執(zhí)行的代碼},// 初始處理調(diào)用的方法// 在實(shí)際需要觸發(fā)的代碼外面包一層延時(shí)clearTimeout方法县昂,以便控制連續(xù)觸發(fā)帶來的無用調(diào)用process:function(){? ? clearTimeout(this.timeoutId);// 先清除之前的延時(shí)肮柜,并在下面重新開始計(jì)算時(shí)間varthat =this;// 我們需要保存作用域,因?yàn)橄旅娴膕etTimeout的作用域是在window倒彰,調(diào)用不要我們需要執(zhí)行的this.performProcessiong方法this.timeoutId = setTimeout(function(){// 100毫秒以后執(zhí)行performProcessiong方法that.performProcessiong();? ? },100)// 如果還沒有執(zhí)行就又被觸發(fā)审洞,會(huì)根據(jù)上面的clearTimeout來清除并重新開始計(jì)算}};// 嘗試開始執(zhí)行processor.process();// 需要重新綁定在一個(gè)觸發(fā)條件里復(fù)制代碼
上面這段代碼就是最基本的實(shí)現(xiàn)方式,包在一個(gè)對(duì)象中待讳,然后在對(duì)象中互相調(diào)用芒澜,里面的注釋應(yīng)該可以很清楚的說明每一步是干什么呢,最下面的?processor.process()?我們?cè)趯?shí)際使用的時(shí)候肯定是需要綁定在一個(gè)觸發(fā)條件上的创淡,比如之前的上電梯問題上痴晦,我們就需要把?processor.process()?方法綁定在增加人數(shù)的里面,這樣才會(huì)有多次調(diào)用的情況發(fā)生
上面再怎么說都是很簡(jiǎn)單的實(shí)現(xiàn)琳彩,在實(shí)際生產(chǎn)環(huán)境中誊酌,邏輯會(huì)相對(duì)復(fù)雜很多,但是萬變不離其宗露乏,參透了最基礎(chǔ)的碧浊,再舉一反三就不是什么問題了
應(yīng)該叫“前搖”?瘟仿?
具體我也不知道應(yīng)該叫啥箱锐,英文叫“Leading edge”,甭管中文叫啥了劳较,知道是什么意思就行了驹止。之前我們寫的代碼很明顯可以看出來浩聋,在我們連續(xù)觸發(fā)一個(gè)方法的時(shí)候,是在?setTimeout?結(jié)束后才去真正執(zhí)行幢哨,但是還有一種情況赡勘,那就是我們?cè)谶B續(xù)觸發(fā)一個(gè)方法的時(shí)候嫂便,第一次觸發(fā)就執(zhí)行了捞镰,然后后面的連續(xù)觸發(fā)不再執(zhí)行,等連續(xù)觸發(fā)停止毙替,經(jīng)過延時(shí)以后岸售,再次觸發(fā)才會(huì)真正執(zhí)行。
我還是盜圖吧厂画。凸丸。。普遍的形式是下面這種
連續(xù)觸發(fā)結(jié)束時(shí)執(zhí)行袱院,而我們現(xiàn)在說的“前搖”則是下面這種情況
在連續(xù)觸發(fā)的一開始就執(zhí)行了屎慢,然后往后的連續(xù)觸發(fā)不執(zhí)行,連續(xù)觸發(fā)停止后再經(jīng)過延時(shí)時(shí)間后觸發(fā)才會(huì)再次執(zhí)行
下面是我自己寫的忽洛,大概意思是這樣腻惠,代碼實(shí)現(xiàn)也貼出來
<!DOCTYPE html>電梯上人? 電梯上人,人數(shù)+1重置電梯人數(shù):0(假設(shè)電梯可以無限裝人)varpersonNum =0;// 電梯人數(shù)varokNext =true;// 是否可進(jìn)行下次執(zhí)行vartimeoutFn =null;varaddBtn =document.getElementById('addBtn');// 獲取添加人數(shù)按鈕varpersonNumP =document.getElementById('personNum');// 獲取顯示人數(shù)的標(biāo)簽varresetBtn =document.getElementById('resetBtn');// 獲取重置按鈕/**
? ? * @method 電梯添加人數(shù)
? ? * @description 電梯可以上人欲虚,但是上人以后就不能再上了集灌,不管怎么觸發(fā)都不行,除非停止觸發(fā)500毫秒以后复哆,再觸發(fā)的時(shí)候才可以繼續(xù)執(zhí)行
? ? */functionaddPerson(){if(okNext) {? ? ? ? okNext =false;? ? ? ? personNum ++? ? ? ? personNumP.innerHTML =`電梯人數(shù):${personNum}(假設(shè)電梯可以無限裝人)`}? ? ? clearTimeout(timeoutFn);? ? ? timeoutFn = setTimeout(function(){? ? ? ? okNext =true;? ? ? },500)? ? }/**
? ? * @method 重置
? ? */functionreset(){? ? ? personNum =0;? ? ? personNumP.innerHTML ='電梯人數(shù):0(假設(shè)電梯可以無限裝人)';? ? }? ? addBtn.addEventListener('click', addPerson);? ? resetBtn.addEventListener('click', reset);復(fù)制代碼
上面代碼要是看不太明白欣喧,可以直接粘下去自己執(zhí)行以下看看是什么感覺,就知道是什么意思了梯找。
代碼純我自己寫的唆阿,要是有不對(duì)的地方,請(qǐng)大佬指正啊
Throttle 節(jié)流
什么是節(jié)流
節(jié)流呢锈锤,也是我自己的理解驯鳖,在連續(xù)觸發(fā)一個(gè)方法的某一時(shí)間段中,控制方法的執(zhí)行次數(shù)牙咏。
同樣舉個(gè)例子吧臼隔,一個(gè)地鐵進(jìn)站閘口,10秒進(jìn)一個(gè)人(10秒內(nèi)執(zhí)行一個(gè)方法)妄壶,管這10秒中來了是5個(gè)人摔握、10個(gè)人還是20個(gè)人,都只是進(jìn)一個(gè)人(從第一次觸發(fā)后10秒不管被觸發(fā)多少次都不會(huì)執(zhí)行丁寄,直到下一個(gè)10秒才會(huì)再執(zhí)行)氨淌。
如何實(shí)現(xiàn)呢泊愧??
時(shí)間戳
我們首先用時(shí)間戳來判斷前后的時(shí)間間隔盛正,然后就可以知道我從上次執(zhí)行完這個(gè)方法過了多久删咱,過了這么長(zhǎng)時(shí)間,是不是已經(jīng)超過了自己規(guī)定的時(shí)長(zhǎng)豪筝,如果時(shí)長(zhǎng)超過了痰滋,我就可以再次執(zhí)行了
<!DOCTYPE html>地鐵進(jìn)站進(jìn)站人數(shù)+1重置旅客總?cè)藬?shù):0進(jìn)站人數(shù):0varpersonNum =0;// 進(jìn)站人數(shù)varpersonTotal =0;// 一共來了多少人varaddBtn =document.getElementById('addBtn');// 獲取添加人數(shù)按鈕varpersonNumP =document.getElementById('personNum');// 獲取顯示人數(shù)的標(biāo)簽varpersonTotalP =document.getElementById('personTotal');// 獲取顯示總?cè)藬?shù)的標(biāo)簽varresetBtn =document.getElementById('resetBtn');// 獲取重置按鈕/**
? ? * @method 增加進(jìn)站人數(shù)
? ? * @description 每個(gè)時(shí)間間隔執(zhí)行的方法
? ? */functionaddPerson(){? ? ? personNum ++;? ? ? personNumP.innerHTML =`進(jìn)站人數(shù):${personNum}`;? ? }/**
? ? * @method 節(jié)流方法(時(shí)間戳)
? ? * @param {Function} fn 需要節(jié)流的實(shí)際方法
? ? * @param {Number} wait 需要控制的時(shí)間長(zhǎng)度
? ? * @description 根據(jù)上一次執(zhí)行的時(shí)間,和這一次執(zhí)行的時(shí)間做比較续崖,如果大于控制的時(shí)間敲街,就可以執(zhí)行
? ? */functionthrottle(fn, wait){varprev =0;// 第一次執(zhí)行的時(shí)候是0,所以第一次點(diǎn)擊的時(shí)候肯定大于這個(gè)數(shù)严望,所以會(huì)立馬執(zhí)行returnfunction(){varcontext =this;varargs =arguments;varnow =Date.now();// 實(shí)際執(zhí)行的時(shí)間personTotal ++;? ? ? ? personTotalP.innerHTML =`旅客總?cè)藬?shù):${personTotal}`;if(now - prev >= wait) {// 執(zhí)行的時(shí)間是不是比上次執(zhí)行的時(shí)間大于需要延遲的時(shí)間多艇,大于,我們就執(zhí)行fn.apply(context, args);? ? ? ? ? prev = now;// 執(zhí)行了以后像吻,重置上一次執(zhí)行的時(shí)間為剛剛執(zhí)行這次函數(shù)的時(shí)間峻黍,下次執(zhí)行就用這個(gè)時(shí)間為基準(zhǔn)}? ? ? }? ? }/**
? ? * @method 重置
? ? */functionreset(){? ? ? personNum =0;? ? ? personTotal =0;? ? ? personNumP.innerHTML ='進(jìn)站人數(shù):0';? ? ? personTotalP.innerHTML =`旅客總?cè)藬?shù):0`;? ? }? ? addBtn.addEventListener('click', throttle(addPerson,1000));? ? resetBtn.addEventListener('click', reset);復(fù)制代碼
節(jié)流函數(shù)?throttle?用到了作用域,call拨匆、apply和閉包等相關(guān)的知識(shí)姆涩,看不懂的可以看我之前的文章
《前端戰(zhàn)五渣學(xué)JavaScript——閉包》
《前端戰(zhàn)五渣學(xué)JavaScript——call、apply以及bind》
上面的代碼中我感覺可以很直觀的看出來是根據(jù)判斷前后兩次的時(shí)間涮雷,來得知可不可以進(jìn)行下一次函數(shù)的執(zhí)行阵面。參考著代碼中的注釋我覺得應(yīng)該可以看明白吧:flushed::flushed::flushed:
setTimeout
如果我們用?setTimeout?的話,我們只需要更改一下?throttle?方法
/**
* @method 節(jié)流方法(setTimeout)
* @param {Function} fn 需要節(jié)流的實(shí)際方法
* @param {Number} wait 需要控制的時(shí)間長(zhǎng)度
* @description 這個(gè)方法就很類似防抖了洪鸭,就是判斷當(dāng)前函數(shù)有沒有延遲setTimeout函數(shù)样刷,有的話就不執(zhí)行了
*/functionthrottle(fn, wait){vartimeout =null;returnfunction(){varcontext =this;varargs =arguments;? ? personTotal ++;? ? personTotalP.innerHTML =`旅客總?cè)藬?shù):${personTotal}`;if(!timeout) {varthat =this;? ? ? timeout = setTimeout(()=>{? ? ? ? timeout =null;? ? ? ? fn.apply(context, args)? ? ? }, wait)? ? }? }}復(fù)制代碼
雖然我們只需要更改幾行代碼就實(shí)現(xiàn)了用?setTimeout?實(shí)現(xiàn)節(jié)流的這個(gè)方法,但是我們仔細(xì)看上面的圖览爵,我們可以發(fā)現(xiàn)置鼻,當(dāng)我點(diǎn)擊第一次的時(shí)候,進(jìn)站旅客是沒有增加的蜓竹,這跟我們實(shí)際情況不一樣箕母,我們先來的,我不用等啊俱济,我直接就能進(jìn)站嘶是,對(duì)不對(duì)。還有當(dāng)我結(jié)束增加人數(shù)的時(shí)候蛛碌,進(jìn)站旅客過去等待時(shí)間以后還會(huì)加一個(gè)人聂喇,這當(dāng)然也不是我們想看到的。
使用時(shí)間戳還是setTimeout,取決于業(yè)務(wù)場(chǎng)景了
rAF(requestAnimationFrame)
誒希太?克饶?rAF是什么?什么是requestAnimationFrame誊辉?這在我沒有寫這篇博客的時(shí)候矾湃,我根本不知道window下還有個(gè)這個(gè)方法,神奇吧堕澄,那這個(gè)方法是干什么的呢邀跃??
告訴瀏覽器——你希望執(zhí)行一個(gè)動(dòng)畫奈偏,并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動(dòng)畫坞嘀。該方法需要傳入一個(gè)回調(diào)函數(shù)作為參數(shù)躯护,該回調(diào)函數(shù)會(huì)在瀏覽器下一次重繪之前執(zhí)行惊来。————《MDN Web Docs》
就是在用這個(gè)可以一直重繪動(dòng)畫棺滞,然后讓人看起來是個(gè)動(dòng)畫裁蚁,重繪的這個(gè)過程是個(gè)很頻繁的操作,所以如果我們自己寫继准,不加以干涉枉证,在性能和資源上會(huì)造成嚴(yán)重的浪費(fèi),所以我們可以使用requestAnimationFrame來使用我們的動(dòng)畫看起來很流暢移必,又不會(huì)頻繁調(diào)用
優(yōu)點(diǎn)
目標(biāo)是60fps(16毫秒的一幀)室谚,瀏覽器將決定如何安排渲染的最佳時(shí)間。
相對(duì)簡(jiǎn)單和標(biāo)準(zhǔn)的API崔泵,未來不會(huì)改變秒赤,減少維護(hù)成本。
缺點(diǎn)
rAF是內(nèi)部api憎瘸,所以我們并不方便修改
如果瀏覽器選項(xiàng)卡沒有激活入篮,就用不了
兼容性不好,在IE9幌甘,Opera Mini和舊Android中仍然不支持
node中不能使用
讓我們來使用rAF吧
直接上圖
<!DOCTYPE html>rAF使用#SomeElementYouWantToAnimate{width:100px;height:100px;background-color:#000;? ? }varstart =null;varelement =document.getElementById('SomeElementYouWantToAnimate');? ? element.style.position ='absolute';/**
? ? * @method 移動(dòng)我們的小黑方塊
? ? */functionstep(timestamp){if(!start) start = timestamp;varprogress = timestamp - start;? ? ? element.style.left =Math.min(progress /10,200) +'px';if(progress <2000) {window.requestAnimationFrame(step);? ? ? }? ? }window.requestAnimationFrame(step);復(fù)制代碼
總結(jié)
rAF是一個(gè)內(nèi)部api潮售,固定的16毫秒執(zhí)行一次,因?yàn)槿搜劢邮?0fps的動(dòng)畫就會(huì)感到很流暢了锅风,如果我們需要改變r(jià)AF的執(zhí)行時(shí)間酥诽,那我們只能自己去寫動(dòng)畫的方法,節(jié)流還是防抖皱埠,看個(gè)人愛好了
收官
防抖:連續(xù)觸發(fā)一個(gè)函數(shù)肮帐,不管是觸發(fā)開始執(zhí)行還是結(jié)束執(zhí)行,只要在連續(xù)觸發(fā)漱逸,就只執(zhí)行一次
節(jié)流:規(guī)定時(shí)間內(nèi)只執(zhí)行一次泪姨,不管是規(guī)定時(shí)間內(nèi)被觸發(fā)了多少次
rAF:也算是一種節(jié)流手段游沿,原生api,旨在使動(dòng)畫在盡量少占用資源的情況下使動(dòng)畫流暢
lodash中相對(duì)應(yīng)的_.throttle和_.debounce肮砾,在我看來是最佳實(shí)踐了诀黍,推薦使用
End Game
《復(fù)仇者聯(lián)盟4》現(xiàn)階段的漫威宇宙的結(jié)束,《哈利·波特》《火影忍者》一個(gè)個(gè)完結(jié)的電影仗处,雖然在時(shí)刻提醒著我們青春再慢慢的消失眯勾,正如英雄聯(lián)盟中的那句話,我們有了新的敵人叫“生活”婆誓。當(dāng)這些完結(jié)的并不是真正的結(jié)束吃环,《哈利·波特》有《神奇動(dòng)物在哪里》,《火影忍者》有《博人傳》洋幻,《鋼鐵俠》有《蜘蛛俠》郁轻,晚輩從前輩手中接過接力棒,繼續(xù)往后跑文留,我們也從自己青蔥的歲月進(jìn)入下一階段好唯,努力奮斗吧!燥翅!