最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue和react中關于插槽詳解

 更新時間:2022年08月19日 11:34:52   作者:yxnne???????  
這篇文章主要介紹了vue和react中關于插槽詳解,slot插槽是Vue對組件嵌套這種擴展機制的稱謂,在react可以也這樣稱呼,但是并不很常見。不過叫slot確實很形象

簡述Slot

slot插槽是Vue對組件嵌套這種擴展機制的稱謂,在react可以也這樣稱呼,但是并不很常見。不過叫slot確實很形象。

這樣的形式就是slot插槽:

vue

<template>
  <container-comp>
    <content></content>
    <footer></footer>
  </container-comp>
</template>

react

() => (
  <ContainerComp>
    <Content />
    <Footer />
  </ContainerComp>
)

(我們可以把container-comp稱之為容器組件,把content、footer稱之為子組件)

這種機制的好處主要在于,在某個容器提供的模版或者數(shù)據中,可以根據需求靈活擴展需要渲染的子組件。專業(yè)點說就是通過容器和子組件之間的協(xié)議(數(shù)據交換和渲染方式),將彼此邏輯獨立解藕,提升了各自的復用性。

舉個例子,容器組件提供了一份渲染模版,將各個模塊的位置預留出來,使用的時候根據各個子組件的順序或者插槽名稱,在不同場景可以選擇不同的子組件。

再舉個使用插槽的例子,容器組件中提供一些數(shù)據,比如定時請求某種接口得到數(shù)據,或者監(jiān)聽,訂閱一些數(shù)據,比如在掛載完成后監(jiān)聽鼠標事件,得到位置數(shù)據。數(shù)據拿到之后,具體的對數(shù)據的渲染方式交給子組件來做,而這時候,容器可以通過參數(shù)傳遞的方式將得到的數(shù)據交給子組件。

通過上面簡單的的例子描述,可以看到,使用插槽的的代碼設計符合單一職責原則,邏輯更加內聚。

而不管是vue還是react上述描述的這些功能都是支持的,只是有的叫法略有所別,但是其目的一致。(因為近期在項目中使用vue多一點,而之前對vue的了解只是籠統(tǒng)的學習過響應式原理,并沒有真正在項目里寫過vue,所以,近期希望結合vue和react,來系統(tǒng)的回顧回顧相關的知識點。)

下面就先看下vue中的插槽都有什么功能。一邊看vue,一邊對比react。 參考這里:vue2官網:slot,可以看到,插槽相關的核心功能有:

  • 基本渲染插槽內容;
  • 具名插槽:一個容器多個插槽,需要分別命名;
  • 插槽傳遞參數(shù),屬于相對高級點的用法;

基本插槽

vue基本插槽

最簡單插槽用法就像下面這樣:

<template>
  <main-comp>
    <div>內容</div>
    <!--  
    可以是任何自定義組件
    <my-sub></my-sub>
    -->
  </main-comp>
</template>

main-comp就是容器組件,而我們將<div>內容</div>作為容器的子元素,那么,容器里面怎么寫呢?

<template>
  <div class="main">
    <slot>后備信息,以防萬一</slot>
  </div>
</template>

可以看到,在容器里面簡單的使用slot標簽,相當于占位。當組件渲染的時候,<slot></slot> 將會被替換為<div>內容</div>,如果沒有使用時插槽的話,會渲染出slot標簽內的內容:“后備信息,以防萬一”。當然,使用的插槽不止是<div>內容<div>這么簡單,可以是任何自定義組件。

ok,對應react中實現(xiàn)對應的代碼怎么寫呢?

react基本插槽

使用插槽組件:

() => (
  <MainComp>
    <div>內容</div>
    {/* <MySub />  可以是任何自定義組件 */}
  </MainComp>
)

容器中定義插槽:

const MainComp = (props) => {
  return (
    <div class="main">
      {props.children ?? '后備信息,以防萬一'}
    </div>
  )
}

react中,組件的子組件都存在props.children中,所以直接在jsx中渲染對應的位置渲染props.children變量就可以了,而后備內容可以應用任何js語法,來判斷props.children收否存在,從而顯示后備內容與否。

具名插槽

vue具名插槽

