成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

React造輪系列:Layout 組件思路

neroneroffy / 1346人閱讀

摘要:本文是造輪系列第三篇。造輪子系列組件思路造輪系列對(duì)話框組件思路想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳博客一年百來(lái)篇優(yōu)質(zhì)文章等著你初始化參考組件分別分為五個(gè)組件。參考方應(yīng)杭老師的造輪子課程交流干貨系列文章匯總?cè)缦?,覺(jué)得不錯(cuò)點(diǎn)個(gè),歡迎加群互相學(xué)習(xí)。

本文是React造輪系列第三篇。

1.React 造輪子系列:Icon 組件思路

2.React造輪系列:對(duì)話框組件 - Dialog 思路

想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你!

初始化 Layout

參考 And Design ,Layout 組件分別分為 Layout, Header, Aside, Content,Footer 五個(gè)組件?;臼褂媒Y(jié)構(gòu)如下:


  
header
content
footer

假如我們想直接在 Layout 組件添加 styleclassName 如:


 // 同上

這樣寫并不支持,我們需要在組件內(nèi)聲明它:

// lib/layout/layout.tsx
interface Props {
  style: CSSProperties,
  className: string
}

const Layout: React.FunctionComponent = (props) => {
  return (
    
{props.children}
) }

注意這個(gè) style 是一個(gè) CSSProperties,如果不知道 style 是什么類型的,這邊有間技巧就是在正常 div 上寫 style,然后通過(guò) IDE 功能跳轉(zhuǎn)到定義代碼塊,就能知道類型了。

上面寫法看上去沒(méi)問(wèn)題,但如果我還想支持 id 或者 src 等 html 原生的屬性呢,是不是要一個(gè)一個(gè)的寫呢,當(dāng)然不是,因?yàn)榻涌谑强梢岳^承的,我們直接繼承 MapHTMLAttributes 即可:

interface Props extends React.MapHTMLAttributes{
}

接下就是使用傳入的 style, className:

const Layout: React.FunctionComponent = (props) => {
  const {className, ...rest} = props
  return (
    
{props.children}
) }

這里的 sc 是做第一個(gè)輪子的時(shí)候封裝,對(duì)應(yīng)的方法如下:

function scopedClassMaker(prefix: string) {
  return function x(name?: string) {
    const result = [prefix, name].filter(Boolean).join("-");
      return [result, options && options.extra].filter(Boolean).join(" ")
  };
}

export {scopedClassMaker};

從上述的實(shí)現(xiàn)方式,可以發(fā)現(xiàn)問(wèn)題,如果我們直接在組件內(nèi)寫 className={sc(""), className}, 我們通過(guò) sc 方法生成的函數(shù)會(huì)被傳入的 className 覆蓋。所以需要就 sc 方法進(jìn)一步驟改造,擴(kuò)展傳入 className,實(shí)現(xiàn)方式如下:

interface Options {
  extra: string | undefined
}


function scopedClassMaker(prefix: string) {
  return function x(name?: string, options ?:Options ) {
    const result = [prefix, name].filter(Boolean).join("-");
    if (options && options.extra) {
      return [result, options && options.extra].filter(Boolean).join(" ")
    } else {
      return result;
    }
  };
}

export {scopedClassMaker};

如果懂 Es6 閱讀以下代碼應(yīng)該很容易,這里就一在詳細(xì)講了。

然后調(diào)用方式如下:

// lib/layout/layout.tsx
...
const Layout: React.FunctionComponent = (props) => {
  const {className, ...rest} = props
  return (
    
{props.children}
) } ...

在回顧一下,開始的結(jié)構(gòu):

//lib/layout/layout.example.tsx

  
header
content
footer

再次運(yùn)行:

這里有個(gè)問(wèn)題,實(shí)際我們想要的效果是 Content 內(nèi)容是要撐開的,所以我們需要使用 flex 來(lái)布局,自動(dòng)填寫使用的 flex-grow 屬性:

// lib/layout/layout.scss
.gu-layout {
  border: 1px solid red;
  display: flex;
  flex-direction: column;
  &-content {
    flex-grow: 1;
  }
}    
  

運(yùn)行效果:

那如果 Layout 里面還有 Layout 呢,如下:

第二個(gè)例子

header
content
footer

運(yùn)行效果:

如果嵌套 Layout,content 還是沒(méi)有撐開。說(shuō)明如果 Layout 里面還有 Layout,那里面的 Layout 應(yīng)該占滿全部。

.gu-layout {
  // 同上
  & & {
    flex-grow: 1;
    border: 1px solid blue;
  }
}

這里說(shuō)明一下 & &, & 表示當(dāng)前的類名,所以就是 & 就是 .gu-layout。

運(yùn)行效果:

這樣有個(gè)問(wèn)題, 如果 Layout 里面有 Layout,這個(gè)里面的一般是左右布局,所以需要設(shè)置水平方向?yàn)?row

  & & {
    flex-grow: 1;
    border: 1px solid blue;
    flex-direction: row;
  }

運(yùn)行效果:

如果想讓 Aside 換到右邊,只需要調(diào)整位置即可。

第三個(gè)例子

header
content
footer

運(yùn)行效果:

在來(lái)看別外一種布局:

第四個(gè)例子

header
content
footer

運(yùn)行效果:

可以看到 我們希望當(dāng)有 Aside 組件時(shí),需要的是左右布局,當(dāng)前的樣式無(wú)法滿足,需要再次調(diào)整,參考 AntD 設(shè)計(jì),當(dāng)有里面有 Aside 組件, Layout 就多了一個(gè)左右布局的樣式的 className,所以我們要在 Layout 組件檢測(cè) children 類型。

實(shí)現(xiàn)思路是,可以先在 Layout 組件內(nèi)打印 children

所以我可以通過(guò)遍歷 children 來(lái)判斷,實(shí)現(xiàn)如下:

props.children.map(node => {
  console.log(node)
})

這邊不能直接使用 map,因?yàn)?children 的類型有5種, ReactChild, ReactFragment ,ReactPortal,boolean, null, undefined,所以這里需要對(duì) children 進(jìn)行約束,至少要有一個(gè)元素。

// lib/layout/layout.tsx

interface Props extends React.MapHTMLAttributes{
  children: ReactElement | Array 
}

const Layout: React.FunctionComponent = (props) => {
  const {className, ...rest} = props
  let hasAside = false
  if ((props.children as Array).length) {
    (props.children as Array).map(node => {
      if (node.type === Aside) {
        hasAside = true
      }
    })
  }
  return (
    
{props.children}
) } export default Layout

添加對(duì)應(yīng)的 css:

.gu-layout {
  ...
  &.hasAside {
    flex-direction: row;
    .gu-layout{
      flex-direction: column
    }
  }
  ...
}

運(yùn)行效果:

上述寫法,有些問(wèn)題,這一個(gè)就是使用到了 let 聲明,這們就不符合我們函數(shù)式編程了,第二個(gè) sc 方法還需要進(jìn)一步改善。

刪除代碼里的 let

在上述代碼中,我們使用了一個(gè) let hasAside = false,來(lái)判斷 Layout 里面是否有 Aside,這樣寫就不符合我們函數(shù)式的定義了。

其實(shí)我們做的是通過(guò)遍歷,然后一個(gè)一個(gè)判斷是否有 Aside ,如果有剛設(shè)置為 true, 從上圖可以看出,我們最后可以把所有判斷結(jié)果 或(|)起來(lái),如果為 true ,則有,否則無(wú)。這時(shí)候我們就可以使用 es6 新引入的 reduce 方法了。

// lib/layout/layout.tsx

...
const Layout: React.FunctionComponent = (props) => {
  const {className, ...rest} = props
  if ((props.children as Array).length) {
    const hasAside = (props.children as Array)
      .reduce((result, node) => result || node.type === Aside, false)
  }
  return (
    
{props.children}
) } ...

通過(guò) reduce 改進(jìn)后的方法有個(gè)問(wèn)題,我們 hasAside 是在 if 塊域里面的,外部訪問(wèn)不到,那有沒(méi)有什么辦法刪除 {} 塊作用域呢?

我們把把 if 條件通過(guò) && 放到跟遍歷同一級(jí):

// lib/layout/layout.tsx
...
  const children = props.children as Array
  const hasAside = ( children.length)
    && children.reduce((result, node) => result || node.type === Aside, false)

...
總結(jié)

Layout 組件相對(duì)簡(jiǎn)單,這邊主要介紹一些實(shí)現(xiàn)思路,源碼已經(jīng)到這里。

參考

《方應(yīng)杭老師的React造輪子課程》

交流

