欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

react?定位組件源碼解析

 更新時(shí)間:2023年03月28日 09:13:06   作者:孟祥_成都  
這篇文章主要為大家介紹了react定位組件源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

react組件庫(kù)系列耽擱了一些時(shí)間,繼續(xù)了!定位組件在b端里面實(shí)在太常見了。

首先介紹一下什么是定位組件,如下圖:

也就是上面的“這是一個(gè)彈窗的div”其實(shí)是絕對(duì)定位到按鈕上的,因?yàn)槭墙^對(duì)定位,所以可以定位到任意元素上。

整體源碼來自于t-design的popup組件

但是他們也是二次封裝了react-popper,react-popper又依賴@popperjs/core,所以這篇文章主要解決的是@popperjs/core的實(shí)現(xiàn)原理。

計(jì)劃:

  • 本篇是@popperjs/core的實(shí)現(xiàn)核心原理
  • 第二篇講 react-popper實(shí)現(xiàn)核心原理
  • 最后一篇是t-designpopup實(shí)現(xiàn)原理。

講源碼之前,跟大家亮點(diǎn)好玩的知識(shí)點(diǎn):

里面有很多實(shí)用的工具函數(shù),說實(shí)話,原以為自己原生dom api掌握還挺熟練的,看了這些兼容性的代碼,我才知道自己有多無知,舉個(gè)例子,你們一個(gè)元素的position是absolute,那么它是相當(dāng)于誰(shuí)定位?例如:

  <body>
    <div>
      網(wǎng)二
    </div>
    <div style="transform: translateX(2px);">
      <span style="position: absolute; top: 0" >李四</span>
  </div>
  </body>

肯定有人說了,這個(gè)我熟啊,相當(dāng)于上面包含它的元素只要不是static定位的。這個(gè)沒錯(cuò),但是只答對(duì)一部分,還有一種可能,本身元素是static元素也會(huì)成為定位上下文,比如給它加一個(gè)transform屬性,你可以試試上面的代碼,李四是相對(duì)于transform屬性的div定位的。

不僅僅是transform屬性,下面的方式都可以成定位上下文元素(當(dāng)時(shí)看源碼這里我是怎么也不明白為啥要判斷下面這些)

  • 有transform、perspective、filter屬性中任意一個(gè)不為none。
  • 是will-change屬性值為以上任意一個(gè)屬性的祖先元素。
  • 是contain屬性值包含paint、layout、strict或content的祖先元素。

正文開始!

如何創(chuàng)建基礎(chǔ)的popper

使用createPopper API,我們先看看是怎么用的:

假設(shè)我們有這樣一個(gè)html文件

<!DOCTYPE html>
<html>
  <head>
    <title>Popper Tutorial</title>
  </head>
    <style>
      #tooltip {
        background: #333;
        color: white;
        font-weight: bold;
        padding: 4px 8px;
        font-size: 13px;
        border-radius: 4px;
      }
    </style>
  <body>
    <button id="button" aria-describedby="tooltip">My button</button>
    <div id="tooltip" role="tooltip">My tooltip</div>
    <script src="https://unpkg.com/@popperjs/core@2"></script>
    <script>
      const button = document.querySelector('#button');
      const tooltip = document.querySelector('#tooltip');
      const popperInstance = Popper.createPopper(button, tooltip);
    </script>
  </body>
</html>

我們的目的是把tooltip組件定位到button組件下面,如下圖

我們僅僅使用了

使用createPopper函數(shù),需要傳遞兩個(gè)參數(shù):參考元素(reference element)和彈出式元素(popper element),以及一個(gè)可選的配置對(duì)象。參考元素是要彈出的元素的參照點(diǎn),而彈出式元素是要彈出的元素本身。

例如,以下是一個(gè)創(chuàng)建彈出式元素的示例代碼:

import { createPopper } from '@popperjs/core';
const referenceElement = document.querySelector('#reference');
const popperElement = document.querySelector('#popper');
const popper = createPopper(referenceElement, popperElement, {
  placement: 'top',
});