上面是最簡單的場景,但有時候,一個容器需要渲染很多插槽,比如需要渲染一個內容區(qū)域content和一個底部區(qū)域footer,這時候就需要對插槽命名了,稱之為具名插槽: 下面main-comp組件要使用兩個插槽,分別命名為content和footer:

<template>
  <main-comp>
    <template v-slot:content>
      <sub-comp1></sub-comp1>
    </template>
    <template  v-slot:footer>
      <footer-comp></footer-comp>
    </template>
  </main-comp>
</template>

定義插槽:

<template>
  <div>
    <slot name="content"></slot>
    <slot name="footer"></slot>
  </div>
</template>

slot用name屬性標注了其名字“xxx”,對應使用的時候要用v-slot:xxx,這樣“xxx”的template就會對應替換成name是xxx的slot的位置。有一點需要注意,v-slot這個指令對template生效,也就是說,要使用具名插槽,必須要用template將內容包裹起來。

另外,如果slot顯示指定name,其實它對應也是有name的,它默認的name叫default。

react具名插槽的討論

具名插槽,對應react的話,我用了這些年react,還真沒聽過“具名插槽”這個稱謂。不過盡管沒有100%一致的對應vue的具名插槽,但類似的功能有幾種實現(xiàn)方式:

模仿具名插槽

a. 用次序約定:

我們知道react的“插槽”寫法(嵌套子組件),子組件都是作為props.children數(shù)組的子元素,那么其實最簡單的一種方式就是,children的次序對應著某個子插槽。比如:
使用時:

() => {
  return (
    <MainComp>
      <SubComp1 />
      <FooterComp />
    </MainComp>
  )
}

那么,props.children[0]對應的就是SubComp1,而props.children[1]對應的就是FooterComp,所以在MainComp內部就可以這樣:

const MainComp = (props) => {
  const content = props.children[0]
  const footer = props.children[1]
  
  return (
  <div>
    { content }
    { footer }
  </div>
  )
}

但是上述寫法的問題在于:具名呢?說好的名稱呢?使用的時候順序亂了咋辦?

b. 傳遞對象:

想要實現(xiàn)具名,可以下面這樣寫法,本質還是props.children,我們把對象作為“插槽”內容,對象的key就是插槽名稱,value就是子組件:

() => {
  return (
    <MainComp>
      {
        {
          content:(<SubComp1 />),
          footer:(<FooterComp />)
        }
      }
    </MainComp>
  )
}

對應的MainComp:

const MainComp = (props) => {
  const { content, footer  } = props.children
  return (
  <div>
    { content }
    { footer }
  </div>
  )
}

這里這個props.children可以直接解構對象的屬性。(有一點要注意的是:props.children不一定是數(shù)組,當只有一個元素的時候就不是數(shù)組)。

c. 判斷組件的自定義靜態(tài),實現(xiàn)具名

上述這種寫法看上去和vue的功能一致了,但是坦白講,這樣的代碼在react世界里面實屬罕見。不是說寫法錯誤,但是似乎不那么符合使用習慣。

react中類似具名的插槽其實還可以通過給子組件顯示命名方式實現(xiàn),其實就是給子組件掛了個靜態(tài)變量:

const Content = () => (<div>I am Content</div>)
const Footer = (props) => (<div>Footer Here {props.info}</div>)

// 兩個子組件標記出來
Content.compName =  'content'
Footer.compName =  'footer'

這樣在容器組件中就能通過這兩個標記,識別出對應的組件:

export function MainComp(props) {

  const isMany = React.Children.count(props.children) > 0
  let footer = (<div>footer</div>)
  let content = (<div>content</div>)

  if (isMany) { 
    React.Children.forEach(props.children, item => {
      const { compName } = item.type
      // 判斷子組件類型
      if (compName === 'footer') footer = item
      if (compName === 'content') content = item
    })
  }

  return (
    <div>
      title text<br/> 
      { content }
      { footer }
    </div>
  )
}

這里面用了幾個React.Children的方法來判斷props.children,核心邏輯是當children是數(shù)組時,遍歷每一個子項,判斷其“name”(這里我們的約定為compName),再根據name設置對應需要渲染的子組件的變量。

isMany部分也可以這樣寫:

  try {
    React.Children.only(children)
  } catch (e) {
    React.Children.forEach(children, item => {
      const { compName } = item.type
      if (compName === 'footer') footer = item
      if (compName === 'content') content = item
    })
  }

