Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何声明SVG组件的道具类型?[反应、打字脚本和网页]_Reactjs_Typescript_Svg_Webpack - Fatal编程技术网

Reactjs 如何声明SVG组件的道具类型?[反应、打字脚本和网页]

Reactjs 如何声明SVG组件的道具类型?[反应、打字脚本和网页],reactjs,typescript,svg,webpack,Reactjs,Typescript,Svg,Webpack,基本上,我想做的是将SVG图标导入到我的react组件中,并向其添加道具。类似于size=“24px”使其作为一个组件更加灵活。或者通过添加classNameprop(这样我就可以添加例如hover-prop)来使用CSS对其进行编辑。 由于这是我第一次在Webpack中使用TypeScript,我对如何声明SVG元素的类型感到困惑,因此出现了一个错误(如下所示) 由于包含SVG的方法很多,我决定将其作为一个组件导入 menu-icon.svg <svg width="24&qu

基本上,我想做的是将SVG图标导入到我的react组件中,并向其添加道具。类似于
size=“24px”
使其作为一个组件更加灵活。或者通过添加
className
prop(这样我就可以添加例如hover-prop)来使用CSS对其进行编辑。 由于这是我第一次在Webpack中使用TypeScript,我对如何声明SVG元素的类型感到困惑,因此出现了一个错误(如下所示)

由于包含SVG的方法很多,我决定将其作为一个组件导入

menu-icon.svg

<svg width="24" height="24" viewBox="0 0 24 24">
  <path fill="currentColor" fillRule="evenodd" d="M4.5 5h15a.5.5 0 1 1 0 1h-15a.5.5 0 0 1 0-1zm0 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1z"></path>
</svg>
到目前为止我的理解是
  • 我可以将svg组件包装在一个div中,然后像这样添加一个
    className
    ,但我觉得这是一个不雅观的解决方案,并不是一个好的实践
  • 我从中了解到SVG道具不是字符串,因为它们是
    SVganizatedString
    对象。因此:
  • 我试图创建.tsx文件而不是.svg(那时我不需要
    index.d.ts
    文件),但只有当
    className
    的类型为
    string
    时,它才能工作。另外,我不确定将SVG图标存储在扩展名为
    .SVG
    的文件中是否是一种好的做法。在我看来,这不利于清晰。如果我错了,请告诉我好的实践是什么。下面是一个例子:
从“React”导入React;
接口菜单{
类名?:svganizatedstring;
}
导出类MenuIcon扩展了React.PureComponent{
render(){
返回(
);
}
}

我觉得我缺少一些基础知识,我真的很难弄清楚我应该关注什么,因为有几个主题结合在一起

您可以通过全局抽象来参数化SVG,从而实现简单的JSX。元素级定制。怎么用?使用React的FC。尝试实现以下功能:

  • 创建以下接口
  • svgiconstationvalues
    导入tsx文件
  • 将React中的
    {FC}
    导入同一tsx文件
  • 创建一个
    SvgIcon
    接口,扩展
    FC
    svgiconinstancevalues
  • 如您所见,抽象了三个单独的类名参数(1、2、3):(1)类名用于
    ,属性
    JSX.intrinsiceelements.svg:SVGProps
    ;(2)
    属性的类名称2
    JSX.intrinsiceelements.circle:SVGProps
    ;(3)
    属性JSX.IntrinsicElements.path的类名称3:SVGProps

  • 请注意,
    const-ArIcon:SvgIcon=({…}):JSX.Element=>{…}
    实际上是一个JSX.Element。因此,
    本身和任何子元素(圆、路径等)都是
    JSX.intrinsiceelements
    ,每个元素都允许有自己唯一的
    类名。这些
    className
    调用是手动添加到svg的,转换调用也是如此(在其他地方内联旋转图标)

  • JSX.intrinsiceelements
    JSX属性
    类名定义如下

  • 这使用了tailwindcss和React的Next.js框架。也就是说,如果我想让包含图标的
    JSX.intrinsiceElement
    圆圈仅在移动设备上脉动,该怎么办?将顺风的
    动画脉冲
    添加到
    className2
    ,如下所示
