国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

React源碼閱讀之:Controlled Input

alanoddsoff / 1611人閱讀

摘要:現(xiàn)在看了源碼之后,發(fā)現(xiàn)自己還是,根本就不是這么做的,我還花了很多時(shí)間去找他阻止默認(rèn)行為的證據(jù),結(jié)果才發(fā)現(xiàn)走了歪路。

不知道大家對(duì)于Controlled Input的概念好不好奇,我在最開(kāi)始用React的時(shí)候就對(duì)其非常感興趣,然而奈何那時(shí)候能力不夠,也沒(méi)那么多時(shí)間去看源碼,所以一直處于猜測(cè)而沒(méi)有去證實(shí)的階段。在后來(lái)使用Vue進(jìn)行開(kāi)發(fā)的時(shí)候,我還自己實(shí)現(xiàn)過(guò)類(lèi)似的組件,那時(shí)候是通過(guò)preventDefault keyDown事件來(lái)阻止自動(dòng)更新,實(shí)現(xiàn)了大致的功能,所以當(dāng)時(shí)覺(jué)得這可能也是React的做法吧。現(xiàn)在看了源碼之后,發(fā)現(xiàn)自己還是too young,React根本就不是這么做的,我還花了很多時(shí)間去找他阻止默認(rèn)行為的證據(jù),結(jié)果才發(fā)現(xiàn)走了歪路。閑話(huà)到此為止,我們來(lái)看看React中如何實(shí)現(xiàn)Controlled Input

在看這個(gè)之前最好了解過(guò)React的事件系統(tǒng),相關(guān)內(nèi)容我已經(jīng)準(zhǔn)備好,但是還沒(méi)整理成文章,大家可以先去自行了解下,我更新上來(lái)之后會(huì)在這里放鏈接,所以也可以關(guān)注我獲取最新內(nèi)容。

先來(lái)看一下batchedUpdates的代碼:

function batchedUpdates(fn, bookkeeping) {
  if (isBatching) {
    return fn(bookkeeping);
  }
  isBatching = true;
  try {
    return _batchedUpdates(fn, bookkeeping);
  } finally {
    isBatching = false;
    var controlledComponentsHavePendingUpdates = needsStateRestore();
    if (controlledComponentsHavePendingUpdates) {
      _flushInteractiveUpdates();
      restoreStateIfNeeded();
    }
  }
}

finally里面執(zhí)行了一個(gè)方法叫做restoreStateIfNeeded,如果你通過(guò)代碼調(diào)試把debugger放之前,并且你寫(xiě)一個(gè)不更新state的demo,你會(huì)發(fā)現(xiàn),在執(zhí)行這個(gè)方法之前,input里面的內(nèi)容其實(shí)是先變了的,然后執(zhí)行完之后再變回來(lái)。哈哈,現(xiàn)在你應(yīng)該能大致猜到了吧,是的,React的做法并不關(guān)心event,他等內(nèi)容執(zhí)行完了,然后看是否需要回滾再滾回來(lái)。

那么接下去我們就來(lái)看看細(xì)節(jié)
function restoreStateIfNeeded() {
  if (!restoreTarget) {
    return;
  }
  var target = restoreTarget;
  var queuedTargets = restoreQueue;
  restoreTarget = null;
  restoreQueue = null;

  restoreStateOfTarget(target);
  if (queuedTargets) {
    for (var i = 0; i < queuedTargets.length; i++) {
      restoreStateOfTarget(queuedTargets[i]);
    }
  }
}

這里涉及兩個(gè)公共變量:restoreTargetrestoreQueue,那么這兩個(gè)變量會(huì)在什么情況下變化呢?

在同一個(gè)文件ReactControlledComponent里面有這么一個(gè)方法

export function enqueueStateRestore(target) {
  if (restoreTarget) {
    if (restoreQueue) {
      restoreQueue.push(target);
    } else {
      restoreQueue = [target];
    }
  } else {
    restoreTarget = target;
  }
}

那么這個(gè)方法什么時(shí)候調(diào)用呢?答案是在ChangeEventPlugin里面

ChangeEventPlugin = {
  extractEvents() {
    // ...
    const event = createAndAccumulateChangeEvent(
      inst,
      nativeEvent,
      nativeEventTarget,
    );
  }
}

function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
  const event = SyntheticEvent.getPooled(
    eventTypes.change,
    inst,
    nativeEvent,
    target,
  );
  event.type = "change";
  // Flag this event loop as needing state restore.
  enqueueStateRestore(target);  // 這里
  accumulateTwoPhaseDispatches(event);
  return event;
}

我們先不關(guān)心這里具體是什么含義,我們只需要知道只有change event才需要回滾內(nèi)容,所以在生成change事件的時(shí)候會(huì)把對(duì)應(yīng)的節(jié)點(diǎn)。而生成事件的時(shí)間和batchUpdates是一起的,這就把整個(gè)內(nèi)容串聯(lián)起來(lái)了

inpute content -> trigger change event -> create event object -> enqueueStateRestore -> events trigger finsihed -> restoreStateIfNeeded
如何restore
function restoreStateOfTarget(target) {
  var internalInstance = getInstanceFromNode(target);
  if (!internalInstance) {
    // Unmounted
    return;
  }
  var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
  fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props);
}

