【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(七)

这篇具有很好参考价值的文章主要介绍了【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(七)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


学习内容来源:React + React Hook + TS 最佳实践-慕课网


相对原教程,我在学习开始时(2023.03)采用的是当前最新版本:

版本
react & react-dom ^18.2.0
react-router & react-router-dom ^6.11.2
antd ^4.24.8
@commitlint/cli & @commitlint/config-conventional ^17.4.4
eslint-config-prettier ^8.6.0
husky ^8.0.3
lint-staged ^13.1.2
prettier 2.8.4
json-server 0.17.2
craco-less ^2.0.0
@craco/craco ^7.1.0
qs ^6.11.0
dayjs ^1.11.7
react-helmet ^6.1.0
@types/react-helmet ^6.1.6
react-query ^6.1.0
@welldone-software/why-did-you-render ^7.0.1
@emotion/react & @emotion/styled ^11.10.6

具体配置、操作和内容会有差异,“坑”也会有所不同。。。


一、项目起航:项目初始化与配置

  • 【实战】 一、项目起航:项目初始化与配置 —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(一)

二、React 与 Hook 应用:实现项目列表

  • 【实战】 二、React 与 Hook 应用:实现项目列表 —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二)

三、TS 应用:JS神助攻 - 强类型

  • 【实战】三、 TS 应用:JS神助攻 - 强类型 —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(三)

