欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

vue中的mounted鉤子怎么用

這篇文章主要為大家展示了“vue中的mounted鉤子怎么用”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“vue中的mounted鉤子怎么用”這篇文章吧。

目前創(chuàng)新互聯(lián)已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、蒙城網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

vue中的mounted鉤子怎么用

注:閱讀本文需要對vue的patch流程有較清晰的理解,如果不清楚patch流程,建議先了解清楚這個(gè)流程再閱讀本文,否則可能會感覺云里霧里。

聊之前我們先看一個(gè)場景

<div id="app">
    <aC />
    <bC />
</div>

如上所示,App.vue文件里面有兩個(gè)子組件,互為兄弟關(guān)系

組件里面自各有created和mounted兩個(gè)生命周期鉤子,a表示組件名 C是created的縮寫

// a組件
created() {
    console.log('aC')
  },
mounted() {
  debugger
  console.log('aM')
},

// b組件
created() {
    console.log('bC')
  },
mounted() {
  debugger
  console.log('bM')
},

請問打印順序是什么?各位讀者可以先腦補(bǔ)一下,后面看看對不對。

如果對vue patch流程比較熟悉的讀者,可能會認(rèn)為順序是aC→aM→bC→BM,也就是a組件先創(chuàng)建,再掛載,然后到b組件重復(fù)以上流程。因?yàn)閺膒atch的方法里面可以知道,組件created后,再走到insert進(jìn)父容器的過程,是一個(gè)同步的流程,只有這個(gè)流程走完后,才會遍歷到b組件,走b組件的渲染流程。

實(shí)際上瀏覽器打印出來的順序是aC→bC→aM→bM,也就是兩個(gè)created先執(zhí)行,才到mounted執(zhí)行,和上面的分析相悖。這里先說原因,子組件從created到insert進(jìn)父容器的過程還是同步的,但是insert進(jìn)父容器后,也可以理解為子組件mounted,并沒有馬上調(diào)用mounted生命周期鉤子。下面從源碼角度分析一下:

先大概回顧一下子組件渲染流程,patch函數(shù)調(diào)用createElm創(chuàng)建真實(shí)element,createElm里面通過createComponent判斷當(dāng)前vnode是否組件vnode,是則進(jìn)入組件渲染流程

function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
    var i = vnode.data;
    if (isDef(i)) {
      var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;
      if (isDef(i = i.hook) && isDef(i = i.init)) {
        i(vnode, false /* hydrating */);
      }
      if (isDef(vnode.componentInstance)) {
        initComponent(vnode, insertedVnodeQueue);
				// 最終組件創(chuàng)建完后會走到這里 把組件對應(yīng)的el插入到父節(jié)點(diǎn)
        insert(parentElm, vnode.elm, refElm);
        if (isTrue(isReactivated)) {
          reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);
        }
        return true
      }
    }
  }

createComponent里面就把組件對應(yīng)的el插入到父節(jié)點(diǎn),最后會返回到patch調(diào)用棧,調(diào)用

invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);

因?yàn)樽咏M件有vnode.parent所以會走一個(gè)分支,但是我們也看看第二個(gè)分支調(diào)用的insert是什么

function invokeInsertHook (vnode, queue, initial) {
    // delay insert hooks for component root nodes, invoke them after the
    // element is really inserted
    if (isTrue(initial) && isDef(vnode.parent)) {
      vnode.parent.data.pendingInsert = queue;
    } else {
      for (var i = 0; i < queue.length; ++i) {
        queue[i].data.hook.insert(queue[i]);
      }
    }
  }

這個(gè)insert是掛在vnode.data.hook上,在組件創(chuàng)建過程中,createComponent方法里面有一個(gè)調(diào)用

installComponentHooks,在這里把insert鉤子注入了。這個(gè)方法實(shí)際定義在componentVNodeHooks對象里面,可以看到這個(gè)insert里面調(diào)用了callHook(componentInstance, 'mounted'),這里實(shí)際上就是調(diào)用子組件的mounted生命周期。

insert: function insert (vnode) {
    var context = vnode.context;
    var componentInstance = vnode.componentInstance;
    if (!componentInstance._isMounted) {
      componentInstance._isMounted = true;
      callHook(componentInstance, 'mounted');
    }
    if (vnode.data.keepAlive) {
      if (context._isMounted) {
        // vue-router#1212
        // During updates, a kept-alive component's child components may
        // change, so directly walking the tree here may call activated hooks
        // on incorrect children. Instead we push them into a queue which will
        // be processed after the whole patch process ended.
        queueActivatedComponent(componentInstance);
      } else {
        activateChildComponent(componentInstance, true /* direct */);
      }
    }
  },

再來看看這個(gè)方法,子組件走第一個(gè)分支,僅僅執(zhí)行了一行代碼vnode.parent.data.pendingInsert = queue , 這個(gè)queue實(shí)際是在patch 開始時(shí)候,定義的insertedVnodeQueue。這里的邏輯就是把當(dāng)前的insertedVnodeQueue,掛在parent的vnode data的pendingInsert上。

function invokeInsertHook (vnode, queue, initial) {
    // delay insert hooks for component root nodes, invoke them after the
    // element is really inserted
    if (isTrue(initial) && isDef(vnode.parent)) {
      vnode.parent.data.pendingInsert = queue;
    } else {
      for (var i = 0; i < queue.length; ++i) {
        queue[i].data.hook.insert(queue[i]);
      }
    }
  }

// 在patch 開始時(shí)候 定義了insertedVnodeQueue為一個(gè)空數(shù)組
var insertedVnodeQueue = [];

