微信小程序的 WXML 目前(2025.07)是不支持 <svg> 标签的,所以没办法直接使用 Lucide 这一类的图标,但小程序提供了 <image> 标签,是支持 SVG 格式的,但!直接用 <image> 引入 SVG 就没办法自定义颜色了。

有解决方案吗?有的,因为 <image> 是支持 base64 格式的,那我们动态创建 SVG 图标即可。

怎么动态创建呢,把图标的 SVG 字符串中的颜色熟悉(stroke)提取出来,将整个 SVG 字符串作为图标模板,然后用字符串的 replace() 替换即可。

本文的代码是 React + Taro,其他框架的思路是一样的,只是写法略有差异。这里需要用到 js-base64 这个库,记得先 npm 安装一下。

以 Lucide 的 book 图标为例,它的 SVG 是这样的:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-book-icon lucide-book"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"/></svg>

可以把 stroke="currentColor" 改成 stroke="{{color}}",同时把 width="24" height="24" 也改成 width="{{size}}" height="{{size}}" 然后封装成公共组件(Icon.tsx)帮我们做模板替换的事:

import { Image } from "@tarojs/components";
import { Base64 } from 'js-base64';

export interface IconProps extends React.PropsWithClassName {
  color?: string; // 新增颜色属性
  size?: number;  // 可选尺寸控制
}

interface IconComponentProps extends IconProps {
  svgTemplate: string;
}

export const Icon: React.FC<IconComponentProps> = ({
  className,
  color = "currentColor",
  size = 24,
  svgTemplate,
}) => {
  const svgData = useMemo(() => {
    const svgCode = svgTemplate
      .replace(/{{color}}/g, color)
      .replace(/{{size}}/g, String(size));

    const base64 = Base64.encode(svgCode);
    return `data:image/svg+xml;base64,${base64}`;
  }, [color, size, svgTemplate]);

  return (
    <Image
      className={className}
      src={svgData}
      mode="widthFix"
      style={{ width: `${size}px`, height: `${size}px` }}
    />
  );
};

之后我们的图标就可以这样实现:

import { Icon } from "../Icon";
import type { IconProps } from "../Icon";

// 其他图标修改 SVG_TEMPLATE 的值,并替换 width、height、stroke
const SVG_TEMPLATE = `
<svg xmlns="http://www.w3.org/2000/svg" width="{{size}}" height="{{size}}" viewBox="0 0 24 24" fill="none" stroke="{{color}}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-book-icon lucide-book">
  <path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"/>
</svg>
`;

export const Book: React.FC<IconProps> = props => {
    return <Icon {...props} svgTemplate={SVG_TEMPLATE} />;
}

这个图标就可以优雅地自定义大小和颜色了:

<Book size={24} color="#3f3f3f" />

标签: 小程序

添加新评论