美文网首页
如何使用TypeScript和Styled-Components

如何使用TypeScript和Styled-Components

作者: 程序员之家 | 来源:发表于2023-06-05 09:40 被阅读0次

近年来,OTT(over-the-top)视频流媒体平台变得更加创新和易于使用。在他们的用户界面中,电影和连续剧的标题排列得清晰可见。

在本教程中,我将指导您完成创建图像轮播组件的过程,该组件看起来就像您在许多 OTT 平台(想想 Netflix)上看到的一样。

我们将从创建原子组件开始,例如Tags、Description、Title等,它们将显示有关每个电影标题的各种信息。然后,我们将通过复合模式将这些组件拼接在一起,以创建一个Banner以图像形式显示每个电影标题的组件。最后,我们将使用该HeroBanner组件使用包构建图像轮播组件Swiper。

(更多优质教程:java567.com,搜"ts")

到本文结束时,您将掌握创建美观且实用的图像轮播组件的知识和技能,这将给您的用户留下深刻印象。让我们开始吧!

目录

先决条件

如何构建横幅组件

如何构建单个组件

如何使用复合图案将所有组件缝合在一起

如何构建图像轮播组件

概括

先决条件

在继续下一节之前,请确保您熟悉以下主题:

CSS – 需要 CSS 的中级知识来设置我们将在本文中创建的小组件的样式。

Styled components——你需要熟悉 styled-components 是什么,因为我们将使用它来创建一个包含静态/动态 css 的组件版本。

复合 模式——我们将使用此模式将各个组件拼接在一起,以便以后可以方便地使用它们。

TypeScript – 我们将在整个教程中使用TypeScript 。它在 JavaScript 之上提供了良好的类型安全。对它有一些基本的了解肯定会在这里有所收获。

如何构建横幅组件

下面的 gif 表示图像轮播组件。如果您不知道什么是图像轮播,那么让我给您做一个简要的概述。

图像轮播是一个组件,由旋转固定次数或可以在导航图标的帮助下旋转的图像组成。

在本教程中,我们将创建此组件。但在进入图像轮播之前,我们将从一个非常基本的组件开始,即横幅组件。

Banner Component 将成为一个帮助我们显示的组件:

标题

标签

描述

背景图

之后,在styled-components和 CSS的帮助下,我们会让它看起来像我们在大多数 OTT 平台上看到的一样漂亮。

构建此组件涉及以下步骤:

构建各个组件

将所有组件与复合图案拼接在一起

如何构建单个组件

我们的横幅组件将由一些无法进一步分解的基本较小组件组成。这些组件称为原子组件。让我们首先构建最简单的组件,即 Title 组件:

首先,创建一个如下所示的功能组件:

constTitle=(props: {title:string})=><div>{props.title}</div>;

我们还需要设置此组件的样式。我们创建一个带样式的 div 组件并将其放置在上面的 Title 组件中,如下所示:

constStyledTitle=styled.div`

font-size: 28px;

font-weight: 600;

color: white;

`;

constTitle=(props: {title:string})=>(

<StyledTitle>{props.title}</StyledTitle>

);

我们阵容中的下一个组件是Tags组件。它是一个 div 元素,它映射到字符串(标签)并将它们显示在元素中span:

创建一个函数式组件,它接受一个字符串数组作为 prop,并使用 map 函数将它们显示在 span 元素中:

constTags=(props: {tags:string[] })=>{

return(

<div>

{props.tags.map((tag:string,index:number)=>(

<spankey={`tag-${tag}-index`}>{tag}</span>

     ))}

</div>

  );

};

现在让我们创建一个样式化的 div 组件,作为上述 div 元素的替代品。我们创建这个包装器组件来将样式应用于子元素:

constStyledTag=styled.div`

padding: 0.5rem 0;

& span {

margin-right: 0.5rem;

font-size: 1rem;

font-weight: 500;

color: rgba(255, 255, 255, 0.6);

}

`;

最后,我们将这些组件拼接在一起:

constTags=(props: {tags:string[] })=>{

return(

<StyledTag>

{tags.map((tag:string,index:number)=>(

<spankey={`tag-${tag}-index`}>{tag}</span>

     ))}

</StyledTag>

  );

};

同样,我们创建另一个组件,称为Description组件。它有助于显示电影标题的描述。它也是一个功能组件,它接受描述道具并使用样式化组件显示它:

constStyledDescription=styled.div`

text-align: start;

color: rgba(255, 255, 255, 0.8);

display: -webkit-box;

max-width: 50%;

-webkit-line-clamp: 4;

-webkit-box-orient: vertical;

overflow: hidden;

`;

constDescription=(props: {description:string})=>(

<StyledDescription>{description}</StyledDescription>

);