源碼里面再搜索insertedVnodeQueue ,可以看到有這樣一段邏輯,initComponent還是在createComponent里面調(diào)用的

function initComponent (vnode, insertedVnodeQueue) {
    if (isDef(vnode.data.pendingInsert)) {
      insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert);
      vnode.data.pendingInsert = null;
    }
    vnode.elm = vnode.componentInstance.$el;
    if (isPatchable(vnode)) {
			// ??注意這個(gè)方法 
      invokeCreateHooks(vnode, insertedVnodeQueue);
      setScope(vnode);
    } else {
      // empty component root.
      // skip all element-related modules except for ref (#3455)
      registerRef(vnode);
      // make sure to invoke the insert hook
      insertedVnodeQueue.push(vnode);
    }
  }

insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert) 重點(diǎn)看這一行代碼,把 vnode.data.pendingInsert這個(gè)數(shù)組每一項(xiàng)push到當(dāng)前vnode的insertedVnodeQueue中,注意這里是通過apply的方式,所以是把 vnode.data.pendingInsert這個(gè)數(shù)組每一項(xiàng)都push,而不是push pendingInsert這個(gè)列表進(jìn)去。也就是說在這里,組件把他的子組件的insertedVnodeQueue里面的item收集了,因?yàn)殇秩臼且粋€(gè)深度遞歸的過程,所有最后根組件的insertedVnodeQueue能拿到所有子組件的insertedVnodeQueue里面的每一項(xiàng)。

從invokeInsertHook的queue[i].data.hook.insert(queue[i]) 這一行可以看出,insertedVnodeQueue里面的item應(yīng)該是vnode。源碼中搜索insertedVnodeQueue.push ,可以發(fā)現(xiàn)是invokeCreateHooks這個(gè)方法把當(dāng)前vnode push了進(jìn)去。

function invokeCreateHooks (vnode, insertedVnodeQueue) {
    for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {
      cbs.create[i$1](emptyNode, vnode);
    }
    i = vnode.data.hook; // Reuse variable
    if (isDef(i)) {
      if (isDef(i.create)) { i.create(emptyNode, vnode); }
	     // 把當(dāng)前vnode push 到了insertedVnodeQueue
      if (isDef(i.insert)) { insertedVnodeQueue.push(vnode); }
    }
  }

對于組件vnode來說,這個(gè)方法還是在initComponent中調(diào)用的。

到這里就很清晰,子組件insert進(jìn)父節(jié)點(diǎn)后,并不會馬上調(diào)用mounted鉤子,而是把組件對應(yīng)到vnode插入到父vnode的insertedVnodeQueue中,層層遞歸,最終根組件拿到所有子組件的vnode,再依次循環(huán)遍歷,調(diào)用vnode的insert鉤子,從而調(diào)用了mounted鉤子。這里是先進(jìn)先出的,第一個(gè)被push進(jìn)去的第一個(gè)被拿出來調(diào)用,所以最深的那個(gè)子組件的mounted先執(zhí)行。最后附上一張?jiān)创a調(diào)試的圖,可以清晰的看到根組件的insertedVnodeQueue是什么內(nèi)容。

至于為什么vue要這樣設(shè)計(jì),是因?yàn)閽燧d是先子后父的,子組件插入到了父節(jié)點(diǎn),但是父節(jié)點(diǎn)還沒有真正插入到頁面中,如果這時(shí)候立馬調(diào)用子組件的mounted,對框架使用者來說可能會造成困惑,因?yàn)樽咏M件調(diào)用mounted的時(shí)候并沒有真正渲染到頁面中,而且此時(shí)也肯定也無法通過document.querySelector的方式操作dom。

以上是“vue中的mounted鉤子怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

標(biāo)題名稱:vue中的mounted鉤子怎么用
當(dāng)前地址:http://aaarwkj.com/article10/gghhgo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作網(wǎng)站策劃、品牌網(wǎng)站建設(shè)、全網(wǎng)營銷推廣網(wǎng)站導(dǎo)航、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管
久久九特黄的免费大片| 日韩国产欧美一区二区在线视频| 亚洲精品麻豆一区二区| 外国男人搞亚洲女人在线| 国产我不卡在线观看免费| 日韩精品成人区中文字幕| 国产欧美高清在线观看视频| 亚洲av天堂一区二区香蕉| 亚洲一区二区三区国色天香| 欧美老熟妇一区三区精品| 91黄色国产在线播放| 国产一级特黄大片特爽| 在线成人影院中文字幕| 中文字幕人妻少妇美臀| 射精视频在线观看免费| 久久九九亚洲欧美中文字幕| 日本免费一区二区三个| 国产91在线观看网站| 欧美日韩成人精品一区二区| 91青青草原免费观看| 在线视频天堂亚洲天堂| 一本之道高清久久久首页| 欧美日韩国产另类一区二区| 国产精品日本在线观看| 亚洲精品熟女一区二区三区| 午夜一区二区精品视频国产| 国产日韩欧美在线精品| 高清国产国产精品三级国产av| 久久久久久精品国产免费| 顶级少妇做爰片高潮丸| 免费观看久久久激情片| 欧美精品欧美激情免费区| 久久婷婷av一区二区三区| 欧美色高清视频在线播放| 久久精品国产亚洲av品| 一欧美一区二区三区| 国内在线免费观看av| 亚洲成年人黄片在线播放| 亚洲精品福利一二三区| 国产夫妻性生活国产视频| 精品国产无遮挡污污网站|