中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

官網(wǎng)做的好看的網(wǎng)站有哪些設(shè)計(jì)網(wǎng)站排行

官網(wǎng)做的好看的網(wǎng)站有哪些,設(shè)計(jì)網(wǎng)站排行,號(hào)碼之家官網(wǎng),區(qū)政府網(wǎng)站建設(shè)匯報(bào)nexttick是啥 nextTick是Vue提供的一個(gè)全局API,由于Vue的異步更新策略導(dǎo)致我們對(duì)數(shù)據(jù)的修改不會(huì)更新,如果此時(shí)想要獲取更新后的Dom,就需要使用這個(gè)方法. vue的異步更新策略意思是如果數(shù)據(jù)變化,vue不會(huì)立刻更新dom,而是開啟一個(gè)隊(duì)列,把組件更…

nexttick是啥

nextTick是Vue提供的一個(gè)全局API,由于Vue的異步更新策略導(dǎo)致我們對(duì)數(shù)據(jù)的修改不會(huì)更新,如果此時(shí)想要獲取更新后的Dom,就需要使用這個(gè)方法.
vue的異步更新策略意思是如果數(shù)據(jù)變化,vue不會(huì)立刻更新dom,而是開啟一個(gè)隊(duì)列,把組件更新函數(shù)保存在隊(duì)列里,在統(tǒng)一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更會(huì)異步的批量更新,這一策略導(dǎo)致我們對(duì)數(shù)據(jù)的修改不會(huì)立即體現(xiàn)在dom上,此時(shí)如果想要獲取更新后的dom狀態(tài),就要使用nexttick
nextTick所指定的回調(diào)會(huì)在瀏覽器更新DOM完畢之后再執(zhí)行。即在一次事件循環(huán)中,更新了數(shù)據(jù),把更新Dom的操作放入隊(duì)列中,使用了nextTick,則把nextTick里的回調(diào)放入隊(duì)列中,執(zhí)行完所有的同步代碼后,去執(zhí)行微任務(wù),即依次調(diào)用隊(duì)列里的函數(shù)。

函數(shù)簽名:

nextTick<T = void, R = void>(this: T, fn?: (this: T) => R): Promise<Awaited<R>>:

this:不是參數(shù),是ts中的一個(gè)語法,給 this 定義類型。給用于綁定回調(diào)函數(shù)中的 this 上下文,可以省略。
fn:要異步執(zhí)行的回調(diào)函數(shù),是一個(gè)函數(shù),可以省略。
函數(shù)返回一個(gè) Promise,Promise 的泛型為 Awaited,表示回調(diào)函數(shù)執(zhí)行后的返回值。

使用場(chǎng)景:

  • created中想要獲取dom時(shí)
  • 響應(yīng)式數(shù)據(jù)變化后獲取dom更新后的狀態(tài),比如希望獲取列表更新后的高度
vm.name = 'changed'
vm.$nextTick(()=>{ // 要在更新數(shù)據(jù)的后面使用console.log(app.innerHTML)
})

vue2、vue3中nexttick源碼

