Material-UI学习 第二章 构建第一个页面

2 篇文章 0 订阅
2 篇文章 0 订阅

第二章 构建第一个页面

项目结构

经过上一章学习,我们的项目结构应该是

# 在 src 文件夹下面
│ App.tsx
│ index.tsx

ok,我们应当如何学习管理我们的项目结构呢?

  • github上找一个已有项目,学习它的结构。

下面是一个开源项目,react-pxq我们用它来学习一下目录结构。

# git@github.com:bailicangdu/react-pxq.git
├── api
│   ├── api.js
│   └── server.js
├── assets
│   └── iconfonts
│       ├── iconfont.css
│       ├── iconfont.eot
│       ├── iconfont.svg
│       ├── iconfont.ttf
│       └── iconfont.woff
├── components
│   ├── alert
│   │   ├── alert.jsx
│   │   └── alert.less
│   ├── header
│   │   ├── header.jsx
│   │   └── header.less
│   └── TouchableOpacity
│       ├── TouchableOpacity.jsx
│       └── TouchableOpacity.less
├── envconfig
│   └── envconfig.js
├── index.js
├── pages
│   ├── balance
│   │   ├── balance.jsx
│   │   └── balance.less
│   ├── helpcenter
│   │   ├── helpcenter.jsx
│   │   └── helpcenter.less
│   ├── home
│   │   ├── home.jsx
│   │   └── home.less
│   ├── production
│   │   ├── production.jsx
│   │   └── production.less
│   └── record
│       ├── components
│       │   ├── recordList.jsx
│       │   └── recordList.less
│       ├── record.jsx
│       └── record.less
├── registerServiceWorker.js
├── router
│   └── index.js
├── store
│   ├── home
│   │   ├── action.js
│   │   ├── action-type.js
│   │   └── reducer.js
│   ├── production
│   │   ├── action.js
│   │   ├── action-type.js
│   │   └── reducer.js
│   └── store.js
├── style
│   ├── base.css
│   └── mixin.less
└── utils
    ├── asyncComponent.jsx
    ├── mixin.js
    └── setRem.js

​ 有可取之处,但也有一些我们用不到的东西,就比如*.less文件,Material提倡JSS写法,这会在以后讲到,在这之前,我们先来规定一下我们的目录结构。

# in src
mkdir components
cd components
mkdir layout

现在,你的目录应该是这样的结构。

│ App.tsx
│ index.tsx
└─components
  └─layout

ok,继续,我们在layout创建两个文件:Footer.tsxHeader.tsx

//Footer.tsx
import React from 'react'
const Footer: React.FunctionComponent = () => {
    return <div>
    </div>
}
export default Footer;

//Header.tsx
import React from 'react'
const Header:React.FunctionComponent = ()=>{
    return <div>
        
    </div>
}
export default Header;

​ 为了能直观看到修改,我们先把这两个组件导出到App.tsx中去。但是,如果我们不做任何修改,在App.tsx中,我们会使用两条import语句。

​ 这在现在看起来不是问题,但是,随着我们layout,含有越来越多的组件,那我们的引入语句将会越来越多,所以我们在layout文件夹中创建index.tsx这样,我们就可以通过它,引用 layout文件夹中所有组件。

//src/components/layout/index.tsx
import Header from './Header'
import Footer from './Footer'
export {
    Header,
    Footer
}

然后修改我们的App.tsx文件,引入我们的Header.tsxFooter.tsx组件。

//App.tsx
import React from 'react'
import {Header,Footer} from './components/layout'
const App:React.FunctionComponent = ()=>{
   return <>
    <Header></Header>
    <Footer></Footer>
   </> 
}
export default App;

使用AppBar(应用栏)组件

应用栏用来显示与当前屏幕相关的信息和操作。

在这里插入图片描述

cool!,看到漂亮的组件总是让人心潮澎湃对吧?

让我们开始在自己的页面上使用AppBar组件!

