亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

React造輪系列:Layout 組件思路

neroneroffy / 1344人閱讀

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

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

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

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

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

初始化 Layout

參考 And Design ,Layout 組件分別分為 Layout, Header, Aside, Content,Footer 五個組件?;臼褂媒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}
) }

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

上面寫法看上去沒問題,但如果我還想支持 id 或者 src 等 html 原生的屬性呢,是不是要一個一個的寫呢,當(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 是做第一個輪子的時候封裝,對應(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)問題,如果我們直接在組件內(nèi)寫 className={sc(""), className}, 我們通過 sc 方法生成的函數(shù)會被傳入的 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)行:

這里有個問題,實(shí)際我們想要的效果是 Content 內(nèi)容是要撐開的,所以我們需要使用 flex 來布局,自動填寫使用的 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 呢,如下:

第二個例子

header
content
footer

運(yùn)行效果:

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

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

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

運(yùn)行效果:

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

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

運(yùn)行效果:

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

第三個例子

header
content
footer

運(yùn)行效果:

在來看別外一種布局:

第四個例子

header
content
footer

運(yùn)行效果:

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

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

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

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

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

// 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

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

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

運(yùn)行效果:

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

刪除代碼里的 let

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

其實(shí)我們做的是通過遍歷,然后一個一個判斷是否有 Aside ,如果有剛設(shè)置為 true, 從上圖可以看出,我們最后可以把所有判斷結(jié)果 或(|)起來,如果為 true ,則有,否則無。這時候我們就可以使用 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}
) } ...

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

我們把把 if 條件通過 && 放到跟遍歷同一級:

// 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 組件相對簡單,這邊主要介紹一些實(shí)現(xiàn)思路,源碼已經(jīng)到這里。

參考

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

交流

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

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

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

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

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/104315.html

相關(guān)文章

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

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

    qianfeng 評論0 收藏0
  • 動手造輪 | 一款Bash 腳本 +HTTP 請求工具 +JSON 解析工具組成的測試小工具

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

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

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

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

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

    cocopeak 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<