這樣我們在使用“插槽”組件的時候就不用擔心子組件次序問題了:

() => {
  return (
    <MainComp>
      <Footer /> {/* 先寫footer還是能正確的渲染出來 */}
      <Content />
    </MainComp>
  )
}

上面a、b、c三種方法實現(xiàn)了和vue一樣的具名的slot,第一種只是簡單的次序對應,第二種能實現(xiàn),但是不太符合react習慣,第三種能實現(xiàn),也是react的寫法。

不過,一般簡單的需求,沒必要用第三種,可以直接使用屬性傳遞組件,我也不知道應該怎么叫,就叫屬性插槽吧。

屬性插槽

一個更符合react習慣,近似實現(xiàn)vue具名slot的方法是,直接傳props,但props的類型是組件:

() => {
  return (
    <MainComp
      content={(<SubComp1 />)}
      footer={(<FooterComp />)}  
    /> 
  )
}

這樣在MainComp的內部直接通過props去拿對應的組件并渲染在適當?shù)奈恢镁托校?/strong>

const MainComp = (props) => {
  const { content, footer } = props
  return (
  <div>
    { content }
    { footer }
  </div>
  )
}

嚴格意義上說,雖然這樣能實現(xiàn)和vue具名插槽一樣的功能,但使用卻不是用插槽的形式。 但是這樣代碼在react世界中,卻是最常見的方式。這可能是兩種框架不同特點導致的微小差異了。

插槽傳參

vue插槽傳參

插槽傳遞參數(shù),可以幫助我們實現(xiàn)一些更高級的功能。

先看下vue中,如何給插槽傳遞參數(shù):

<template>
  <div class="main">
    <slot 
      :styleProps="shareStyle" 
      :data="shareStyle" 
      :description="desc">
    </slot>
  </div>
</template>

上面的代碼是定義slot時候,我們給slot綁定了三個屬性,這看上去和我們使用組件,給組件傳遞參數(shù)的用法沒有什么區(qū)別。

使用slot的時候這樣接收參數(shù):

  <!-- slotProps 是通過main傳遞過來的 -->
  <template v-slot:default="slotProps">
    <!-- 默認插槽可以簡寫成 v-slot -->
    <div :style="slotProps.styleProps">{{ slotProps.description}}</div>
  </template>

首先我們看到使用的時候在template標簽中使用了指令v-slot,即v-slot:default="slotProps",這句話什么意思呢?

就是當前這里template對應default這個名稱的slot(defalut可以省略,上面定義slot的地方也沒寫name=“default”,其實是省略了)。

而這個slotProps表示所有傳遞過來的屬性,也就是說:

slotProps = {
  styleProps, data, description
}

所以在template中,可以使用slotProps上的任何屬性。也可以給作為插槽的自定義組件傳遞參數(shù), 比如:

<template v-slot:rightItem="slotProps">
  <staff :staff="slotProps.data"></staff>
</template>

vue插槽傳參大致就是這樣了,接著看看react吧。

react:render-props

react中其實沒法直接給插槽傳遞參數(shù),只能借助一點技術手段:函數(shù)。

這種方式有個專有名詞叫:render-props。

render-props的具體的方式就是,子組件作為插槽是用函數(shù)的形式,而容器組件渲染的時候對應的就調用這個函數(shù),在調用函數(shù)的時候,把需要傳遞的參數(shù)傳入函數(shù),這樣在插槽函數(shù)的作用域內就拿到了數(shù)據:

() => {
  return ( 
    <MainComp>
      {
        (data) => (<Staff staff={data} />)
      } 
    </MainComp>
  )
}

看下容器MainComp組件:

const MainComp = (props) => {

  const [data, setData] = useState({})
  useEffect(() => {
    const info = await getData()
    setData(info)
  }, []) 
  return (
    <div>
      {
        props.children && props.children(data)
      }
    </div>
  )
}

當然了,這種函數(shù)形式的“插槽”不止可以用作插槽,用在普通的props上自然也是可以的。在react世界里,凡是要從另一個組件拿數(shù)據的場合,都可以考慮傳個函數(shù):