最后,我们将创建Banner组件。该组件的目的是显示电影标题的背景图像以及传递给它的子项。让我们创建这个组件的一个非常基本的版本:

constBanner=(props)=>{

return(

<div

style={{

backgroundImage:`url(${props.image})`,

width:"100%",

height:"400px",

     }}

>

<div>{props.children}</div>

</div>

  );

};

<Bannerimage="https://m.media-amazon.com/images/M/MV5BZjRlNDUxZjAtOGQ4OC00OTNlLTgxNmQtYTBmMDgwZmNmNjkxXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_.jpg">

<h1style={{color:"yellow"}}>Die hard</h1>

</Banner>;

如果我们执行这个组件,它会做我们期望的事情,“显示背景图像和子组件”,如下所示:

但是风格似乎不对——我们不希望这个组件看起来这么难看。我们需要的是应用 CSS 将事物放在正确的位置 🙂(双关语)。

我们希望电影海报在右边,所有子组件都应该在它的左边。现在让我们创建一个样式化的组件来做到这一点:

constStyledContainer=styled.div`

height: 400px;

width: 100%;

display: flex;

background-image: linear-gradient(90deg, rgba(0, 0, 0, 1) 60%, transparent),

url(${(props)=>props.image});

background-size: contain;

background-repeat: no-repeat;

background-position: right;

& > div {

display: flex;

flex-direction: column;

justify-content: center;

align-items: flex-start;

padding-left: 10px;

}

`;

constBanner=(props)=>{

return(

<StyledContainerimage={props.image}>

<div>{props.children}</div>

</StyledContainer>

  );

};

<Bannerimage="https://m.media-amazon.com/images/M/MV5BZjRlNDUxZjAtOGQ4OC00OTNlLTgxNmQtYTBmMDgwZmNmNjkxXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_.jpg">

<h1style={{color:"yellow"}}>Die hard</h1>

</Banner>;

我们创建了一个名为 的新样式组件StyledContainer。它由 CSS 组成,它将图像右对齐并在容器周围应用黑色渐变,以便只有电影标题可见。

接下来,在该& > div部分中,我们确保所有子组件都左对齐。这是它的样子:

耶皮耶!我们的 Banner 组件已准备就绪。现在让我们用上面创建的所有组件测试这个横幅组件。将Title, Tags, 和Description组件放在Banner组件内部,如下所示:

<Bannerimage="https://m.media-amazon.com/images/M/MV5BZjRlNDUxZjAtOGQ4OC00OTNlLTgxNmQtYTBmMDgwZmNmNjkxXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_.jpg">

<Titletitle="Die Hard"/>

<Tagstags={["Action","Thriller"]}/>

<Descriptiondescription="NYPD cop John McClane's plan to reconcile with his estranged wife is thrown for a serious loop when, minutes after he arrives at her office, the entire building is overtaken by a group of terrorists. With little help from the LAPD, wisecracking McClane sets out to single-handedly rescue the hostages and bring the bad guys down."/>

</Banner>;

这就是我们的 Banner 组件的样子。

如何使用复合图案将所有组件缝合在一起

我们希望我们的 Banner 组件易于使用,并且应该灵活。我们可以借助复合模式将 Title、Tags 和 Description 组件拼接到 Banner 组件中。

使用此模式创建的组件在其内部组件之间共享状态和逻辑。这种复合模式的一个例子是语义 UI 提供的菜单组件。

<Menu>

<Menu.Item/>

</Menu>;

使用这种模式的好处是我们只需要导入一个组件——在我们的例子中我们只导入 Banner 组件。它的所有内部组件都可以直接使用,如下所示:

<Banner.Title/>

<Banner.Tags/>

<Banner.Description/>

现在让我们开始为我们的 Banner 组件做同样的事情。

由于我们已准备好所有组件,因此我将它们放在一个文件中:

import"./styles.css";

importstyledfrom"styled-components";

importReactfrom"react";

exporttypeBannerProps={

title:string,

tags:string[],

description:string,

image:string,

};

constStyledTitle=styled.div`

font-size: 28px;

font-weight: 600;

color: white;

`;

constStyledTag=styled.div`

padding: 0.5rem 0;

& span {

margin-right: 0.5rem;

font-size: 1rem;

font-weight: 500;

color: rgba(255, 255, 255, 0.6);

}

`;

constStyledDescription=styled.div`

text-align: start;

color: rgba(255, 255, 255, 0.8);

display: -webkit-box;

max-width: 50%;

-webkit-line-clamp: 4;

-webkit-box-orient: vertical;

overflow: hidden;

`;

constContainer=styled.div`

height: 400px;

width: 100%;

display: flex;

background-image: linear-gradient(90deg, rgba(0, 0, 0, 1) 60%, transparent),

url(${(props:Pick<BannerProps,"image">)=>props.image});

background-size: contain;

background-repeat: no-repeat;

background-position: right;

& > div {

display: flex;

flex-direction: column;

justify-content: center;

align-items: flex-start;

padding-left: 10px;

}

`;