上面的代碼中,createPopper函數(shù)接收參考元素和彈出式元素,以及一個(gè)配置對(duì)象。這里的配置對(duì)象中指定了彈出式元素的位置,它將出現(xiàn)在參考元素的上方。

popper是一個(gè)對(duì)象,其中的方法用于進(jìn)一步管理和控制彈出式元素的行為。例如,可以使用update函數(shù)在參考元素或彈出式元素發(fā)生變化時(shí)重新計(jì)算彈出式元素的位置和大小,或者可以使用destroy函數(shù)在不需要彈出式元素時(shí)將其刪除。

createPopper函數(shù)的返回值

包含以下屬性和方法的對(duì)象:

  • state:一個(gè)對(duì)象,包含有關(guān)彈出式元素的位置、大小和其他信息的狀態(tài)信息。
  • update:一個(gè)函數(shù),用于更新彈出式元素的位置和大小。
  • forceUpdate:一個(gè)函數(shù),用于強(qiáng)制更新彈出式元素的位置和大小。
  • destroy:一個(gè)函數(shù),用于刪除彈出式元素并清除其事件偵聽器。
  • setOptions: 這個(gè)函數(shù)用于更新彈出式元素的配置選項(xiàng)。

上面我們的案例是如何實(shí)現(xiàn)自動(dòng)定位的呢,也就是createPopper函數(shù)調(diào)用后,

const popper = createPopper(referenceElement, popperElement, {
  placement: 'top',
});

popperElement自動(dòng)定位到referenceElement元素的上面了,原因就是createPopper在執(zhí)行過程中,調(diào)用了setOptions方法,所以我們只要看一下setOptions方法如何實(shí)現(xiàn),就知道了它如何實(shí)現(xiàn)自動(dòng)定位了。

注:這里我們不加入任何中間件,這樣會(huì)提高復(fù)雜度,后面再講幾個(gè)典型的中間件實(shí)現(xiàn)原理。

setOptions方法本質(zhì)上是調(diào)用了forceUpdate方法。

forceUpdate() {
        const { reference, popper } = state.elements;
        state.rects = {
          reference: getCompositeRect(
            reference,
            getOffsetParent(popper),
            state.options.strategy === 'fixed'
          ),
          popper: getLayoutRect(popper),
        };
}

我們先開第一部分,reference, popper是啥意思呢,如下,reference就是referenceElement,popper就是popperElement。

const popper = createPopper(referenceElement, popperElement, {
  placement: 'top',
});

state.rects是啥意思呢,簡(jiǎn)單來說,就是包含了reference的getBoundingClientRect的結(jié)果,popper也是包含了reference的getBoundingClientRect的結(jié)果。

這里再簡(jiǎn)單講一下 getBoundingClientRect是什么。

含義:

方法返回元素的大小及其相對(duì)于視口的位置。

值:

返回值是一個(gè) DOMRect 對(duì)象,這個(gè)對(duì)象是由該元素的 getClientRects() 方法返回的一組矩形的集合, 即:是與該元素相關(guān)的CSS 邊框集合。

屬性值:

  • top: 元素上邊距離頁(yè)面上邊的距離
  • left: 元素右邊距離頁(yè)面左邊的距離
  • right: 元素右邊距離頁(yè)面左邊的距離
  • bottom: 元素下邊距離頁(yè)面上邊的距離
  • width: 元素寬度
  • height: 元素高度

為什么需要這些屬性呢?你想想,我絕對(duì)定位某個(gè)元素,我知道了另一個(gè)元素的坐標(biāo),是不是絕對(duì)定位上去就很簡(jiǎn)單了?

這也是定位組件最最最基本的思想,所有的定位組件都差不多。

接著講:

forceUpdate() {
        const { reference, popper } = state.elements;
        state.rects = {
          reference: getCompositeRect(
            reference,
            getOffsetParent(popper),
            state.options.strategy === 'fixed'
          ),
          popper: getLayoutRect(popper),
        };
}

為什么這里要用getCompositeRect來代替getBoundingClientRect的功能,其實(shí)里面主要也是用了getBoundingClientRect的功能。

