1. 目标一: 我要为我的 icon 添加 css 样式
修改文件:@/lib/Icon/index.tsx
import * as React from 'react';
import './importAllIcons';
import './icon.scss'
interface IconType {
icon: string
}
const Icon: React.FC<IconType> =({icon})=>{
return<svg className='sweetui-icon'>
<use xlinkHref={ `#${icon}` }></use>
</svg>
}
export default Icon;
新建scss 文件, @/lib/Icon/icon.scss:
.sweetui-icon{
width: 1em;
height: 1em;
}
重新运行项目yarn start, 命令行输出错误:
错误原因: webpack 无法识别scss 类型文件, 需要安装专用的加载器
配置webpack, 告诉它如何加载使用scss文件
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
为什么需要配置这三个loader: 查看这篇博客
安装相关loader, 修改@/package.json,
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"node-sass": "npm:sass",
"css-loader": "^2.1.1",
运行安装命令: yarn
重新启动项目: yarn start
浏览器查看:
我们的目标成功了!!
2. 目标二: 我要给Icon添加点击事件
- 修改
@/lib/Icon/index.tsx
import * as React from 'react';
import './importAllIcons';
import './icon.scss'
interface IconType {
icon: string
onClick?: ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void) | undefined
}
const Icon: React.FC<IconType> =({icon, onClick})=>{
return<svg className='sweetui-icon' onClick={onClick}>
<use xlinkHref={ `#${icon}` }></use>
</svg>
}
export default Icon;
技巧: 如何找到 onClick 类型? 查看这篇博文
修改@/lib/index.tsx:
import React from 'react';
import ReactDOM from 'react-dom';
import Icon from './Icon';
const fn =(e: React.MouseEvent<SVGSVGElement>)=>{
console.log('haha',e.currentTarget);
}
ReactDOM.render(
<div>
<Icon icon='wechat' onClick={fn}/>
<Icon icon='alipay'/>
</div>
,
document.getElementById('root')
)
浏览器测试:
我们的目标成功了!
3. 目标三: 一次性让我们的icon能响应事件
上个目标我们成功添加了 onClick事件!
如果我想为我的Icon组件添加, onClick, onMouseMove, onMouseLeave ...等属性, 我总不能一个个自己添加把?!
一次性添加所有响应事件的方法如下:
修改: @/lib/Icon/index.tsx
import * as React from 'react';
import './importAllIcons';
import './icon.scss'
interface IconType extends React.SVGAttributes<SVGSVGElement>{
icon: string
}
const Icon: React.FC<IconType> =(props)=>{
return<svg
className='sweetui-icon'
{...props}
>
<use xlinkHref={ `#${props.icon}` }></use>
</svg>
}
export default Icon;
如何快速找到需要继承的父类 React.SVGAttributes<SVGSVGElement>看这篇博客
修改:@/lib/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import Icon from './Icon';
const fn =(e: React.MouseEvent<SVGSVGElement>)=>{
console.log('haha',e.currentTarget);
}
ReactDOM.render(
<div>
<Icon icon='wechat'
onClick={fn}
onMouseMove={()=>{console.log('move');}}
/>
<Icon icon='alipay'/>
</div>
,
document.getElementById('root')
)
看浏览器:
我们的目标成功了!
4. 目标四: 解决className 会被覆盖的bug
@/lib/Icon/index.tsx部分代码如下, 如果props包含 className这个属性, 就会把className='sweetui-icon'覆盖掉了
const Icon: React.FC<IconType> =(props)=>{
return<svg
className='sweetui-icon'
{...props}
>
<use xlinkHref={ `#${props.icon}` }></use>
</svg>
}
解决办法:
安装classnames : yarn add classnames
修改@/lib/Icon/index.tsx
import * as React from 'react';
import './importAllIcons';
import './icon.scss'
import classNames from 'classnames';
interface IconType extends React.SVGAttributes<SVGSVGElement>{
icon: string
}
const Icon: React.FC<IconType> =(props)=>{
const {className, ...restProps} = props
return<svg
className={classNames('sweetui-icon', className)}
{...restProps}
>
<use xlinkHref={ `#${props.icon}` }></use>
</svg>
}
export default Icon;
我们的目标达成了!