四、JWT、用户认证与异步请求

  • 【实战】四、 JWT、用户认证与异步请求(上) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(四)

  • 【实战】四、 JWT、用户认证与异步请求(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(五)

五、CSS 其实很简单 - 用 CSS-in-JS 添加样式

1~3

  • 【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(上) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(六)

4.用Grid和Flexbox布局优化项目列表页面

编辑 src\authenticated-app.tsx

import styled from "@emotion/styled";
import { useAuth } from "context/auth-context";
import { ProjectList } from "screens/ProjectList";

/**
 * grid 和 flex 各自的应用场景
 * 1. 要考虑,是一维布局 还是 二维布局
 * 一般来说,一维布局用flex,二维布局用grid
 * 2. 是从内容出发还是从布局出发?
 * 从内容出发:你先有一组内容(数量一般不固定),然后希望他们均匀的分布在容器中,由内容自己的大小决定占据的空间
 * 从布局出发:先规划网格(数量一般比较固定),然后再把元素往里填充
 * 从内容出发,用flex
 * 从布局出发,用grid
 */

export const AuthenticatedApp = () => {
  const { logout } = useAuth();
  return (
    <Container>
      <Header>
        <HeaderLeft>
          <h3>Logo</h3>
          <h3>项目</h3>
          <h3>用户</h3>
        </HeaderLeft>
        <HeaderRight>
          <button onClick={logout}>登出</button>
        </HeaderRight>
      </Header>
      <Nav>Nav</Nav>
      <Main>
        <ProjectList />
      </Main>
      <Aside>Aside</Aside>
      <Footer>Footer</Footer>
    </Container>
  );
};
const Container = styled.div`
  display: grid;
  grid-template-rows: 6rem 1fr 6rem; // 3行每行高度(fr 单位是一个自适应单位,表示剩余空间中所占比例)
  grid-template-columns: 20rem 1fr 20rem;
  grid-template-areas:
    "header header header"
    "nav main aside"
    "footer footer footer";
  /* grid-gap: 10rem; // 每部分之间的间隔 */
  height: 100vh;
`;

// grid-area 用来给 grid 子元素起名字
const Header = styled.header`
  grid-area: header;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
`;
const HeaderLeft = styled.div`
  display: flex;
  align-items: center;
`;
const HeaderRight = styled.div``;
const Main = styled.main`
  grid-area: main;
  /* height: calc(100vh - 6rem); */
`;
const Nav = styled.nav`
  grid-area: nav;
`;
const Aside = styled.aside`
  grid-area: aside;
`;
const Footer = styled.footer`
  grid-area: footer;
`;

grid 和 flex 各自的应用场景

1.要考虑,是一维布局 还是 二维布局

  • 一般来说,一维布局用flex,二维布局用grid

2.是从内容出发还是从布局出发?

  • 从内容出发:你先有一组内容(数量一般不固定),然后希望他们均匀的分布在容器中,由内容自己的大小决定占据的空间
  • 从布局出发:先规划网格(数量一般比较固定),然后再把元素往里填充
  • 从内容出发,用flex
  • 从布局出发,用grid

【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(七),javascript,css,react.js

  • CSS Grid: Holy Grail Layout | DigitalOcean

5.使用 emotion 自定义样式组件

区别于 react 的功能组件 emotion 组件我们称其为 样式组件

新建 src\components\lib.tsx(emotion 自定义样式组件库):

import styled from '@emotion/styled'

export const Row = styled.div<{
  gap?: number | boolean,
  butween?: boolean,
  marginBottom?: number
}>`
  display: flex;
  align-items: center;
  justify-content: ${props => props.butween ? 'space-between' : undefined };
  margin-bottom: ${ props => props.marginBottom + 'rem' };
  > * {
    /* 直接子元素强制控制样式 */
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    margin-right: ${ props => typeof props.gap === 'number' ? props.gap + 'rem' : props.gap ? '2rem' : undefined };
  }
`

上一节代码是为了学习 grid,为实现后续效果,清除无用代码并使用自定义样式组件(src\authenticated-app.tsx):

import styled from "@emotion/styled";
import { Row } from "components/lib";
import { useAuth } from "context/auth-context";
import { ProjectList } from "screens/ProjectList";

export const AuthenticatedApp = () => {
  const { logout } = useAuth();
  return (
    <Container>
      <Header butween={ true }>
        <HeaderLeft gap={ true }>
          <h2>Logo</h2>
          <h2>项目</h2>
          <h2>用户</h2>
        </HeaderLeft>
        <HeaderRight>
          <button onClick={logout}>登出</button>
        </HeaderRight>
      </Header>
      <Main>
        <ProjectList />
      </Main>
    </Container>
  );
};
const Container = styled.div`
  display: grid;
  grid-template-rows: 6rem 1fr;
  height: 100vh;
`;

// grid-area 用来给 grid 子元素起名字
const Header = styled(Row)``;
const HeaderLeft = styled(Row)``;
const HeaderRight = styled.div``;
const Main = styled.main``;

6.完善项目列表页面样式

编辑 src\screens\ProjectList\components\SearchPanel.tsx(使用Form.Itememotioncss 属性):

// /** @jsx jsx */
// import { jsx } from '@emotion/react'
/** @jsxImportSource @emotion/react */
...
export const SearchPanel = ({ users, param, setParam }: SearchPanelProps) => {
  return (
    <Form css={{ marginBottom: '2rem', '>*': '' }} layout="inline">
      <Form.Item>
        <Input placeholder='项目名' ... />
      </Form.Item>
      <Form.Item>
        <Select>...</Select>
      </Form.Item>
    </Form>
  );
};

在使用 emotioncss 属性时 需要注意,由于 React 17 的自动导入破坏了 @emotion 自身运行时的支持,从而将导致 emotionjsx 运行时导入后未使用,也就无法使用 emotioncss 属性将 /** @jsx jsx */ 改为 /** @jsxImportSource @emotion/react */ 即可
截止2023.05.04,官方文档中依旧是 /** @jsx jsx */ 的导入方式:Emotion – The css Prop

编辑 src\screens\ProjectList\index.tsx(调整与外部间距):

...

export const ProjectList = () => {
  ...
  
  return (
    <Container>
      <h1>项目列表</h1>
      <SearchPanel users={users} param={param} setParam={setParam} />
      <List users={users} list={list} />
    </Container>
  );
};

const Container = styled.div`
  padding: 3.2rem
`

安装 dayjs 库:

npm i dayjs --force

截止 2020.9 moment 库已停止开发

编辑 src\screens\ProjectList\components\List.tsx(表中新增部门和创建时间字段):

...
import dayjs from 'dayjs'

interface Project {
  ...
  created: number;
}
...

export const List = ({ users, list }: ListProps) => {
  return (
    <Table
      pagination={false}
      columns={[
        {
          title: "名称",
          ...
        },
        {
          title: "部门",
          dataIndex: "organization"
        },
        {
          title: "负责人",
          ...
        },
        {
          title: "创建时间",
          render: (text, project) => (
            <span>
              {project.created ? dayjs(project.created).format('YYYY-MM-DD') : '无'}
            </span>
          ),
        },
      ]}
      dataSource={list}
    ></Table>
  );
};

将预置 svg 文件(software-logo.svg) 放入src\assets

【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(七),javascript,css,react.js

使用方式推荐 ReactComponent as SVG

编辑 src\authenticated-app.tsx(添加 Logo、优化登出、header 添加底部阴影)(部分未修改内容省略):

...
import { ReactComponent as SoftwareLogo } from 'assets/software-logo.svg'
import { Button, Dropdown } from "antd";
import type { MenuProps } from 'antd';

export const AuthenticatedApp = () => {
  const { logout, user } = useAuth();
  const items: MenuProps['items'] = [{
    key: 1,
    label: '登出',
    onClick: logout
  }]
  return (
    <Container>
      <Header between={true}>
        <HeaderLeft gap={true}>
          <SoftwareLogo width='18rem' color='rgb(38,132,255)'/>
          <h2>项目</h2>
          <h2>用户</h2>
        </HeaderLeft>
        <HeaderRight>
          <Dropdown menu={{ items }}>
            <Button type='link' onClick={e => e.preventDefault()}>
              Hi, { user?.name }
            </Button>
          </Dropdown>
        </HeaderRight>
      </Header>
      <Main>... </Main>
    </Container>
  );
};
const Container = styled.div`...`;

// grid-area 用来给 grid 子元素起名字
const Header = styled(Row)`
  padding: 3.2rem;
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1);
  z-index: 1;
`;
...

Dropdownoverlay 属性已被 menu 属性取代,注意 MenuProps 的引入

本次美化成果:
【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(七),javascript,css,react.js

7.遗留问题处理

src\utils\index.ts

解开 @ts-ignore "封印"的报错

...
export const isVoid = (val: unknown) => val === undefined || val === null || val === ''

export const cleanObject = (obj: { [key: string]: unknown }) => {
  const res = { ...obj };
  Object.keys(res).forEach((key) => {
    const val = res[key];
    if (isVoid(val)) {
      delete res[key];
    }
  });
  return res;
};  

export const useMount = (cbk: () => void) =>
  useEffect(() => {
    // TODO 依赖项里加上callback 会造成无限循环,这个和 useCallback 以及 useMemo 相关
    cbk();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
...
  • object 类型涵盖很广(functionnew RegExp('')…),若只是想用键值对的形式可以使用上面所示的形式 { [key: string]: unknown }
  • val = res[key] 的值是 false 或是 false 的字面量,isFalsy 也会识别,然后就会有 bug,比如 checkedvisible

安装另一个版本的 jira-dev-toolapi 有更改):

npm i jira-dev-tool # --force (可能需要强制安装)

若有报错,可以将 node_modules 清空再装或是按照报错提示操作

修改项目入口文件 src\index.tsx(部分未修改内容省略):

...
import { loadServer, DevTools } from "jira-dev-tool";
...

loadServer(() => {
  root.render(
    // <React.StrictMode>
    <AppProvider>
      <DevTools/>
      <App />
    </AppProvider>
    // </React.StrictMode>
  );
});
...

修改 src\context\index.tsx(部分未修改内容省略):

...
import { QueryClient, QueryClientProvider } from 'react-query'

export const AppProvider = ({ children }: { children: ReactNode }) => {
  return <QueryClientProvider client={new QueryClient()}>
    <AuthProvider>{children}</AuthProvider>
  </QueryClientProvider>;
};



部分引用笔记还在草稿阶段,敬请期待。。。文章来源地址https://www.toymoban.com/news/detail-522971.html

到了这里,关于【实战】 五、CSS 其实很简单 - 用 CSS-in-JS 添加样式(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(七)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在JavaScript中添加css样式 js追加类

    一、原生js中添加类的方法 二、jquery中添加类的方法 三、检查是否含有某个类的方法 四、在JavaScript中添加CSS样式: 五、使用HTML DOM的setAttribute()方法更改CSS属性: 六、使用JavaScript可以通过动态创建样式表 style标签 来添加CSS样式。 例如,以下代码创建一个新的style标签,并

    2024年02月03日
    浏览(40)
  • CSS设置鼠标样式和添加视频样式

    CSS用户界面样式 轮廓线outline 使图片和文字对齐 vertical-align: baseline | top | middle | bottom baseline 默认元素设置在父元素的基线上 top把元素的顶端与行中最高元素的顶端对齐 middle把元素放置父元素的中部 bottom把元素的顶端与行中最低的元素的顶端对齐 这个用法限于行内和行内块

    2024年02月07日
    浏览(26)
  • 第一个react应用程序并添加样式

    将目录下的文件、src文件夹、public文件夹清空,项目根目录下新建一个文件index.js 在文件中写入以下代码 react开发需要引入多个依赖文件:React和ReactDOM. ReactDOM.render是 React 的最基本方法用于将模板转为 HTML 语言,并插入指定的 DOM 节点。 该方法接收两个参数: 创建的模板,

    2024年02月11日
    浏览(32)
  • 步入React前厅 - Css In React

    目录 扩展学习资料 行内样式 引入样式表 CSS Module @/src/components/common.module.css @/src/components/listitem.module.css css管理进阶 Css管理工具 练习 资料名称 链接 css module CSS Modules 用法教程 - 阮一峰的网络日志       在React中使用css预编译 https://juejin.im/post/5c3d67066fb9a049f06a8323      sty

    2024年02月13日
    浏览(59)
  • CSS给元素添加边框(样式、颜色、宽度)

    CSS边框属性允许你指定一个元素边框的样式和颜色, 和边框宽度。 可以使用 border 属性将边框样式,颜色,和宽度 一起设置。 如果不设置其中的某个值,也不会出问题,比如 border: solid #ff0000; 也是允许的。 边框样式属性指定要显示什么样的边界。除了在 border 属性里面设置边框

    2024年01月21日
    浏览(32)
  • 在油猴脚本中添加css样式的方法

    由于项目要求,需要在系统页面注入dom元素,且对这些注入的元素在UI界面层有美观度要求,就避免不了要对其CSS样式优化。 通常在油猴脚本中添加CSS样式的方法如下: 一、引入外部css文件 二、使用油猴自带样式添加请求 三、自定义样式函数 四、js添加样式 或 以上是在油

    2024年01月23日
    浏览(24)
  • 通过使用html的css样式来达到给背景色添加渐变色的效果

    这里我直接添加了两个div,并且给两个div添加了基本的css样式,有问题请私信          在演示开始之前我们先来认识一下实现渐变效果的一个属性  background: linear-gradient 这个是我们设置背景渐变色的关键属性,然后我们开始演示(这里我们通过修改第二个div)          

    2024年02月08日
    浏览(37)
  • 微信小程序通过js动态修改css样式的方法,以及css变量

    不知道各位小帅有没有遇到这种问题,在微信小程序开发的时候,我们想要将某个文字大小变大,那么本篇文章就是解决这个问题。

    2024年02月06日
    浏览(38)
  • 【React】如何简单快速地修改antd组件UI内部样式如字体颜色

    最近刚开始学习react 在写一个登录的页面 发现组件的颜色不太合适,默认是黑色字体 那我想修改成白色字体以适应我的页面 运用多种css文件打包策略太过复杂 对我这种小白不友好 两行代码搞定 实现需求 通过:global加上!important 在Umi项目中,在global.less文件夹下面,通过roo

    2024年02月13日
    浏览(34)
  • Vue3通过JS修改Css样式(附节点获取相关知识)

    方法一:通过获取节点style(获取标签节点) 方法二:通过动态设置class 方法三:直接动态设置style  附节点获取相关知识

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包