constTitle=({title}:Pick<BannerProps,"title">)=>(

<StyledTitle>{title}</StyledTitle>

);

constTags=({tags}:Pick<BannerProps,"tags">)=>{

return(

<StyledTag>

{tags.map((tag)=>(

<spankey={`tag-${tag}`}>{tag}</span>

     ))}

</StyledTag>

  );

};

constDescription=({description}:Pick<BannerProps,"description">)=>(

<StyledDescription>{description}</StyledDescription>

);

constBanner=(props:any)=>{

return(

<Containerimage={props.image}>

<div>{props.children}</div>

</Container>

  );

};

Banner.Title=Title;

Banner.Tags=Tags;

Banner.Description=Description;

exportdefaultBanner;

上面代码的快速解释:

首先,我们为名为 BannerProps 的横幅组件创建类型。它看起来像这样:

exporttypeBannerProps={

title:string;

tags:string[];

description:string;

image:string;

};

接下来,我们将创建的所有原子组件放在这里。我们还确保在原子组件的每个函数定义中使用 BannerProps 类型,例如:

constTitle=({title}:Pick<BannerProps,"title">)=>(

<StyledTitle>{title}</StyledTitle>

);

如您所见,我们使用 TypeScript 的 Pick 实用程序函数仅从 Banner 道具中选取标题道具。

最后,我们通过为 Banner 组件创建一个新属性来拼接所有这些组件,如下所示,并导出该组件:

Banner.Title=Title;

Banner.Tags=Tags;

Banner.Description=Description;

exportdefaultBanner;

注意:出于本教程的目的,我们使用复合模式,但您可以独立使用这些原子组件。我这里选择使用复合模式来教大家使用。您可以将它应用于不同的场景,例如构建选择按钮或菜单组件时。

干得好——我们终于将所有的原子组件拼接成一个单一的 Banner 组件。在下一节中,我们将讨论如何使用该组件。

如何构建图像轮播组件

最后,我们到了可以构建图像轮播组件的地步。在本节中,我们将执行以下操作:

构建一个 Banner Tile 组件,它将在轮播中充当单个图像

构建图像轮播组件。

让我们先创建 Banner Tile 组件。该组件的目的是使用该Banner组件。

首先,我们将从创建可以迭代的示例数据开始。创建一个名为的文件sampledata.json并将以下内容放入其中:

{

"data": [

   {

"title":"The Last of Us",

"genres": ["Drama"],

"cover_url":"/t/p/w600_and_h900_bestv2/uKvVjHNqB5VmOrdxqAt2F7J78ED.jpg",

"description":"Twenty years after modern civilization has been destroyed, Joel, a hardened survivor, is hired to smuggle Ellie, a 14-year-old girl, out of an oppressive quarantine zone. What starts as a small job soon becomes a brutal, heartbreaking journey, as they both must traverse the United States and depend on each other for survival."

   },

   {

"title":"Fight Club",

"genres": ["Drama","Thriller","Comedy"],

"cover_url":"/t/p/w300_and_h450_bestv2/pB8BM7pdSp6B6Ih7QZ4DrQ3PmJK.jpg",

"description":"A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground fight clubs forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion."

   },

   {

"title":"Creed III",

"genres": ["Drama","Thriller"],

"cover_url":"/t/p/w600_and_h900_bestv2/cvsXj3I9Q2iyyIo95AecSd1tad7.jpg",

"description":"After dominating the boxing world, Adonis Creed has been thriving in both his career and family life. When a childhood friend and former boxing prodigy, Damien Anderson, resurfaces after serving a long sentence in prison, he is eager to prove that he deserves his shot in the ring. The face-off between former friends is more than just a fight. To settle the score, Adonis must put his future on the line to battle Damien - a fighter who has nothing to lose."

   },

   {

"title":"Die Hard",

"genres": ["Action","Thriller"],

"cover_url":"/t/p/w1280/yFihWxQcmqcaBR31QM6Y8gT6aYV.jpg",

"description":"NYPD cop John McClane's plan to reconcile with his estranged wife is thrown for a serious loop when, minutes after he arrives at her office, the entire building is overtaken by a group of terrorists. With little help from the LAPD, wisecracking McClane sets out to single-handedly rescue the hostages and bring the bad guys down."

   }

  ]

}

BannerTile.tsx接下来,在目录中创建一个名为的文件components。然后创建一个使用 Banner 组件的功能组件,如下所示:

importBanner, {BannerProps}from"./Banner";