干貨系列文章匯總?cè)缦拢X(jué)得不錯(cuò)點(diǎn)個(gè)Star,歡迎 加群 互相學(xué)習(xí)。

https://github.com/qq44924588...

我是小智,公眾號(hào)「大遷世界」作者,對(duì)前端技術(shù)保持學(xué)習(xí)愛好者。我會(huì)經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!

關(guān)注公眾號(hào),后臺(tái)回復(fù)福利,即可看到福利,你懂的。

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

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

相關(guān)文章

  • React造輪系列:對(duì)話框組件 - Dialog 思路

    摘要:本文是造輪系列第二篇。實(shí)現(xiàn)方式事件處理跟差不多,唯一多了一步就是當(dāng)點(diǎn)擊或者的時(shí)候,如果外部有回調(diào)就需要調(diào)用對(duì)應(yīng)的回調(diào)函數(shù)。 本文是React造輪系列第二篇。 1.React 造輪子系列:Icon 組件思路 本輪子是通過(guò) React + TypeScript + Webpack 搭建的,至于環(huán)境的搭建這邊就不在細(xì)說(shuō)了,自己動(dòng)手谷歌吧。當(dāng)然可以參考我的源碼。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳Git...

    qianfeng 評(píng)論0 收藏0
  • 動(dòng)手造輪 | 一款Bash 腳本 +HTTP 請(qǐng)求工具 +JSON 解析工具組成的測(cè)試小工具

    摘要:數(shù)人云開源一款容器管理工具,開發(fā)過(guò)程中,為了保證的健壯性和穩(wěn)定性,數(shù)人云開發(fā)團(tuán)隊(duì)自制了一套適合測(cè)試的小工具。于是一款簡(jiǎn)單的腳本請(qǐng)求工具解析工具組成的測(cè)試小工具雛形出現(xiàn)了。是一款命令行解析文本的工具,支持非常多的語(yǔ)法解析構(gòu)造重組文本。 數(shù)人云開源一款容器管理工具Crane,Crane開發(fā)過(guò)程中,為了保證API的健壯性和穩(wěn)定性, 數(shù)人云開發(fā)團(tuán)隊(duì)自制了一套適合Crane API測(cè)試的小工具。...

    hyuan 評(píng)論0 收藏0
  • 淺說(shuō)虛擬列表的實(shí)現(xiàn)原理

    摘要:虛擬列表的實(shí)現(xiàn)有多種方案,本文以組件為基礎(chǔ)進(jìn)行分析。常見的無(wú)限滾動(dòng)便是延遲渲染的一種實(shí)現(xiàn),而虛擬列表則是按需渲染的一種實(shí)現(xiàn)。接下來(lái),本文會(huì)簡(jiǎn)單介紹虛擬列表的一種實(shí)現(xiàn)方案。實(shí)現(xiàn)本章節(jié)將會(huì)創(chuàng)建一個(gè)組件,并結(jié)合代碼,慢慢梳理虛擬列表的實(shí)現(xiàn)。 在 列表數(shù)據(jù)的展示優(yōu)化 一文中,提到了對(duì)于列表形態(tài)的數(shù)據(jù)展示的按需渲染。這種方式是指根據(jù)容器元素的高度以及列表項(xiàng)元素的高度來(lái)顯示長(zhǎng)列表數(shù)據(jù)中的某一個(gè)部分...

    趙春朋 評(píng)論0 收藏0
  • B站Up主-山地人-這位老哥2019年的前端自學(xué)計(jì)劃進(jìn)展如何?——講一個(gè)B站Up主自學(xué)前端85天的故

    摘要:前言自從上次在掘金發(fā)布年山地人的前端完整自學(xué)計(jì)劃講一個(gè)站主山地人的天前端自學(xué)故事以來(lái),一眨眼山地人老哥在站做主已經(jīng)有天了。所以這個(gè)體系里的一些框架包括也是山地人年自學(xué)計(jì)劃的一部分。月底,山地人老哥開啟了的兩個(gè)專題。 前言 自從上次在掘金發(fā)布【2019年山地人的前端完整自學(xué)計(jì)劃——講一個(gè)B站UP主山地人的40天前端自學(xué)故事】 以來(lái),一眨眼山地人老哥在B站做Up主已經(jīng)有85天了。 時(shí)隔一個(gè)...

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

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

0條評(píng)論

閱讀需要支付1元查看
<