/。。。
常量arIconXs:JSX.Element=(
如果使用typescript和next对react-fontsawesome库进行黑客攻击,以创建自定义的fontsawesome SVG图标,这些图标将保留到生产环境中,并且不会因库版本更新而改变,这会激发您的兴趣


干杯

我一直在面对这个问题,这个解决方案对我很有效:

声明模块“*.svg”{
从“react”导入{ReactElement,SVGProps};
常量内容:(道具:SVGProps)=>ReactElement;
导出默认内容;

}
谢谢,非常好用,顺便说一句,你能为Next.js+TypeScript精确你的svgr配置吗?我想知道我是否需要为svgr使用任何TypeScript选项。谢谢!你把这段代码放在哪里?@v把它加载到你的TypeScript项目根文件夹的index.d.ts上
import React from 'react';
import MenuIcon from '../assets/menu-icon.svg';

const Header: React.SFC = () => {
  return (
    <header className="c-header u-side-paddings">
      <MenuIcon className="c-header__icon" />  // <-- className prop doesn't match provided type
    </header>
  );
};

export default Header;
declare module '*.svg' {
  import React = require('react');
  export const ReactComponent: React.SFC<React.SVGProps<SVGSVGElement>>;
  const src: string;
  export default src;
}
(JSX attribute) className: string
Type '{ className: string; }' is not assignable to type 'IntrinsicAttributes'.
  Property 'className' does not exist on type 'IntrinsicAttributes'.ts(2322)
    import React from 'react';
    
    interface MenuIcon {
      className?: SVGAnimatedString;
    }
    
    export class MenuIcon extends React.PureComponent<MenuIcon> {
      render() {
        return (
          <svg width="24" height="24" viewBox="0 0 24 24">
      <path fill="currentColor" fillRule="evenodd" d="M4.5 5h15a.5.5 0 1 1 0 1h-15a.5.5 0 0 1 0-1zm0 
 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1z"></path>
    </svg>
        );
      }
    }
interface SvgIconConstituentValues {
    strokeColor?: string;
    strokeWidth?: string;
    strokeWidth2?: string;
    strokeWidth3?: string;
    strokeFill?: string;
    fillColor?: string;
    fillColor2?: string;
    fillColor3?: string;
    fillColor4?: string;
    fillColor5?: string;
    fillColor6?: string;
    fillColor7?: string;
    imageWidth?: string;
    imageHeight?: string;
    width?: string;
    height?: string;
    rotateCenter?: number;
    className?: string;
    className2?: string;
    className3?: string;
    className4?: string;
    className5?: string;
}

export default SvgIconConstituentValues;
import { FC } from 'react';
import SvgIconConstituentValues from 'types/svg-icons';

// FC can be parameterized via Abstraction
export interface SvgIcon extends FC<SvgIconConstituentValues> {}
export const ArIcon: SvgIcon = ({
    width = '8.0556vw',
    height = '8.0556vw',
    strokeColor = `stroke-current`,
    strokeWidth = '2',
    fillColor = 'none',
    fillColor2 = `fill-primary`,
    rotateCenter = 0,
    className = ` antialiased w-svgIcon max-w-svgIcon`,
    className2 = ` stroke-current`,
    className3 = ` fill-primary`
}): JSX.Element => {
    return (
        <svg
            width={width}
            height={height}
            viewBox='0 0 65 65'
            fill={fillColor}
            xmlns='http://www.w3.org/2000/svg'
            className={className}
            transform={`rotate(${rotateCenter}, 65, 65)`}
        >
            <circle
                cx='32.5'
                cy='32.5'
                r='31.5'
                stroke={strokeColor}
                strokeWidth={strokeWidth}
                className={className2}
            />
            <path
                d='M30.116 39H32.816L27.956 26.238H25.076L20.18 39H22.808L23.87 36.084H29.054L30.116 39ZM26.462 28.992L28.226 33.816H24.698L26.462 28.992ZM40.7482 39H43.5202L40.7842 33.78C42.4582 33.294 43.5022 31.944 43.5022 30.162C43.5022 27.948 41.9182 26.238 39.4342 26.238H34.4482V39H36.9502V34.086H38.2462L40.7482 39ZM36.9502 31.944V28.398H38.9662C40.2262 28.398 40.9642 29.1 40.9642 30.18C40.9642 31.224 40.2262 31.944 38.9662 31.944H36.9502Z'
                fill={fillColor2}
                className={className3}
            />
        </svg>
    );
};
SVGAttributes<T>.className?: string | undefined
import { ArIcon } from 'components/svg-icons';
import Link from 'next/link';
import { Media } from 'components/window-width';
import { Fragment } from 'react';
import DarkMode from 'components/lead-dark-mode';

const ArIconConditional = (): JSX.Element => {
    const arIconXs: JSX.Element = (
        <Media at='xs'>
            <Link href='/'>
                <a
                    className='container block pl-portfolio pt-portfolio justify-between mx-auto w-full min-w-full '
                    id='top'
                    aria-label='top'
                >
                    <ArIcon width='18vw' height='18vw' className='transition-all transform translate-y-90' 
 className2='transition-all duration-1000 delay-200 transform' className3='text-secondary fill-secondary' />
                </a>
            </Link>
        </Media>
    );

    const arIconSm: JSX.Element = (
        <Media at='sm'>
            <Link href='/'>
                <a
                    className='container block pl-portfolio pt-portfolio justify-between mx-auto w-full min-w-full '
                    id='top'
                    aria-label='top'
                >
                    <ArIcon width='15vw' height='15vw' className='' className2='' className3='' />
                </a>
            </Link>
        </Media>
    );

    const arIconMd: JSX.Element = (
        <Media at='md'>
            <Link href='/'>
                <a
                    className='container block pl-portfolio pt-portfolio justify-between mx-auto w-full min-w-full '
                    id='top'
                    aria-label='top'
                >
                    <ArIcon width='12.5vw' height='12.5vw' className='' className2='' className3='' />
                </a>
            </Link>
        </Media>
    );

    const arIconDesktop: JSX.Element = (
        <Media greaterThan='md'>
            <Link href='/'>
                <a
                    className='container block pl-portfolio pt-portfolio justify-between mx-auto w-full min-w-full '
                    id='top'
                    aria-label='top'
                >
                    <ArIcon width='10vw' height='10vw' className='' className2='' className3='' />
                </a>
            </Link>
        </Media>
    );

    const ArIconsCoalesced = (): JSX.Element => (
        <Fragment>
            <div className='relative block justify-between lg:w-auto lg:static lg:block lg:justify-start transition-all w-full min-w-full col-span-5'>
                {arIconXs}
                {arIconSm}
                {arIconMd}
                {arIconDesktop}
            </div>
        </Fragment>
    );
    return (
        <Fragment>
            <div className='select-none relative z-1 justify-between pt-portfolioDivider navbar-expand-lg grid grid-cols-6 min-w-full w-full container overflow-y-hidden overflow-x-hidden transform'>
                <ArIconsCoalesced />
                <div className='pt-portfolio'>
                    <DarkMode />
                </div>
            </div>
        </Fragment>
    );
};

export default ArIconConditional;

// ...
    const arIconXs: JSX.Element = (
        <Media at='xs'>
            <Link href='/'>
                <a
                    className='container block pl-portfolio pt-portfolio justify-between mx-auto w-full min-w-full '
                    id='top'
                    aria-label='top'
                >
                    <ArIcon width='18vw' height='18vw' className='transition-all transform translate-y-90' 
 className2='transition-all duration-1000 delay-200 transform animate-pulse' className3='text-secondary fill-secondary' />
                </a>
            </Link>
        </Media>
    );
// ...