() => {
  return (
    <MainComp
      staff={(data) => (<Staff staff={data} />)}
    />
  )
}

對應的MainComp,最終也是通過函數(shù)調用給子組件傳遞參數(shù),只是獲取子組件的方式換一下:

const MainComp = (props) => {
  const [data, setData] = useState({})
  useEffect(() => {
    const info = await getData()
    setData(info)
  }, []) 
  return (
    <div>
      {/* 這里變一下 */}
      {
        props.staff && props.staff(data)
      }
    </div>
  )
}

以上就是對兩種框架“插槽”相關的實現(xiàn)方式的簡單總結。

總言之,不管vue或者react,都有著很靈活的用法,上面的這些要素和技巧,都可以在實際項目中可以根據需要自行組合或者擴展。

到此這篇關于vue和react中關于插槽詳解的文章就介紹到這了,更多相關vue react 插槽內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • vue前端HbuliderEslint實時校驗自動修復設置

    vue前端HbuliderEslint實時校驗自動修復設置

    這篇文章主要為大家介紹了vue前端中Hbulider中Eslint實時校驗自動修復設置操作過程,有需要的朋友可以借鑒參考下希望能夠有所幫助
    2021-10-10
  • vue 表單輸入框不支持focus及blur事件的解決方案

    vue 表單輸入框不支持focus及blur事件的解決方案

    這篇文章主要介紹了vue 表單輸入框不支持focus及blur事件的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Vue實現(xiàn)多圖添加顯示和刪除

    Vue實現(xiàn)多圖添加顯示和刪除

    這篇文章主要為大家詳細介紹了Vue實現(xiàn)多圖添加顯示和刪除,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • 用vue設計一個日歷表

    用vue設計一個日歷表

    這篇文章主要介紹了如何用vue設計一個日歷表,幫助大家更好的理解和學習vue框架,感興趣的朋友可以了解下
    2020-12-12
  • Vue與.net?Core?接收List<T>泛型參數(shù)

    Vue與.net?Core?接收List<T>泛型參數(shù)

    這篇文章主要介紹了Vue與.net?Core?接收List<T>泛型參數(shù),文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • vue動態(tài)代理無須重啟項目解決方案詳解

    vue動態(tài)代理無須重啟項目解決方案詳解

    這篇文章主要為大家介紹了vue動態(tài)代理無須重啟項目解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • vue3渲染函數(shù)(h函數(shù))的變更剖析

    vue3渲染函數(shù)(h函數(shù))的變更剖析

    這篇文章主要介紹了vue3渲染函數(shù)(h函數(shù))的變化,文中給大家介紹了h函數(shù)的三個參數(shù)詳細說明及vue3 h函數(shù)-綁定事件,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-10-10
  • Vue 按鈕居中、按鈕居左、按鈕居右的實現(xiàn)代碼

    Vue 按鈕居中、按鈕居左、按鈕居右的實現(xiàn)代碼

    在 Vue 中,如果需要將按鈕居中顯示,可以使用 CSS 中的 `text-align: center` 屬性來實現(xiàn),本文通過實例代碼給大家介紹Vue 按鈕居中、按鈕居左、按鈕居右的實現(xiàn)代碼,感興趣的朋友一起看看吧
    2023-10-10
  • vue 判斷頁面是首次進入還是再次刷新的實例

    vue 判斷頁面是首次進入還是再次刷新的實例

    這篇文章主要介紹了vue 判斷頁面是首次進入還是再次刷新的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue3 el-form-item如何自定義label標簽內容

    vue3 el-form-item如何自定義label標簽內容

    這篇文章主要介紹了vue3 el-form-item如何自定義label標簽內容問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評論

梁平县| 黄山市| 洞口县| 青岛市| 福泉市| 阜康市| 上虞市| 天峨县| 彩票| 海宁市| 玛沁县| 珲春市| 珲春市| 海晏县| 台东县| 顺平县| 祁门县| 南雄市| 枣阳市| 平湖市| 诸暨市| 兴城市| 北安市| 米脂县| 丽江市| 五华县| 乐安县| 永寿县| 拉孜县| 鱼台县| 汉沽区| 西盟| 黄大仙区| 得荣县| 黄冈市| 荃湾区| 江源县| 扶沟县| 独山县| 兴海县| 苍南县|