//Header.tsx
import React from 'react'
import { AppBar, Toolbar, IconButton, Typography, Button } from '@material-ui/core'
import { Menu as MenuIcon } from '@material-ui/icons'
const Header: React.FunctionComponent = () => {
    return <div>
        <AppBar position="static">
            <Toolbar>
                <IconButton edge="start" color="inherit" aria-label="menu">
                    <MenuIcon />
                </IconButton>
                <Typography variant="h5">
                    New Page !
          		</Typography>
            </Toolbar>
        </AppBar>
    </div>
}
export default Header;

有关App Bar的相关说明你可以在这找到。

​ 我们暂时不写任何css相关,为了更好的学习Material的思想,我们先把大致组件学习一遍。

​ 我在文件中使用了React.FunctionComponent组件,也是React所推崇的函数组件。

​ class组件带来了一些开发上的难题,比如生命周期的强耦合,我们无法理清思路、细分组件,所以新版本的React建议我们使用函数组件,并且提供了Hook API来解决函数组件无法保存state的问题。

Header.tsx我们见到一些新元素比如AppBar, Toolbar, IconButton, Button,想要一开始就完全弄清楚每个组件在什么时候用,使用什么参数,并不是好的学习习惯,我们因该先像喝水、睡觉去习惯它们,而不是去搞清楚水的成分、睡眠的作用。

使用 Tabs(选项卡)组件

​ 下面,我们同样修改Footer.tsx文件。

import React,{useState} from 'react'
import { Paper, Tab, Tabs } from '@material-ui/core'
const Footer: React.FunctionComponent = () => {
    const [value,setValue]= useState(0)
    /**
     * tab选项卡切换时,触发事件
     * @param event 事件对象
     * @param val value值 选择的下标
     */
    function handChage(event:React.ChangeEvent<{}>,val:any){
        setValue(val)
    }
    return <div>
        <Paper>
            <Tabs value={value} onChange={handChage} aria-label="simple tabs example">
                <Tab label="Item One" />
                <Tab label="Item Two" />
                <Tab label="Item Three" />
            </Tabs>
        </Paper>
    </div>
}
export default Footer;

​ 这里就要解释一些东西了,Tabs组件,通过value参数决定,哪一个Tab选项被选择。

​ 很明显,我们需要class组件的state成员变量了,但是我们应该追随官方,我们使用Hook API。

​ 对Hook API 不清楚的同学,点击这里学习详细的知识。我在这只简单讲解一下。

useState(init_value)//返回[value,setValue],我们可以使用es6的数组结构方法,接受返回值。
//它相当我们
//state:{value:init_value}
//setValue(10)相当于setState({value:10})

通过使用Hook API在函数组件也能达到存放state。

使用Container、Grid、Box组件

​ 现在,我们的layout算是暂时搭建好了,现在我们开始构建内容。含有内容的页面已经算是一个page了,所以我们再创建一个page文件夹,存放我们所有页面。

src
└─pages
    └─index
       	index.tsx

​ 如果你在项目中使用了React-router等路由插件,就可以将这些页面放入路由,再将路由放入App.tsx文件的中间。

​ 现在使用这些组件,我们搭建一个类似于每日一文的网站出来,这是一个浏览型的网站,用来当练手的小项目最好不过。

Container(容器)组件

容器组件会让您页面的内容水平居中。 这是最基本的布局元素。

NameTypeDefaultDescription
children *node
classesobject覆盖或扩展应用于组件的样式。
componentelementType‘div’用于根节点的组件。要么是使用DOM元素的字符串,要么是组件。
fixedboolfalse设置max-width以匹配当前断点的最小宽度。如果您希望设计一组固定大小而不是尝试容纳完全流体视口,这将非常有用。它默认是流动的。
maxWidth‘xs’ | ‘sm’ | ‘md’ | ‘lg’ | ‘xl’ | false‘lg’确定容器的最大宽度。容器宽度随着屏幕的大小而增长。设置false为禁用maxWidth

引入

import Container from '@material-ui/core/Container';
// or
import { Container } from '@material-ui/core';

​ 一般来说,我们都是从@material-ui/core库中引入组件,从@material-ui/icons引入图标。只要大家记好,不使用文档也能开发页面。

​ 显然,我们使用Container作为主体显示最合适不过,因为它自动居中,且自适应,当然我们也可以自己写组件实现这些功能,不过使用Material-UI就是要追求快,写轮子当然是好事,但不能在学习使用轮子的时候,去造轮子,这样只会导致自己学习速度过慢。

