亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

從源碼里了解vue中的nextTick的使用

2019-11-19 12:29:28
字體:
來源:轉載
供稿:網友

今天做了一個需求,場景是這樣的:

在頁面拉取一個接口,這個接口返回一些數據,這些數據是這個頁面的一個浮層組件要依賴的,然后我在接口一返回數據就展示了這個浮層組件,展示的同時,上報一些數據給后臺(這些數據就是父組件從接口拿的),這個時候,神奇的事情發生了,雖然我拿到數據了,但是浮層展現的時候,這些數據還未更新到組件上去。

父組件:

<template>  .....  <pop ref="pop" :name="name"/></template><script>export default {  .....  created() {    ....    // 請求數據,并從接口獲取數據    Data.get({      url: xxxx,      success: (data) => {        // 問題出現在這里,我們賦值以后直接調用show方法,去展現,show方法調用的同時上報數據,而上報的數據這個時候還未更新到子組件        this.name = data.name        this.$refs.pop.show()      }    })  }}</script>

子組件

<template>  <div v-show="isShow">    ......  </div></template><script>export default {  .....  props: ['name'],  methods: {    show() {      this.isShow = true      // 上報      Report('xxx', {name: this.name})    }  }}</script>

問題分析:

原因vue官網上有解析( cn.vuejs.org/v2/guide/re… )

可能你還沒有注意到,Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue 將開啟一個隊列,并緩沖在同一事件循環中發生的所有數據改變。如果同一個 watcher 被多次觸發,只會被推入到隊列中一次。這種在緩沖時去除重復數據對于避免不必要的計算和 DOM 操作上非常重要。然后,在下一個的事件循環“tick”中,Vue 刷新隊列并執行實際 (已去重的) 工作。Vue 在內部嘗試對異步隊列使用原生的 Promise.then 和 MessageChannel,如果執行環境不支持,會采用 setTimeout(fn, 0) 代替。

這句話就是說,當我們在父組件設置this.name=name的時候,vue并不會直接更新到子組件中(dom的更新也一樣未立即執行),而是把這些更新操作全部放入到一個隊列當中,同個組件的所有這些賦值操作,都作為一個watcher的更新操作放入這個隊列當中,然后等到事件循環結束的時候,一次性從這個隊列當中獲取所有的wathcer執行更新操作。在我們這個例子當中,就是我們在調用show的時候,實際上,我們的this.name=name并未真正執行,而是被放入隊列中。vue的這種做法是基于優化而做的,毋庸置疑,不然我們如果有n多個賦值vue就執行n多個dom更新,那效率將會非常的低效和不可取的。


下文中的更新操作指對data的值進行更新的操作,在vue中,都會被放入隊列異步執行。

解決方案:

1、 使用nextTick來延遲執行show方法(籠統得說,執行所有需要在數據真正更新后的操作

通過上面的分析我們知道,我們的所有的對vue實例的更新操作,都會先被放入一個隊列當中,延遲異步執行,這些異步操作,要么是microtask,要么是macrotask(是microtask還是macroktask取決于環境,nextTick的源碼中有所體現),根據事件循環機制,先入隊列的先執行,所以如果我們在nextTick當中執行操作就會變成這樣。


2、 使用setTimeout來延遲執行show方法,原理同上

所以我們的解決方法可以是:

this.name = data.namesetTimeout(() => { this.$refs.pop.show()})

或者

this.name = data.namethis.$nextTick(() => { this.$refs.pop.show()})

nextTick的實現原理

其實nextTick的實現原理是挺簡單的,簡單點說,就是實現異步,通過不同的執行環境,用不同的方式來實現,保證nextTick里面的回調函數能夠異步執行。為什么要這么做呢?因為vue對dom的更新也是異步的呀。

下面貼出源碼:

/** * Defer a task to execute it asynchronously. */export const nextTick = (function () { const callbacks = [] let pending = false let timerFunc function nextTickHandler () {  pending = false  const copies = callbacks.slice(0)  callbacks.length = 0  for (let i = 0; i < copies.length; i++) {   copies[i]()  } } // the nextTick behavior leverages the microtask queue, which can be accessed // via either native Promise.then or MutationObserver. // MutationObserver has wider support, however it is seriously bugged in // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It // completely stops working after triggering a few times... so, if native // Promise is available, we will use it: /* istanbul ignore if */ if (typeof Promise !== 'undefined' && isNative(Promise)) {  var p = Promise.resolve()  var logError = err => { console.error(err) }  timerFunc = () => {   p.then(nextTickHandler).catch(logError)   // in problematic UIWebViews, Promise.then doesn't completely break, but   // it can get stuck in a weird state where callbacks are pushed into the   // microtask queue but the queue isn't being flushed, until the browser   // needs to do some other work, e.g. handle a timer. Therefore we can   // "force" the microtask queue to be flushed by adding an empty timer.   if (isIOS) setTimeout(noop)  } } else if (!isIE && typeof MutationObserver !== 'undefined' && (  isNative(MutationObserver) ||  // PhantomJS and iOS 7.x  MutationObserver.toString() === '[object MutationObserverConstructor]' )) {  // use MutationObserver where native Promise is not available,  // e.g. PhantomJS, iOS7, Android 4.4  var counter = 1  var observer = new MutationObserver(nextTickHandler)  var textNode = document.createTextNode(String(counter))  observer.observe(textNode, {   characterData: true  })  timerFunc = () => {   counter = (counter + 1) % 2   textNode.data = String(counter)  } } else {  // fallback to setTimeout  /* istanbul ignore next */  timerFunc = () => {   setTimeout(nextTickHandler, 0)  } } return function queueNextTick (cb?: Function, ctx?: Object) {  let _resolve  callbacks.push(() => {   if (cb) {    try {     cb.call(ctx)    } catch (e) {     handleError(e, ctx, 'nextTick')    }   } else if (_resolve) {    _resolve(ctx)   }  })  if (!pending) {   pending = true   timerFunc()  }  if (!cb && typeof Promise !== 'undefined') {   return new Promise((resolve, reject) => {    _resolve = resolve   })  } }})()

首先我們看到這個是利用了閉包的特性,返回queueNextTick,所以我們實際調用的nextTick其實就是調用queueNextTick,一調用這個方法,就會把nextTick的回調放入隊列callbacks當中,等到合適的時機,會將callbacks中的所有回調取出來執行,以達到延遲執行的目的。為啥要用閉包呢,我覺得有兩個原因:

1、共享變量,比如callbacks、pending和timerFunc。

2、避免反復判斷,即是避免反復判斷timerFunc是利用Promise還是利用MutationObserver或是setTimeout來實現異步,這是函數柯里化的一種運用。

這里有兩個最主要的方法需要解釋下:

1、 nextTickHandler

這個函數,就是把隊列中的回調,全部取出來執行,類似于microtask的任務隊列。我們通過調用Vue.$nextTick就會把回調全部放入這個隊列當中,等到要執行的時候,調用nextTickHandler全部取出來執行。

2、 timerFunc

這個變量,它的作用就是通過Promise/Mutationobserver/Settimeout把nextTickHandler放入到真正的任務隊列當中,等到事件循環結束,就從任務隊列當中取出nextTickHandler來執行,nextTickHandler一執行,callbacks里面的所有回調就會被取出來執行來,這樣就達到來延遲執行nextTick傳的回調的效果。

通過這個簡單的源碼分析,我們可以得出兩個結論

1、nextTick會根據不同的執行環境,異步任務可能為microtask或者macrotask,而不是固定不變的。所以,如果你想讓nextTick里面的異步任務統統看成是microtask的話,你會遇到坑的。

2、nextTick的并不能保證一定能獲取得到更新后的dom,這取決于你是先進行數據賦值還是先調用nextTick。比如:

new Vue({   el: '#app',   data() {    return {     id: 2    }   },   created() {       },   mounted() {    this.$nextTick(() => {     console.log(document.getElementById('id').textContent) // 這里打印出來的是2,因為先調用了nextTick    })    this.id = 3   } })

結論

如果想要獲取更新后的DOM或者子組件(依賴父組件的傳值),可以在更新操作之后立即使用Vue.nextTick(callback),注意這里的先后順序,先進行更新操作,再調用nextTick獲取更新后的DOM/子組件,源碼里面我們知道nextTick是無法保證一定是能夠獲取得到更新后的DOM/子組件的

以上所述是小編給大家介紹的vue中的nextTick的使用,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕亚洲色图| 日韩美女视频免费看| 中文字幕亚洲综合久久| 欧美国产亚洲精品久久久8v| 欧美激情免费看| 亚州精品天堂中文字幕| 色中色综合影院手机版在线观看| 亚洲欧美日韩国产中文| 欧美精品在线第一页| 国产专区欧美专区| 97视频在线观看网址| 日韩av手机在线| 亚洲日韩第一页| 成人激情视频在线播放| 色偷偷亚洲男人天堂| 97视频国产在线| 久久99久久久久久久噜噜| 中文字幕亚洲一区| 国外成人免费在线播放| 欧美高清在线观看| 久久精品人人做人人爽| 国产亚洲精品成人av久久ww| 久久人人爽国产| 国内外成人免费激情在线视频| 日韩在线视频国产| 欧美中在线观看| 欧美激情精品久久久久久| 国产日韩欧美另类| 久久精品91久久香蕉加勒比| 亚洲欧美日韩视频一区| 91性高湖久久久久久久久_久久99| 国产区精品视频| 在线亚洲午夜片av大片| 久热99视频在线观看| 久久99久国产精品黄毛片入口| 亚洲人成啪啪网站| 欧美性xxxxxxx| 国产精品吴梦梦| 欧美日韩综合视频| 国产精品日日做人人爱| 亚洲色图18p| 日韩av中文在线| 亚洲伊人久久大香线蕉av| 亚洲欧洲视频在线| 精品香蕉一区二区三区| 91高清免费视频| 国产精品成久久久久三级| 亚洲国产精品推荐| 国产亚洲xxx| 亚洲视频在线播放| 欧美色视频日本高清在线观看| 亚洲一区二区福利| 在线亚洲午夜片av大片| 免费91在线视频| 亚洲激情成人网| 免费91麻豆精品国产自产在线观看| 欧美又大粗又爽又黄大片视频| 国产精品免费视频久久久| 亚洲福利视频网站| 日本在线观看天堂男亚洲| 亚洲成人免费在线视频| 中文字幕v亚洲ⅴv天堂| 国产精品激情av电影在线观看| 国产精品久久91| 久久久精品国产一区二区| 亚洲成人a**站| 欧美日韩xxx| 91精品国产91久久久久久吃药| 久久精品国产久精国产思思| 午夜美女久久久久爽久久| 欧美精品电影免费在线观看| 欧美日本在线视频中文字字幕| 热99精品只有里视频精品| 成人黄色免费网站在线观看| 亚洲一区亚洲二区| 亚洲国产精彩中文乱码av| 欧美精品videossex性护士| 日韩激情av在线免费观看| 国产精品视频一区国模私拍| 国产精品96久久久久久| 亚洲欧洲中文天堂| 在线不卡国产精品| 久久成人亚洲精品| 国产精品毛片a∨一区二区三区|国| 尤物九九久久国产精品的分类| 日韩亚洲精品电影| 国产成人久久久精品一区| 亚洲美女精品成人在线视频| 国产中文字幕日韩| 亚洲激情视频网站| 国产午夜精品全部视频在线播放| 中文字幕亚洲综合久久筱田步美| 亚洲欧美中文另类| 成人黄色av网| 最好看的2019的中文字幕视频| 在线精品高清中文字幕| 亚洲一区中文字幕| 欧美久久久精品| 91精品久久久久久久久久久久久| 亚洲一区二区三区四区在线播放| 国产成人激情小视频| 中文字幕国产日韩| 国产精品久久久久久久久久小说| 精品女同一区二区三区在线播放| 国产欧亚日韩视频| 91在线|亚洲| 国产成人自拍视频在线观看| 成人午夜在线视频一区| 久久九九有精品国产23| 国产日韩中文在线| 中文字幕国产精品| 日日狠狠久久偷偷四色综合免费| 国产精品美女av| 欧美性xxxx极品hd欧美风情| 午夜剧场成人观在线视频免费观看| 国产精品九九九| 国产精品久久久久久久一区探花| 欧美成人在线免费视频| 性欧美xxxx| 国产亚洲一区二区在线| 久久精品视频在线观看| 亚洲电影免费观看高清完整版在线| 亚洲精品日韩欧美| 夜夜躁日日躁狠狠久久88av| 国产精品成av人在线视午夜片| 亚洲激情视频网站| 国外视频精品毛片| 久精品免费视频| 欧美高清在线观看| 97不卡在线视频| 狠狠综合久久av一区二区小说| 久久久久久久久久久亚洲| 狠狠躁夜夜躁久久躁别揉| 在线国产精品播放| www亚洲欧美| 久久99热这里只有精品国产| 欧美性生交大片免网| 91国自产精品中文字幕亚洲| 亚洲毛片在线观看| 久久人体大胆视频| 国产主播喷水一区二区| 日韩美女毛茸茸| 国产精品免费一区豆花| 国产精品免费视频久久久| 国产欧美日韩精品丝袜高跟鞋| 色噜噜久久综合伊人一本| 九色91av视频| 欧美在线观看一区二区三区| 欧美性色xo影院| 亚洲福利精品在线| 国模极品一区二区三区| 国产精品欧美激情在线播放| 性亚洲最疯狂xxxx高清| 欧美成年人视频网站| 少妇激情综合网| 国产福利精品av综合导导航| 欧美日韩中文在线观看| 久久久久久久影视| 亚洲欧美精品在线| 久久久久久久久久久久久久久久久久av| 亚洲片av在线| 日韩精品极品在线观看| 欧美一级电影免费在线观看| 国模视频一区二区三区|