最主要的區(qū)別就是一些非常細(xì)節(jié)的處理了:

絕對(duì)定位的坐標(biāo)受到transfrom: scale的影響

我們舉個(gè)例子:

  <style>
    #a {
      margin: 0 auto;
      width: 500px;
      position: relative;
      transform: scale(2.5);
    }
    #tooltip {
      background: #333;
      color: white;
      font-weight: bold;
      padding: 4px 8px;
      font-size: 13px;
      border-radius: 4px;
    }
  </style>
  <body>
    <div id="a">
      <button id="button" aria-describedby="tooltip">My button</button>
      <div id="tooltip" role="tooltip">My tooltip</div>
    </div>

注意,id是a的div元素,有可能transform的scale出現(xiàn)變化,那么你定位的時(shí)候,是不是要找出scale的值是2.5,然后在正常scale(1)的情況下,決定定位的x,y,width,height都要乘以2.5。

那么問題來了,怎么計(jì)算scale的值呢?有人說了,我可以用getComputedStyle獲取到,問題來了,我還可以用直接在css上設(shè)置scale屬性,縮小和放大,我還可以一起上兩個(gè)屬性,你咋辦?

所以我們要用以下的方法

const dom= xxx; //假設(shè)獲取到了某個(gè)dom元素
dom.getBoundingClientRect().width / dom.offsetWith

學(xué)到了吧,我真的強(qiáng)烈大家多看看開源的好的代碼,你們自己項(xiàng)目很多前端不可能知道這些細(xì)節(jié)的。

好了,繼續(xù)!請(qǐng)問相對(duì)定位的元素如何查找?

有人說了,廢話,文章開頭不是說了嗎,相當(dāng)于offsetParent或者有一些例如css屬性是transform等等屬性的dom元素。

這里面又充滿了坑!

例如,如果是offsetParent是table元素的情況,table元素,并且定位是static的話,我們需要繼續(xù)網(wǎng)上找offsetParent,為啥呢?

如果一個(gè)元素的父元素是一個(gè)table元素,而該元素又沒有顯式地設(shè)置position屬性,那么該元素的offsetParent會(huì)被設(shè)置為table元素的父元素。

所以通常offsetParent屬性得到的是position是非static的元素,這個(gè)就出現(xiàn)問題了?。ㄟ€有一些小細(xì)節(jié),繼續(xù)說下去就太多內(nèi)容了)

計(jì)算相當(dāng)于最近的offsetParent元素,如何計(jì)算絕對(duì)定位的值

源碼核心如下:

 const rect = element.getBoundingClientRect();
 const scroll = getNodeScroll(offsetParent);
  offsets = getBoundingClientRect(offsetParent, true);
  offsets.x += offsetParent.clientLeft;
  offsets.y += offsetParent.clientTop;
 return {
    x: rect.left + scroll.scrollLeft - offsets.x,
    y: rect.top + scroll.scrollTop - offsets.y,
    width: rect.width,
    height: rect.height,
  }

這里的rect是reference元素,scroll可以的話,如果offsetParent我們簡(jiǎn)單看做是window元素,然后獲取的是滾動(dòng)條的滾動(dòng)距離,offsets.x是offsetParent的left + offsetParent.clientLeft的和。

為什么這么算呢,你看啊,reference.left - offsetParent.x(可以認(rèn)為是offsetParent.left),得到的是reference元素左側(cè)到offsetParent元素左側(cè)的距離。

然后上面得到的值加上滾動(dòng)條距離,是不是就是renference元素在offsetParent中的坐標(biāo)了。

注意,源碼里的絕對(duì)定位,雖然position:absolute,但是位移用的transform,而不是top,left這種,目的是提高性能

中間件處理

const orderedModifiers = orderModifiers(
  mergeByName([...defaultModifiers, ...state.options.modifiers])
);
// Strip out disabled modifiers
state.orderedModifiers = orderedModifiers.filter((m) => m.enabled);
state.orderedModifiers.forEach(
  (modifier) =>
    (state.modifiersData[modifier.name] = {
      ...modifier.data,
    })
);

