2. 底部导航栏的制作 - LoveVin/billkeeping-react GitHub Wiki
去 react-router官网 查看对应的安装方法。
yarn add react-router-dom
yarn add --dev @types/react-router-dom
- 从官网的基本例子中 CRM 修改
- 设置默认路径:
<Redirect exact from="/" to="money" />
- 设置404路径:
<Route path="*"> <NoMatch /> </Route>
Router 有三种模式,常用的有两种,一个是 History模式,一个是 Hash模式
- 没有后台服务器,用 Hash模式
- 有后台服务器,配置所有路劲都到首页,使用 History模式
在本项目使用的是 Hash 模式:
import 中的 BrowserRouter as Router, 改为 HashRouter as Router,
看到 url 前都带有了 #
就是设置 hash模式成功
Nav导航栏 可以抽离成一个单独的 .tsx 组件。该组件中使用 styled-components 来自定义样式:
const NavWrapper = styled.div`
line-height: 24px;
box-shadow: 0 0 3px rgba(0,0,0,0.25);
>ul{
display:flex;
>li{
width: 33.333%;
text-align: center;
padding: 16px;
}
}
`;
svg 图片是项目开发过程中使用最佳的图标格式,本项目在 iconfont 中选择的图标。选择好svg图片后,有两种引入方式:
- 直接使用 img标签
import x from 'icons/money.svg';
console.log(x); //输出是 webpack 计算出来的图片路径
<img src={x} alt=""/>
缺点:无法直接修改图标颜色,需要在 svg 的源文件里修改或添加 fill="red" 属性。
- 使用 svg symbol 的方式
这种方式需要安装一个 loader,叫做 svg-sprite-loader。
但是在项目环境中要额外加载 loader 需要在原始的 webpack 中加载,但是 cra(create-react-app) 将其 webpack 配置信息封装了,因此为了添加 svg-sprite-loader,我们需要调出原始的 webpack 配置,使用 eject,使用 eject 前先提交所有代码。
yarn eject
然后会出现询问是否要 eject,这种行为是永久的,选择是(y)
eject 完成后会在项目中出现两个新的文件夹叫做 “config” 和 “scripts”,此时 webpack 的配置文件(webpack.config.js)就在 "config" 文件夹中。所有的 loader 要在该配置文件中配置。
然后开始安装 svg-sprite-loader ,一般安装 webpack或typescript 相关的东西都是 --dev 安装的。
yarn add --dev svg-sprite-loader
安装完后,查看 package.json 中对应的 webpack 版本号,按照 svg-sprite-loader 官方文档说的,配置 webpack.config.js。
//添加如下代码到 webpack.config.js 的 rules 中的 oneOf 中,这里面是专门放 loader 的
{
test: /\.svg$/,
use: [
{ loader: 'svg-sprite-loader', options: {} },
'svg-transform-loader',
'svgo-loader'
]
}
该配置语句涉及到三个 loader,分别是 svg-sprite-loader 、svg-transform-loader 和 svgo-loader。这三个的作用可分别查看对应的官网那。在这里,只需要用到 svg-sprite-loader 和 svgo-loader。svgo-loader 是用于对 svg 图片进行优化的。
{
test: /\.svg$/,
use: [
{ loader: 'svg-sprite-loader', options: {} },
{ loader: 'svgo-loader', options: {
plugins: [
{removeAttrs: {attrs: 'fill'}},
]
}
}
]
}
安装 svgo-loader
yarn add --dev svgo-loader
安装好 svg-sprite-loader 和 svgo-loader 并配置好对应的 webpack 后,
因为配置了 webpack,一定要 yarn start 重启项目才有效!!!重启!重启!重启!
即可使用 svg symbol,使用方法如下:其中 xlinkHref 属性值为 引入的 svg 图标的文件名加#。
import x from 'icons/money.svg';
console.log(x);
<svg>
<use xlinkHref="#money" />
</svg>
可以比较灵活地控制 svg 图片,如添加颜色:
<svg fill="red" className="icon">
<use xlinkHref="#money" />
</svg>
但是使用 import 的方式引入 svg文件时,由于 TreeShaking 现象的存在,如果变量不被引用,就会被渲染树自动移除,就不会正常出现 svg 图标,解决这种现象的方法就是将 import 引入改成 require
引入。因为 TreeShaking 不适用于 require
require( 'icons/money.svg');
看到写了三遍以上的重复代码要将其简化,抽离成一个组件,避免重复代码的出现。在这里图标的加载重复了三遍,可将 svg图标 抽离成一个 Icon.tsx 组件,通过传递外部属性值图标文件的名字来显示图标:
require( 'icons/money.svg');
require('icons/tag.svg');
require('icons/chart.svg');
type Props = {
name: string
}
const Icon = (props: Props) => {
return (
<svg className="icon">
<use xlinkHref={'#' + props.name}/>
</svg>
);
};
在上述的 Icon 组件中需要手动引入多个 svg 文件,当 svg 文件过多时,就会有多个 require 语句,这里使用引入目录的方式,将上述的三个 require 语句改为如下代码。
let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
try {importAll(require.context('icons', true, /\.svg$/));} catch (error) {console.log(error);}
此时的 __WebpackModuleApi 会报错找不到,需要引入 typescript 的某个声明:
yarn add --dev @types/webpack-env
首先,并不是每一个页面都需要有 Nav组件 的,因此不能将 Nav组件 放在 标签里。需要将其单独抽离成一个组件,每一个页面需要时单独加载。
const Layout = (props: any) => {
return (
<Wrapper>
<Main>
{props.children}
</Main>
<Nav/>
</Wrapper>
);
};
//使用组件
<Layout>
<h2>统计页面</h2>
</Layout>
在 Nav 导航栏组件中,在点击切换页面的图标时,需要高亮显示。这就涉及到为 svg 图标自定义颜色样式。导航栏链接不仅包含图标,还包含文字,导航栏链接是由 react-router 的 Link 标签 设置的,那么如何使 Link 元素高亮呢?这就涉及到两个方面,首先必须知道该标签是否被选中,其次是设置选中后的颜色。
- react-router 的 active class 功能(判断是否选中 selected)
进去 react router 的官网,搜索 active class 相关的使用方法。可以看到 active class 功能只有在 NavLink 标签内有,作用就是在被选中时添加 selected 类。
<NavLink to="/tags" activeClassName="selected">
<Icon name="tag"/>
标签
</NavLink>
- svgo-loader 去除 svg 图片的 fill 属性(设置高亮颜色)
首先是 NavLink 标签的文字变红,react router 中的 NavLink 标签被编译后就是 a 标签,因此在 a 标签中设置样式:
> a{
&.selected{
color: red;
.icon{
fill: red;
}
}
}
上述方法对于没有带有 fill 属性的 svg 图片来说是会被当成文字变红高亮的,但是对于一些带有 fill 属性的 svg 资源,上述自定义颜色不起作用。这就需要用到 svgo-loader,svgo-loader 是优化 svg 资源的,有提供删除属性的功能。查看 svgo-loader 和 svgo 的相关选项配置。添加如下:
{ loader: 'svgo-loader', options: {
plugins: [
{removeAttrs: {attrs: 'fill'}},
]
} }
- 在 yarn eject 后再启动 yarn start 时,遇到报错 Cannot find module '@babel/helper-create-regexp-features-plugin',表示缺少改模块,可手动安装:
yarn add @babel/helper-create-regexp-features-plugin
。或者将 node_modules 重新删除再重新安装
rm -rf node_modules
yarn install
- 在该项目中,为了兼容移动端的字体,使用了 font.css中文 来使得在不同平台上都可以有很好的字体显示效果。具体做法是在
helper.scss
中将字体样式定义成了一个变量。