在事件系統(tǒng)執(zhí)行完之后,獲取input節(jié)點(diǎn)對(duì)應(yīng)的Fiber對(duì)象,然后讀取新的props,這里的props是執(zhí)行完綁定事件之后的最新的props,這是對(duì)應(yīng)controlled component真正應(yīng)該顯示的props,然后再去對(duì)比props里面的內(nèi)容和輸入框內(nèi)的實(shí)際內(nèi)容,如果需要退回就執(zhí)行。

function restoreControlledState(domElement, tag, props) {
  switch (tag) {
    case "input":
      restoreControlledState(domElement, props);
      return;
    case "textarea":
      restoreControlledState$3(domElement, props);
      return;
    case "select":
      restoreControlledState$2(domElement, props);
      return;
  }
}

function restoreControlledState(element, props) {
  var node = element;
  updateWrapper(node, props);
  updateNamedCousins(node, props);
}

function updateWrapper(element, props) {
  var node = element;

  updateChecked(element, props);

  var value = getSafeValue(props.value);

  // 更新的重點(diǎn)在這里
  if (value != null) {
    if (props.type === "number") {
      if (value === 0 && node.value === "" ||
      // eslint-disable-next-line
      node.value != value) {
        node.value = "" + value;
      }
    } else if (node.value !== "" + value) {
      node.value = "" + value;
    }
  }

  if (props.hasOwnProperty("value")) {
    setDefaultValue(node, props.type, value);
  } else if (props.hasOwnProperty("defaultValue")) {
    setDefaultValue(node, props.type, getSafeValue(props.defaultValue));
  }

  if (props.checked == null && props.defaultChecked != null) {
    node.defaultChecked = !!props.defaultChecked;
  }
}

后面具體更新的細(xì)節(jié)就不分析了,相信大家都看的懂(可以忽略一些不重要的函數(shù))

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/97688.html

相關(guān)文章

  • 中文輸入法與React文本輸入框的問(wèn)題與解決方案

    摘要:本文的目的是希望能針對(duì)這個(gè)問(wèn)題提供一些說(shuō)明現(xiàn)在暫時(shí)性的解決方案。完全不會(huì)有問(wèn)題的只有一個(gè)瀏覽器,就是上面注釋中所說(shuō)的已經(jīng)實(shí)作出的,上可能根本不需要任何解決方案,它的輸入法編輯器是獨(dú)立于瀏覽器上的文本輸入框之外的。 問(wèn)題來(lái)源是來(lái)自這個(gè)React官方存儲(chǔ)庫(kù)的issue #3926,與這個(gè)議題關(guān)聯(lián)的有很多其他的issue,來(lái)自許多項(xiàng)目,有些是與React相關(guān),有些則是vue或其它JS套件。也...

    shevy 評(píng)論0 收藏0
  • [ 一起學(xué)React系列 -- 5 ] 如何優(yōu)雅得使用表單控件

    摘要:假如我們從后臺(tái)拉取一個(gè)數(shù)據(jù)要填入輸入框,那么必須得使用受控組件,因?yàn)榉鞘芸亟M件只能被用戶(hù)輸入。不影響正常輸入填充該輸入框的默認(rèn)值,此時(shí)不顯示內(nèi)容。 網(wǎng)頁(yè)中使用的form表單大家肯定都再熟悉不過(guò)了,它主要作用是用來(lái)收集和提交信息。React中的表單組件與我們普通的Html中的表單及其表現(xiàn)形式?jīng)]有什么不同,所以如何使用表單我覺(jué)得再拿出來(lái)說(shuō)可能是畫(huà)蛇添足、毫無(wú)意義。不過(guò)再怎么樣也不能辜負(fù)大家...

    Charlie_Jade 評(píng)論0 收藏0
  • 受控組件和非受控組件,強(qiáng)力一波

    摘要:受控組件其值由控制的輸入表單元素稱(chēng)為受控組件。如果讓表單數(shù)據(jù)由處理時(shí),替代方案為使用非受控組件。使用非受控組件時(shí),通常你希望可以為其指定初始值,但不再控制后續(xù)更新。 受控組件 其值由React控制的輸入表單元素稱(chēng)為受控組件。 class NameForm extends React.Component { constructor(props) { super(props);...

    FrancisSoung 評(píng)論0 收藏0
  • 在格式化的場(chǎng)景下,React input 的光標(biāo)的處理辦法

    摘要:具體表現(xiàn)是什么樣的呢圖安卓下不期望的輸入行為可以看到,在安卓手機(jī)下每次格式化發(fā)生的時(shí)候,本來(lái)應(yīng)該一直在最后的光標(biāo)會(huì)錯(cuò)格一位,導(dǎo)致連續(xù)輸入出現(xiàn)問(wèn)題。 今天要來(lái)說(shuō)的是有關(guān)于有數(shù)值格式化的場(chǎng)景中,React input 光標(biāo)的一些異常的表現(xiàn)和對(duì)應(yīng)的處理辦法。故事要從一個(gè) issue 說(shuō)起,有用戶(hù)反映在使用 NumberField 組件輸入時(shí)安卓下會(huì)出現(xiàn)光標(biāo)位置異常,導(dǎo)致連續(xù)輸入會(huì)達(dá)不到期望的...

    cheng10 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<