React使用本地svg图片配置

react使用本地svg图片

采用react-create-app命令生成项目。
安装svg插件:

yarn add svg-sprite-loader svgo-loader --dev

svgo-loadert 插件也可以不用。
最开始想采用react-app-rewired插件,安装react-app-rewired,customize-cra插件,config-overrides.js配置如下:

const rewireEslint = require('react-app-rewired-eslint');
module.exports = function override (config, env) {
  // do stuff with the webpack config...
  config = rewireEslint(config, env);
  return config
}

const path = require('path')
function resolve (dir) {
  return path.join(__dirname, '.', dir)
}

const {
  override,
  addWebpackModuleRule,
  fixBabelImports,
  addLessLoader,
  adjustStyleLoaders,
  addWebpackAlias
} = require('customize-cra')

module.exports = override(
  addWebpackModuleRule(
  //   {
  //   test: /\.(png|jpe?g|gif|bpm|webp)(\?.*)?$/,
  //   exclude: path.resolve(__dirname, '../src/assets/images/svg'), //不处理指定svg的文件
  //   use: {loader: "url-loader",options: {} }
  // },
  // 配置.svg
  {
    test: /\.svg$/,
    include: path.resolve(__dirname, '../src/assets/icons'), //全局引入
    use:  [
      { loader: 'svg-sprite-loader', options: {} },
      { loader: 'svgo-loader', options: {symbolId: "icon-[name]"} },
    ]
  }),
  // 针对antd 实现按需打包:根据import来打包 (使用babel-plugin-import)
  fixBabelImports('import',{
    libraryName:'antd',
    libraryDirectory:'es',
    style:true,//自动打包相关的样式 默认为 style:'css'
  }),
  addLessLoader({
    lessOptions: {
      javascriptEnabled: true,
      modifyVars: { '@brand-primary': '#1DA57A' },
      // localIdentName: '[local]--[hash:base64:5]' // 自定义 CSS Modules 的 localIdentName
    }    
  }),
  adjustStyleLoaders(({ use: [, , postcss] }) => {
    const postcssOptions = postcss.options;
    postcss.options = { postcssOptions };
  }),
  // 路径别名
  addWebpackAlias({
    '@': resolve('src'),
    '@components': resolve('src/components'),
    '@pages': resolve('src/pages')
  })

全局引入SVG的所有图片,代码如下:

  1. 配置全局加载svg图片
    在这里插入图片描述
    index.js代码如下:
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

如果提示找不require,可在tsconfig.json中加入

"types": [
      "node", // 加上此处配置
      "webpack-env"
    ]

或.eslintrc.js配置如下:

"env": {
    "node": true,
    ...
    }

在index.tsx中引入(相当于项目主入口文件),不需要其他操作:

import '@/assets/icons'
  1. 代码实现
import React from "react";
const OsIcon = () => {
  return (
      <svg  className="svg-icon"
          aria-hidden="true"
        >
      <use xlinkHref={'#'+ name}></use>
    </svg>
  )
}
export default OsIcon

在其他页面使用此组件

import OsIcon from "../../components/OsIcon/OsIcon";
 <OsIcon name="logout" />

图片怎么都出不来,配置不方面都没有问题,最后定位到应该默认的webpack配置的问题。
生成webpack

yarn eject

查看生成webpack.config.js配置文件,有如下内容:

	{
        test: /\.svg$/,
        use: [
          {
            loader: require.resolve('@svgr/webpack'),
            options: {
              prettier: false,
              svgo: false,
              svgoConfig: {
                plugins: [{ removeViewBox: false }],
              },
              titleProp: true,
              ref: true,
            },
          },
          {
            loader: require.resolve('file-loader'),
            options: {
              name: 'static/media/[name].[hash].[ext]',
            },
          },
        ],
        issuer: {
          and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
        },
      },

由于此处已经加载svg配置,所以在config-overrides.js配置怎么都不生效,只能在webpack.config.js中配置,删除上述配置,加入配置如下:

{
              test: /\.svg$/,
              include: path.resolve(__dirname, '../src/assets/icons'), 
              use:  [
                { loader: 'svg-sprite-loader', options: {} },
                // { loader: 'svgo-loader', options: {symbolId: "icon-[name]"} },
              ]
            },

启动,显示正常。

封装组件,添加参数与事件

import React, {useMemo, useEffect } from "react";
interface SvgProps {
  name: string;  // 图片名称
  className?: string; //class 名称
  rotate?: number; 
  size?: string | number;
  onclick?: any; // onClick事件
}
/** 自定义SVG图片组件 */
const OsIcon= (props: SvgProps) => {
  let {
    name,
    className,
    rotate,
    size,
    onclick,
  } = props;
  const setData = () => {
    name = "";
    className = "";
    rotate = 0;
    size = 24;
    onclick = new Function
  }
  useEffect(() => { setData(), [] }) // 初始化数据,在渲染的时候初始化一次数据,那么第二个参数必须传空数组
  const svgclass = useMemo(() => {
    if (className) {
      return 'svg-icon '+ className.trim()
    }
    return "svg-icon"
  }, [className])
  const svgStyle = useMemo(() => {
    return {
      transform: 'rotate(' + rotate  + 'deg)',
      fontSize: size  + 'px'
    }
  }, [rotate])
  return (
    <div className="b-k flex-display flex-ai-center ">
      <svg className={svgclass}
        aria-hidden="true"
        style={svgStyle}
        onClick={ onclick }
        >
      <use xlinkHref={'#'+ name}></use>
    </svg>
    </div>
  )
}
export default OsIcon

svg-iconless定义如下:

.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

组件使用如下:

const TabsView = (props:any)=> {
  const popupClick =() => {
     alert('我是一个弹窗~')
  }
 return (
      <div className="m-b-10 m-r-10 m-l-10 m-t-10">
        <OsIcon name="logout" onclick={ popupClick} />
      </div>
    )
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值