首先mergeByName是什么意思,主要是把所有中間件合并了,一個(gè)中間件長(zhǎng)啥樣呢,如下:

{
  name: 'offset',
  enabled: true,
  phase: 'main',
  requires: ['popperOffsets'],
  fn: offset,
}

上面一個(gè)命名為offset的中間件,處理的生命周期在'main'這個(gè)生命周期中。處理這個(gè)offset的中間件函數(shù)是fn屬性里的offset函數(shù),我們跳過,這個(gè)函數(shù)的實(shí)現(xiàn),因?yàn)槲覀冎皇菫榱撕?jiǎn)單介紹中間件是什么。

后面我們會(huì)講生命周期鉤子函數(shù)。

mergeByName簡(jiǎn)單來說,就是我們的中間件如下:

[
{
  name: 'offset',
  enabled: true,
  phase: 'main',
  requires: ['popperOffsets'],
  fn: offset,
},
{
  name: 'offset',
  enabled: true,
  phase: 'main',
  requires: ['popperOffsets'],
  fn: offset1,
}
]

也就是可能有重名的中間件,然后將他們合并,我們看到上面數(shù)組第一個(gè)元素的fn是offset,第二個(gè)是offset1,此時(shí)offset1就會(huì)覆蓋offset,也就是所有中間件最終只能有一個(gè)名字唯一的去處理它。

最終合并為

[
{
  name: 'offset',
  enabled: true,
  phase: 'main',
  requires: ['popperOffsets'],
  fn: offset1,
}
]

orderModifiers

上面處理過后會(huì)把結(jié)果傳給orderModifiers,它會(huì)做兩件事:

  • 1、處理依賴
  • 2、按照生命周期分層

處理依賴

如何處理依賴呢,我們看到上面的 offset中間件有一個(gè) requires: ['popperOffsets'],意思是offset中間件加載之前,首先要popperOffsets中間件處理。所以我們遇到這種情況就要先加載popperOffsets中間件。

注意,這里并沒有處理循環(huán)依賴的情況,需要使用者自己注意(循環(huán)依賴最終會(huì)報(bào)錯(cuò),因?yàn)榭隙〞?huì)棧溢出)。

我們簡(jiǎn)單看下這個(gè)order函數(shù)如何處理依賴關(guān)系。

function order(modifiers) {
  const map = new Map();
  const visited = new Set();
  const result = [];
  modifiers.forEach(modifier => {
    map.set(modifier.name, modifier);
  });
  // On visiting object, check for its dependencies and visit them recursively
  function sort(modifier: Modifier<any, any>) {
    visited.add(modifier.name);
    const requires = [
      ...(modifier.requires || []),
      ...(modifier.requiresIfExists || []),
    ];
    requires.forEach(dep => {
      if (!visited.has(dep)) {
        const depModifier = map.get(dep);
        if (depModifier) {
          sort(depModifier);
        }
      }
    });
    result.push(modifier);
  }
  modifiers.forEach(modifier => {
    if (!visited.has(modifier.name)) {
      // check for visited object
      sort(modifier);
    }
  });
  return result;
}

這里的關(guān)鍵就是sort函數(shù),首先visited函數(shù)會(huì)判斷在加載某個(gè)中間件時(shí),你是否有依賴,有的話,我看看我之前加載過沒有,沒有的話我就先加載依賴。

按照生命周期分層

代碼如下

modifierPhases.reduce((acc, phase) => {
    return acc.concat(
      orderedModifiers.filter(modifier => modifier.phase === phase)
    );
  }, []);

modifierPhases是一個(gè)字符串?dāng)?shù)組,這個(gè)數(shù)組的順序就是生命周期鉤子函數(shù)的順序,或者說處理中間件的順序。

// 如下的變量看做字符串即可
const modifierPhases = [
  beforeRead,
  read,
  afterRead,
  beforeMain,
  main,
  afterMain,
  beforeWrite,
  write,
  afterWrite,
];

通過reduce函數(shù),會(huì)先處理數(shù)組靠前的名字的中間件。

我們接著看剛才的中間件處理流程:

const orderedModifiers = orderModifiers(
  mergeByName([...defaultModifiers, ...state.options.modifiers])
);
// Strip out disabled modifiers
state.orderedModifiers = orderedModifiers.filter((m) =&gt; m.enabled);
state.orderedModifiers.forEach(
  (modifier) =&gt;
    (state.modifiersData[modifier.name] = {
      ...modifier.data,
    })
);

orderedModifiers我們之前介紹了,接著state抽取了所有orderedModifiers中的data數(shù)據(jù),一般情況是沒有這個(gè)數(shù)據(jù)的。

最后orderedModifiers也掛載到了state.orderedModifiers上。

簡(jiǎn)而言之,中間件就是把我們定位坐標(biāo)進(jìn)行了變換,或者添加了監(jiān)聽事件

比如絕對(duì)定位好的坐標(biāo),如果滾動(dòng)條滾動(dòng),是不是要更新坐標(biāo)才能繼續(xù)定位準(zhǔn)確?

這里主邏輯就解釋完了,然后有人就會(huì)說what????沒有寫什么時(shí)候把定位的坐標(biāo)賦給定位元素?。?!

這個(gè)邏輯是寫在中間件里的,所以自然而然我們開始講中間件。

所有官方中間件都會(huì)講

eventListeners中間件

這個(gè)中間件簡(jiǎn)單來說就是遞歸尋找所有的父元素,如果有滾動(dòng)條的話,就加上scroll事件,然后觸發(fā)更新定位坐標(biāo)。

為啥要更新定位坐標(biāo)上面已經(jīng)說的很清楚了唄。

順便再給window事件加上resize事件,這個(gè)也是為了害怕resize窗口導(dǎo)致定位元素定位偏離。

popperOffsets中間件

簡(jiǎn)單來說,就是根據(jù)placement計(jì)算坐標(biāo),placement比如是top,就是絕對(duì)定位到某個(gè)元素的上方,而且是居中對(duì)齊。

這個(gè)坐標(biāo)咋算呢,我簡(jiǎn)單說下頂部居中對(duì)齊,大家自己算就行了

  const commonX = reference.x + reference.width / 2 - element.width / 2;
    case top:
      offsets = {
        x: commonX,
        y: reference.y - element.height,
      };

最后得到的定位坐標(biāo)放到了state屬性上,如下:

state.modifiersData[popperOffsets] = 定位坐標(biāo)

computeStyle中間件

如果state上的popperOffsets屬性不為null,也就是我們上面計(jì)算過的popperOffsets。然后給定義新的定位元素的坐標(biāo)。

有人會(huì)問了,為啥要定義新的坐標(biāo)

  if (state.modifiersData.popperOffsets != null) {
    state.styles.popper = {
      ...state.styles.popper,
      ...mapToStyles({
        placement: getBasePlacement(state.placement),
        variation: getVariation(state.placement),
        popper: state.elements.popper,
        popperRect: state.rects.popper,
        gpuAcceleration,
        isFixed: state.options.strategy === 'fixed',
        offsets: state.modifiersData.popperOffsets,
        position: state.options.strategy,
        adaptive,
        roundOffsets,
      }),
    };
  }

可以看到,核心的是mapToStyles這個(gè)處理函數(shù)。我們看下它的實(shí)現(xiàn),簡(jiǎn)單來說:

  • 如果gpuAcceleration參數(shù)為true,那么我們的定位使用transfrom,否則使用left,top這種方式定位

  • 如果adaptive為true,假設(shè)reference元素變寬或者變窄(比如一段文字),它會(huì)自動(dòng)定位上去

applyStyles中間件

這個(gè)很簡(jiǎn)單,上面我們不是把定位的坐標(biāo)求出來了嗎,這個(gè)中間件就是把定位組件的styles屬性合并上去的,源碼如下,element就是定位元素,這種方式值得大家學(xué)習(xí),而不是直接賦值給style。

    const attributes = state.attributes[name] || {};
    Object.assign(element.style, style);

offset中間件

這個(gè)太簡(jiǎn)單了,偏移距離用的,請(qǐng)看下圖:

flip中間件