簡(jiǎn)單來講就是nexttick回調(diào)函數(shù)使用promise.then方式放入了異步,在所有dom都更新完成后才調(diào)用
先上一個(gè)小例子,(來自https://b23.tv/AmCLtgx),

async increment() {this.count++;//dom還未更新console.log(document.getElementById('counter').textContent)//0await nextTick();//dom已經(jīng)更新conosle.log(document.getElementById('counter').textContent)//1

我們先看,響應(yīng)式數(shù)據(jù)count改變之后,會(huì)發(fā)生什么. (具體代碼講解放在代碼注釋里了,以下為vue3源碼)

  1. 讓與響應(yīng)式數(shù)據(jù)相關(guān)連的函數(shù)去排隊(duì),調(diào)用queueJob()
    源碼位置:(太長(zhǎng)了,只放一部分)
    https://github.com/vuejs/core/blob/main/packages/runtime-core/src/renderer.ts
// 為組件創(chuàng)建一個(gè)響應(yīng)式效果,以便在組件的依賴項(xiàng)發(fā)生變化時(shí)觸發(fā)重新渲染,換句話說,就是一個(gè)響應(yīng)式數(shù)據(jù)改變后, 與它相關(guān)聯(lián)的函數(shù)用什么方式去執(zhí)行
// create reactive effect for renderingconst effect = (instance.effect = new ReactiveEffect(componentUpdateFn,//與響應(yīng)式數(shù)據(jù)相關(guān)聯(lián)的函數(shù)NOOP,//空函數(shù),,表示沒有特定的調(diào)度邏輯() => queueJob(update),//響應(yīng)式數(shù)據(jù)改變后,不會(huì)立刻執(zhí)行componentUpdateFn,而是讓componentUpdateFn去排隊(duì),在未來某一時(shí)刻執(zhí)行、instance.scope, // track it in component's effect scope))
  1. 排隊(duì)函數(shù)具體內(nèi)容
    源碼位置:
    https://github.com/vuejs/core/blob/main/packages/runtime-core/src/scheduler.ts

queueJob方法: 把上一步中輸入的參數(shù)update(也就是job)按特定規(guī)則推到queue任務(wù)隊(duì)列里, 調(diào)用queueFlush()

export function queueJob(job: SchedulerJob) {// the dedupe search uses the startIndex argument of Array.includes()// by default the search index includes the current job that is being run// so it cannot recursively trigger itself again.// if the job is a watch() callback, the search will start with a +1 index to// allow it recursively trigger itself - it is the user's responsibility to// ensure it doesn't end up in an infinite loop.//先檢查queue數(shù)組是否為空,或者job是否已經(jīng)包含在queue數(shù)組中。這個(gè)檢查確保相同的job不會(huì)被多次排隊(duì)。if (!queue.length ||!queue.includes(job,isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex,)) {if (job.id == null) {//如果job無id屬性,把job插入到queue數(shù)組末尾queue.push(job)} else {//如果job有id屬性,就按照id把job插入到queue數(shù)組中特定位置queue.splice(findInsertionIndex(job.id), 0, job)}queueFlush()//刷新隊(duì)列}
}

queueFlush方法: 把flushJobs(真正刷新隊(duì)列的函數(shù))放在promise.then里,等同步任務(wù)都完成后才真的刷新隊(duì)列,再執(zhí)行里面的更新函數(shù)

function queueFlush() {//刷新隊(duì)列方法if (!isFlushing && !isFlushPending) {//當(dāng)前沒有正在進(jìn)行的刷新操作,并且沒有待處理(被掛起)的刷新操作isFlushPending = true//表示有一個(gè)刷新操作待處理(被掛起)currentFlushPromise = resolvedPromise.then(flushJobs)}//注意這里是promise,屬于微任務(wù),所以會(huì)在未來某一時(shí)刻異步的執(zhí)行,因此,當(dāng)flushjob這個(gè)方法真正執(zhí)行時(shí),其實(shí)其他所有的同步代碼都已經(jīng)執(zhí)行完了
}

flushjob方法:按特定順序(從父組件更新到子組件遍歷并執(zhí)行任務(wù)隊(duì)列queue中的任務(wù), 并處理執(zhí)行過程中的任何錯(cuò)誤。

function flushJobs(seen?: CountMap) {//循環(huán)遍歷所有的組件更新函數(shù),去更新所有的組件isFlushPending = falseisFlushing = trueif (__DEV__) {seen = seen || new Map()}// Sort queue before flush.// This ensures that:// 1. Components are updated from parent to child. (because parent is always//    created before the child so its render effect will have smaller//    priority number)// 2. If a component is unmounted during a parent component's update,//    its update can be skipped.queue.sort(comparator)//排序,確保組件從父組件更新到子組件,并允許跳過已卸載組件的更新。// conditional usage of checkRecursiveUpdate must be determined out of// try ... catch block since Rollup by default de-optimizes treeshaking// inside try-catch. This can leave all warning code unshaked. Although// they would get eventually shaken by a minifier like terser, some minifiers// would fail to do that (e.g. https://github.com/evanw/esbuild/issues/1610)const check = __DEV__? (job: SchedulerJob) => checkRecursiveUpdates(seen!, job): NOOPtry {//遍歷作業(yè)隊(duì)列。for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {const job = queue[flushIndex]if (job && job.active !== false) {if (__DEV__ && check(job)) {continue}callWithErrorHandling(job, null, ErrorCodes.SCHEDULER)}}} finally {flushIndex = 0queue.length = 0flushPostFlushCbs(seen)isFlushing = falsecurrentFlushPromise = null// some postFlushCb queued jobs!// keep flushing until it drains.if (queue.length || pendingPostFlushCbs.length) {//若queue仍然有作業(yè),或有待處理的后續(xù)刷新回調(diào),則遞歸調(diào)用flushjob,直到隊(duì)列為空且所有回調(diào)都執(zhí)行完畢flushJobs(seen)}}
}

nextTick: 獲取queueFlush中用到的resolvedPromise, 用then方法執(zhí)行nexttick的回調(diào)函數(shù),

export function nextTick<T = void, R = void>(this: T,//確?;卣{(diào)函數(shù)fn在執(zhí)行時(shí)具有正確的上下文fn?: (this: T) => R,
): Promise<Awaited<R>> {const p = currentFlushPromise || resolvedPromisereturn fn ? p.then(this ? fn.bind(this) : fn) : p
}//如果提供了回調(diào)函數(shù) fn,則在 p 的 promise 對(duì)象上調(diào)用 then 方法。如果有可用的 this 上下文,則使用 bind 方法將 fn 函數(shù)綁定到 this 上下文。否則,直接使用 fn。
//如果未提供回調(diào)函數(shù)(fn 為假值),則直接返回 p 的 promise 對(duì)象。

回看一開始的例子,

async increment() {this.count++;//導(dǎo)致組件更新函數(shù)入隊(duì)//dom還未更新console.log(document.getElementById('counter').textContent)//0await nextTick();//導(dǎo)致下面所有代碼封裝成一個(gè)匿名函數(shù),并放到剛才的組件更新函數(shù)后面,//因此清空隊(duì)列的時(shí)候,會(huì)先把所有的組件全清空后,才會(huì)執(zhí)行nexttick后的延遲的語句或回調(diào)函數(shù)//dom已經(jīng)更新conosle.log(document.getElementById('counter').textContent)//1

vue2中netxtick源碼位置:
https://github.com/vuejs/vue/blob/main/src/core/util/next-tick.ts
里面用到了優(yōu)雅降級(jí),可以看看,不多寫了

/* globals MutationObserver */import { noop } from 'shared/util'
import { handleError } from './error'
import { isIE, isIOS, isNative } from './env'export let isUsingMicroTask = falseconst callbacks: Array<Function> = []
let pending = falsefunction flushCallbacks() {pending = falseconst copies = callbacks.slice(0)callbacks.length = 0for (let i = 0; i < copies.length; i++) {copies[i]()}
}// Here we have async deferring wrappers using microtasks.
// In 2.5 we used (macro) tasks (in combination with microtasks).
// However, it has subtle problems when state is changed right before repaint
// (e.g. #6813, out-in transitions).
// Also, using (macro) tasks in event handler would cause some weird behaviors
// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).
// So we now use microtasks everywhere, again.
// A major drawback of this tradeoff is that there are some scenarios
// where microtasks have too high a priority and fire in between supposedly
// sequential events (e.g. #4521, #6690, which have workarounds)
// or even between bubbling of the same event (#6566).
let timerFunc
//優(yōu)雅降級(jí)
// 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 next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {//首先,判斷是否原生支持Promiseconst p = Promise.resolve()timerFunc = () => {p.then(flushCallbacks)// 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)}isUsingMicroTask = true
} else if (//其次 判斷是否原生支持MutationObserver!isIE &&typeof MutationObserver !== 'undefined' &&(isNative(MutationObserver) ||// PhantomJS and iOS 7.xMutationObserver.toString() === '[object MutationObserverConstructor]')
) {// Use MutationObserver where native Promise is not available,// e.g. PhantomJS, iOS7, Android 4.4// (#6466 MutationObserver is unreliable in IE11)let counter = 1const observer = new MutationObserver(flushCallbacks)const textNode = document.createTextNode(String(counter))observer.observe(textNode, {characterData: true})timerFunc = () => {counter = (counter + 1) % 2textNode.data = String(counter)}isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {// 再次 判斷是否原生支持setImmediate // Fallback to setImmediate.// Technically it leverages the (macro) task queue,// but it is still a better choice than setTimeout.timerFunc = () => {setImmediate(flushCallbacks)}
} else {// 最后 都不支持的情況下 則使用setTimeout來兜底// Fallback to setTimeout.timerFunc = () => {setTimeout(flushCallbacks, 0)}
}// 將回調(diào)函數(shù)cb包裝成一個(gè)箭頭函數(shù)push到事件隊(duì)列callbacks中
export function nextTick(): Promise<void>
export function nextTick<T>(this: T, cb: (this: T, ...args: any[]) => any): void
export function nextTick<T>(cb: (this: T, ...args: any[]) => any, ctx: T): void
/*** @internal*/
export function nextTick(cb?: (...args: any[]) => any, ctx?: object) {let _resolvecallbacks.push(() => {if (cb) {try {cb.call(ctx)} catch (e: any) {handleError(e, ctx, 'nextTick')}} else if (_resolve) {_resolve(ctx)}})if (!pending) {pending = truetimerFunc()}// $flow-disable-lineif (!cb && typeof Promise !== 'undefined') {return new Promise(resolve => {_resolve = resolve})}
}
http://www.risenshineclean.com/news/37636.html

相關(guān)文章:

  • 宜春做網(wǎng)站公司網(wǎng)站seo優(yōu)化工具
  • 網(wǎng)站開發(fā)測(cè)試過程中文域名查詢官網(wǎng)
  • 阜寧做網(wǎng)站的公司新手怎么做電商
  • 自適應(yīng)網(wǎng)站做mip改造在哪里可以免費(fèi)自學(xué)seo課程
  • 哪家做公司網(wǎng)站互聯(lián)網(wǎng)廣告推廣好做嗎
  • 吧網(wǎng)站做軟件的軟件網(wǎng)絡(luò)銷售平臺(tái)怎么做
  • 做國(guó)際網(wǎng)站的流程廣州seo報(bào)價(jià)
  • java做網(wǎng)站百度客服怎么轉(zhuǎn)人工電話
  • 仿做唯品會(huì)網(wǎng)站黃岡便宜的網(wǎng)站推廣怎么做
  • pmp培訓(xùn)seo網(wǎng)站
  • 沈陽網(wǎng)站搜索引擎優(yōu)化google推廣教程
  • 網(wǎng)頁版視頻網(wǎng)站建設(shè)需要多少錢百度sem推廣具體做什么
  • kol合作推廣seo外鏈?zhǔn)鞘裁?/a>
  • 自己創(chuàng)業(yè)做原公司一樣的網(wǎng)站網(wǎng)站seo設(shè)計(jì)
  • 公司做網(wǎng)站的步驟廣州seo關(guān)鍵字推廣
  • 做韋恩圖的網(wǎng)站怎么樣推廣自己的公司
  • wordpress 添加導(dǎo)航菜單成都seo招聘
  • 網(wǎng)站域名有什么用計(jì)算機(jī)培訓(xùn)
  • 大學(xué)新校區(qū)建設(shè)網(wǎng)站網(wǎng)站seo重慶
  • 網(wǎng)站推廣資訊上海百度競(jìng)價(jià)托管
  • 中國(guó)大型建筑公司有哪些seo西安
  • 全國(guó)公安網(wǎng)站備案應(yīng)用寶aso優(yōu)化
  • 班級(jí)建設(shè)網(wǎng)站設(shè)計(jì)方案搜索引擎優(yōu)化到底是優(yōu)化什么
  • 陜西省建設(shè)廳小紅書關(guān)鍵詞排名優(yōu)化
  • java 網(wǎng)站設(shè)計(jì)都有什么推廣平臺(tái)
  • 香港網(wǎng)站代理seo優(yōu)化方案
  • 南昌做網(wǎng)站市場(chǎng)報(bào)價(jià)刷seo關(guān)鍵詞排名軟件
  • 做網(wǎng)站設(shè)計(jì)累嗎網(wǎng)絡(luò)營(yíng)銷策劃步驟
  • css優(yōu)秀網(wǎng)站百度平臺(tái)客服
  • 網(wǎng)站制作公司官網(wǎng)南京長(zhǎng)沙百度