exportdefaultfunctionBannerTile(props:BannerProps) {

const{title,image,tags,description}=props;

return(

<Bannerimage={image}>

<Banner.Titletitle={title}/>

<Banner.Tagstags={tags}/>

<Banner.Descriptiondescription={description}/>

</Banner>

  );

}

现在要测试这个组件,我们可以使用sampledata.json. 通过以下步骤来测试BannerTile组件:

首先,我们应该从 sampledata.json 导入数据:

constsampleData=require('./sampledata.json');

接下来,我们使用 map 函数迭代此数据。我们还确保我们BannerTile在每个数据上调用组件:

<div>

{sampleData.data.map((item:SampleData,index:number)=>(

<BannerTile

key={`key-${item.title}-${index}`}

title={item.title}

tags={item.genres}

image={item.cover_url}

description={item.description}

/>

  ))}

</div>;

运行此代码后的输出将如下所示:

要实现图像轮播,我们可以使用一个名为Swiper的包。我们只需要将所有内容放在BannerTiles滑动器提供的组件中。现在,事不宜迟,让我们开始吧。

要安装 swiper 包,请使用以下命令:

npmi swiper

现在让我们创建一个名为HeroBanner.tsx. 该文件将包含HeroBanner组件。该组件的目的是迭代电影数据并通过图像轮播和BannerTile组件显示它们。

一旦我们安装了 swiper 库,我们就可以开始使用它了。根据 swiper.js 文档,我们需要导入它提供的 CSS:

import"swiper/css";

import"swiper/css/navigation";

接下来,我们还需要从 swiper.js 中导入组件,这将帮助我们构建图像轮播。导入以下组件:

import{Swiper,SwiperSlide}from"swiper/react";

import{Navigation}from"swiper";

现在让我们也导入BannerTile,与横幅关联的类型,以及sampleData来自sampledata.json:

import"swiper/css";

import"swiper/css/navigation";

import{Swiper,SwiperSlide}from"swiper/react";

import{Navigation}from"swiper";

importBannerTilefrom"./BannerTile";

import{BannerProps}from"./Banner";

constsampleData=require("../utilities/sampledata.json");

我们sampleData刚才导入的只包含标题、流派、cover_url 和描述。这是利用类型BannerProps来过滤掉我们需要的类型的最佳时机。

typeSampleData=Pick<BannerProps,'title'|'description'>&{

    genres:string[];

cover_url:string;

}

现在让我们开始实际构建这个组件。创建一个名为的功能组件HeroBanner并将以下代码放入其中:

constHeroBanner=()=>(

<Swipernavigationmodules={[Navigation]}slidesPerView={1}>

{sampleData.data.map((item:SampleData,index:number)=>(

<SwiperSlidekey={`key-${item.title}-${index}`}>

<BannerTile

title={item.title}

tags={item.genres}

image={item.cover_url}

description={item.description}

/>

</SwiperSlide>

   ))}

</Swiper>

);

在 HeroBanner 组件中,我们做了以下事情:

我们使用Swiperswiper.js 库提供的组件作为所有图像的包装容器,即组件BannerTile。我们确保每个视图只有一张幻灯片。

在映射时,sampleData我们确保每个BannerTile组件都被组件包裹SwiperSlide。

要了解有关 swiper 的 React 组件的更多信息,您可以参考它们的文档。

最终输出将如下所示:

我们终于得到了我们想要的东西:一个外观和功能与流行的 OTT 平台上的相似的图像轮播组件。

但是这里还有最后一件事我们需要做。我们需要确保左箭头和右箭头是白色的,这样它们才能突出。为此,我们使用样式组件:

exportconstStyledSwiper=styled(Swiper)`

& .swiper-button-next,

.swiper-button-prev {

color: white;

}

`;

现在我们编辑我们的 HeroBanner 组件。我们用 StyledSwiper 组件替换 Swiper 组件,如下所示:

constHeroBanner=()=>(

<StyledSwipernavigationmodules={[Navigation]}slidesPerView={1}>

{sampleData.data.map((item:SampleData,index:number)=>(

<SwiperSlidekey={`key-${item.title}-${index}`}>

<BannerTile

title={item.title}

tags={item.genres}

image={item.cover_url}

description={item.description}

/>

</SwiperSlide>

   ))}

</StyledSwiper>

);

这是它的外观:

现在看起来不错

概括

这就是您可以为电影标题创建图像轮播的方法。在本教程中,您学习了:

如何创建原子组件

如何通过复合模式将所有组件拼接在一起

如何创建显示与每部电影相关的信息的 BannerTile 组件

如何使用 swiper.js 构建图像轮播组件

(更多优质教程:java567.com,搜"ts")

相关文章

网友评论

      本文标题:如何使用TypeScript和Styled-Components

      本文链接:https://www.haomeiwen.com/subject/umbiedtx.html