原理是,比如我們現(xiàn)在placement:bottom,表示定位到reference元素的下方,當(dāng)我們向下滾動(dòng)的時(shí)候,是不是這個(gè)定位的元素因?yàn)樵谙路?,遲早會(huì)到視口的下面,如下圖:

為了能看見tooltip,我們自動(dòng)翻轉(zhuǎn)到上方!

這就是flip的功能,至于如何實(shí)現(xiàn),我們馬上分析:

假設(shè)我們傳入的placement是bottom,會(huì)自動(dòng)計(jì)算它相反的位置:最后生成['bottom','top'],意思是如果bottom超出視口邊界,就轉(zhuǎn)到top的位置去。

這個(gè)位置我們還可以外界自定義,默認(rèn)的是placement是top,那么就生成['top','bottom'],如果是left就生成['left', 'right'],也就是自己的位置和相反的位置。

然后通過一個(gè)函數(shù)detectOverflow(建議大家可以單獨(dú)copy一份這個(gè)函數(shù)的代碼,表示是否傳入的元素已經(jīng)超過視口的)

但是原理也很簡(jiǎn)單,如果我去寫的話,就是判斷當(dāng)前元素的最上邊是否超過定位它的父元素的最上邊,最左邊和其他方向都是一樣的。比較坐標(biāo)嘛。

然后如果超出也很簡(jiǎn)單,你超出了top,你就返回top: true,沒有就返回top:false,我知道如果超出不就馬上計(jì)算另一個(gè)方向的坐標(biāo)了嗎

以上就是react 定位組件源碼解析的詳細(xì)內(nèi)容,更多關(guān)于react 定位組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • react項(xiàng)目中使用插件配置路由的方法

    react項(xiàng)目中使用插件配置路由的方法

    這篇文章主要介紹了react項(xiàng)目中使用插件配置路由的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • ahooks?useRequest源碼精讀解析

    ahooks?useRequest源碼精讀解析

    這篇文章主要為大家介紹了ahooks?useRequest的源碼精讀解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 在React中強(qiáng)制重新渲染的4 種方式案例代碼

    在React中強(qiáng)制重新渲染的4 種方式案例代碼

    這篇文章主要介紹了在React中強(qiáng)制重新渲染的4 種方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • 如何強(qiáng)制刷新react hooks組件

    如何強(qiáng)制刷新react hooks組件

    這篇文章主要介紹了如何強(qiáng)制刷新react hooks組件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • React state狀態(tài)屬性詳細(xì)講解

    React state狀態(tài)屬性詳細(xì)講解

    React將組件(component)看成一個(gè)狀態(tài)機(jī)(State Machines),通過其內(nèi)部自定義的狀態(tài)(State)和生命周期(Lifecycle)實(shí)現(xiàn)并與用戶交互,維持組件的不同狀態(tài)
    2022-09-09
  • react實(shí)現(xiàn)動(dòng)態(tài)選擇框

    react實(shí)現(xiàn)動(dòng)態(tài)選擇框

    這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)動(dòng)態(tài)選擇框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • React-Native使用Mobx實(shí)現(xiàn)購(gòu)物車功能

    React-Native使用Mobx實(shí)現(xiàn)購(gòu)物車功能

    本篇文章主要介紹了React-Native使用Mobx實(shí)現(xiàn)購(gòu)物車功能,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • react實(shí)現(xiàn)組件狀態(tài)緩存的示例代碼

    react實(shí)現(xiàn)組件狀態(tài)緩存的示例代碼

    本文主要介紹了react實(shí)現(xiàn)組件狀態(tài)緩存的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • React學(xué)習(xí)筆記之條件渲染(一)

    React學(xué)習(xí)筆記之條件渲染(一)

    條件渲染在React里就和js里的條件語(yǔ)句一樣。下面這篇文章主要給大家介紹了關(guān)于React學(xué)習(xí)記錄之條件渲染的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-07-07
  • 對(duì)react中間件的理解

    對(duì)react中間件的理解

    這篇文章主要介紹了對(duì)react中間件的理解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11

最新評(píng)論