React Native Icon方案:react-native-svg

hujiao發表於2018-09-01

原文地址:github.com/HuJiaoHJ/bl…

網上 React Native 的 icon 實現大都是使用iconfont方案,即:react-native-vector-icons

此方案存在一個問題:強依賴客戶端打包,即每新增圖示,就需要客戶端重新打包,資源管理上不能做到 RN 與客戶端解耦

為了避免這個問題,使用了SVG方案:react-native-svg 來實現Icon

接下來將從三個方面進行分享:

  • react-native-svg 使用
  • Icon元件實現及2Web
  • Icon元件使用

此文會涉及部分 React Native 轉 web 的知識,使用的是 react-native-web 方案,可以看看我之前寫的文章:react native轉web方案:react-native-web

react-native-svg 使用

安裝

npm install react-native-svg --save
複製程式碼

Link native code

react-native link react-native-svg
複製程式碼

以上操作,其實就是將 react-native-svg 的依賴安裝到客戶端中,進行了上面的操作,基本已自動完成安裝依賴,但是在部分IOS上會存在問題,如遇到問題可以去 react-native-svg 檢視解決方案

react-native-svg-uri

react-native-svg-uri 支援在RN中通過一個URL或者靜態檔案渲染svg,同時也支援傳入svg字串,將其渲染

使用如下:

// 安裝
npm install react-native-svg-uri --save
// 確保已在客戶端中安裝了 react-native-svg 依賴,若未安裝依賴,執行:
react-native link react-native-svg
複製程式碼

下面將使用 react-native-svg-uri 來實現Icon元件,這個庫原始碼只有兩個js檔案,有興趣的小夥伴可以自行了解~

Icon元件實現及2web

實現

上面我們有提到,react-native-svg-uri 支援傳入svg字串來渲染svg,所以可以將多個svg檔案通過指令碼的形式轉換成一個js物件或者一個json檔案,其格式如下:

svg.js

export default {
    "arrow-left": "<svg t=\"1533091848499\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"579\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"32\" height=\"32\"><defs><style type=\"text/css\"></style></defs><path d=\"M769.405 977.483a68.544 68.544 0 0 1-98.121 0L254.693 553.679c-27.173-27.568-27.173-72.231 0-99.899L671.185 29.976c13.537-13.734 31.324-20.652 49.109-20.652s35.572 6.917 49.109 20.652c27.173 27.568 27.173 72.331 0 99.899L401.921 503.681l367.482 373.904c27.074 27.568 27.074 72.231 0 99.899z\" fill=\"\" p-id=\"580\"></path></svg>"
}
複製程式碼

在使用時,可以通過獲取對應 key 的 value 傳給 react-native-svg-uri 渲染

上面的轉換指令碼可以參考:svg2json,程式碼:github.com/HuJiaoHJ/sv…

做好檔案轉換之後,我們可以開發Icon元件啦

index.js

import createIconSet from './create-icon-set';
// 即上面轉換得到的 svg.js
import svg from './svg';

const Icon = createIconSet(svg, 'rn_components');

export default Icon;

export { createIconSet };
複製程式碼

creact-icon-set.native.js

import React, { Component } from 'react';
import SvgUri from 'react-native-svg-uri';

export default function createIconSet(svg, fontName) {
    return class Icon extends Component {
        render () {
            const { icon, color, size, style } = this.props;
            let svgXmlData = svg[icon];

            if (!svgXmlData) {
                let err_msg = `no "${icon}"`;
                throw new Error(err_msg);
            }
            return (
                <SvgUri width={size} height={size} svgXmlData={svgXmlData} fill={color} style={style} />
            );
        }
    };
}
複製程式碼

以上就是Icon元件的實現

2web

對RN2web感興趣的小夥伴可以看看:react native轉web方案:react-native-web

在此基礎上,我們需要對我們Icon元件支援2web,由於沒有對應的web元件,所以需要我們自行實現對應web的元件

web端我們使用iconfont來做Icon元件(注意:iconfont不支援多色icon,多色的icon只能選擇svg或者img)

還是svg檔案轉換的問題,我們需要先將svg檔案轉換成iconfont,即

React Native Icon方案:react-native-svg

這樣我們就能向常規web一樣使用iconfont啦

上面的轉換工具可以參考:svg2iconfont,程式碼:github.com/HuJiaoHJ/sv…

當然,要注意記得將生成的iconfont.css檔案引入頁面html中,接下來看看2web的Icon元件實現,不需要額外新建資料夾,只需在相同資料夾下新增 creact-icon-set.js 檔案(注意到上面RN的檔案是 creact-icon-set.native.js),這在實際使用過程中,會自動識別這兩個檔案

creact-icon-set.js

import React, { Component } from 'react'
import { createElement, StyleSheet } from 'react-native'

export default function createIconSet(svgs, fontName) {
  return class Icon extends Component {
    render() {
      const { icon, color, size, style } = this.props
      const styles = StyleSheet.create({
        iconStyle: {
          color,
          fontSize: size,
        },
      })
      const props = {
        className: `${fontName ? fontName + '-' : 'icon-'}${icon}`,
        style: StyleSheet.compose(
          style,
          styles.iconStyle
        ),
      }
      return createElement('i', props)
    }
  }
}
複製程式碼

如果看了 react native轉web方案:react-native-web ,應該就能知道 import { createElement, StyleSheet } from 'react-native' 實際上是 import { createElement, StyleSheet } from 'react-native-web',沒錯,就是直接使用的 react-native-web 的 API 來開發轉web之後的元件

以上就完成了Icon元件的2web支援

Icon元件使用

我們怎麼使用呢?有兩種情況:

使用Icon元件自帶icon

Icon元件會自帶一些常用的icon,在使用這些icon時,使用較為簡單,直接引入,如下使用:

// 引入
import Icon from 'Icon';

// 使用
<Icon icon={'arrow-left'} size={30}/>
複製程式碼

注意:如果需要支援2web,需要將對應的 iconfont.css 引入到頁面html中

使用業務icon

如果需要新增業務icon,有如下兩步:

1、將svg轉換成js檔案(如需要支援2web,還需生成iconfont)

這部分就不詳細講了,可以參考上面的內容

2、呼叫 createIconSet 新建 CIcon元件

程式碼如下:

import React from 'react'
// 引入Icon元件的 createIconSet 方法
import { createIconSet } from 'Icon'
// 包含業務svg的js檔案
import svgs from './svgs'

// 傳入業務svg的js物件,生成CIcon元件
const CIcon = createIconSet(svgs)

export default function () {
  return Object.keys(svgs).map((item, index) => (
    // 使用
    <CIcon icon={item} color={'#000'} size={50} key={index} />
  ))
}
複製程式碼

以上所有程式碼可在個人開發的RN元件庫的專案中檢視到:rn_components,元件庫現在才剛開始建設,後續會不斷完善

寫在最後

以上就是我對 React Native Icon方案:react-native-svg 的分享,希望能對有需要的小夥伴有幫助~~~

喜歡我的文章小夥伴可以去 我的個人部落格 點star ⭐️

相關文章