​ 在index.tsx中放入下面代码。

import React from 'react'
import { Paper, Typography, Container, Grid, Box } from '@material-ui/core'
const Index: React.FunctionComponent = () => {
    return <>
        <Paper>
            <Container maxWidth="lg">
                <Box border={1} p={3} m={4} borderColor="grey.500">
                    <Grid>
                        <Typography variant="h3" align="center" component="p"></Typography>
                    </Grid>
                    <br />
                </Box>
            </Container>
        </Paper>
    </>
}
export default Index;

​ 相信聪明的大伙都能看懂,我们在Paper组件中放入了Container组件,并使最大宽度不超出lg(1280px)

​ ok,接下来介绍Grid组件

Grid(栅格)组件

Material Design 响应式布局的栅格可适应屏幕大小和方向,确保布局之间的一致性。

栅格(Grid)组件能确保不同布局间的视觉一致性,同时在众多不同设计中保持灵活性。 Material Design 的响应式 UI 是基于12列的栅格布局。

ok,明白了,12列又是你。接着看

​ 响应式栅格侧重于一致的间距宽度,而不是列宽。 Material design 外边距和列遵循8px的方块形基线栅格。 spacing 属性设置为一个在0和10之间的整数,且并包括0和10。 默认情况下,两个网格项之间的间距遵循这样的线性函数: output(spacing) = spacing * 8px,例如 spacing={2} 会创建一个 16px 的宽间距。

​ [外链图片转存失败(img-HLJz50mz-1568532470145)(C:\Users\Wilin\Desktop\yhy\assets\QQ图片20190915110606.png)]

Box(分组)组件

Box 组件充当大多数 CSS 实用程序所需求的包装器组件。

​ 说明上来看,Box并没有给我们提供过多的样式,更多的是让我们使用它的语义化,告诉其他开发者,这是我们自定义的div,用来包装其他组件。

这几个组件差不多了解,我们开始写代码。

Index 页面

​ 首先,我们需要大量的文字,用来填充主页使其达到每日一文网站的效果。想象一下我们有很多段落,但是都要通过同种方式渲染,所以我们可以封装一下,这段的逻辑。

​ 第二,我们用js数组来存放我们所有的文字。效果应该是这样的

在这里插入图片描述

我们如果要使用,直接通过import TextJson from './text.json.js'

​ 然后,我们来编写渲染的组件。

interface ITextPorps {
    text: string
}
const TextLine: React.FunctionComponent<ITextPorps> = (porps) => {
    const { text } = porps
    return <>
        <Grid>
            <Typography variant="h5" gutterBottom component="p">
                {text}
            </Typography>
        </Grid>
        <br />
    </>
}

我们的TextLine组件,接收text属性,并将其渲染。

​ 最后,我们的文件应该是这样子的。

import React from 'react'
import { Paper, Typography, Container, Grid, Box } from '@material-ui/core'
import TextJson from './index.json'
interface ITextPorps {
    text: string
}
const TextLine: React.FunctionComponent<ITextPorps> = (porps) => {
    const { text } = porps
    return <>
        <Grid>
            <Typography variant="h5" gutterBottom component="p">
                {text}
            </Typography>
        </Grid>
        <br />
    </>
}
const Index: React.FunctionComponent = () => {
    return <>
        <Paper>
            <Container maxWidth="lg">
                <Box border={1} p={3} m={4} borderColor="grey.500">
                    <Grid>
                        <Typography variant="h3" align="center" component="p"></Typography>
                    </Grid>
                    <br />
                    {TextJson.map((item, key) => {
                        return <TextLine text={item.text} key={key} />
                    })}
                </Box>
            </Container>
        </Paper>
    </>
}
export default Index;

​ 最最后,我们需要把页面放到App.tsx文件中,这样才能看到我们的效果。

//App.tsx
import React from 'react'
import {Header,Footer} from './components/layout'
import Index from './pages/index'
const App:React.FunctionComponent = ()=>{
   return <>
    <Header></Header>
    <Index></Index>
    <Footer></Footer>
   </> 
}
export default App;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值