新手问题 稍微折腾了一下 FontAwesome

lukefan · 2020年12月25日 · 最后由 xinyuewaisong 回复于 2021年01月02日 · 438 次阅读

作为一个将编程作为业余爱好的老程序员,折腾一下前端技术,实在是比较痛苦的过程。 前几天尝试着将老版本的 ruby on rails 程序升级上来的过程中学习了一下 webpack 和 react。 然后就尝试着将 jquery 和 bootstrap 搞进去。于是参照了:@syutran新手问题 rails 6 boostrap 尝鲜 中的代码。 唯一差别的是,将 NavBar 的部分,搞到了一个 react 的组件中,这个过程中需要将所有的 class=替换成了 className=,将 tabindex 替换成了 tabIndex。没有问题。 后来发现里面有个问题,就是 fontawesome 的引用出错了,文档中也说了这个没搞明白,于是我就自己试验了一下。

这种字体图标,一共尝试了三种方式:

1、 直接从 FontAwesome 官网上注册,然后生成了一共 kit 的链接,在 app/views/layouts/application.html.erb 中做引用 可以直接通过标记引用各种图标了 这种方式据说是最快的(有 cdn 在工作),不过好像免费方式的调用次数是有限制的,具体没看

2、 通过font-awesome-sass 这个 gem 来实现。 先在 Gemfile 中添加

gem 'font-awesome-sass', '~> 5.15.1'

做 bundle install 然后修改 app/assets/stylesheets/application.css 先将其改名为 application.css.scss 然后添加

@import "font-awesome-sprockets";
@import "font-awesome";

就可以工作了。 而且还可以通过 icon 这个函数,直接在 erb 文件中输出图标。

<%= icon('fas', 'flag') %>

不过这个方法有一个讨厌的地方,也是最后我舍弃了这种方式的主要原因。 我将代码:

@import "font-awesome-sprockets";
@import "font-awesome";

添加到了 app/javascript/styles/application.scss 中,然后再/app/javascript/packs/application.js 中引用

import "../styles/application"

会报错,font-awesome-sprockets 文件找不到,也不工作。为了后面所有的前端代码都放在统一的地方 app/assets 里面不再添加代码,这种方式被舍弃了。

3、 使用react-fontawesome 首先先读官方文档 作为免费用户,先添加各种免费库

yarn add @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/react-fontawesome
yarn add @fortawesome/free-brands-svg-icons @fortawesome/free-regular-svg-icons

然后就是在 React 中直接用组件来显示图标,这个过程中有一个比较麻烦的就是任何图标在调用之前,先要去做 import。

import ReactDOM from 'react-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCoffee } from '@fortawesome/free-solid-svg-icons'

const element = <FontAwesomeIcon icon={faCoffee} />

ReactDOM.render(element, document.body)

稍微简单一点儿的方法是,先引用一堆,并加入到一个库中,然后再在不同的组件中调用 注册:

import ReactDOM from 'react-dom'
import { library } from '@fortawesome/fontawesome-svg-core'
import { fab } from '@fortawesome/free-brands-svg-icons'
import { faCheckSquare, faCoffee } from '@fortawesome/free-solid-svg-icons'

library.add(fab, faCheckSquare, faCoffee)

调用:

import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

export const Beverage = () => (
  <div>
    <FontAwesomeIcon icon="check-square" />
    Your <FontAwesomeIcon icon="coffee" /> is hot and ready!
  </div>
)

调用

import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

export const Showcase = () => (
  <div>
    <FontAwesomeIcon icon={['fab', 'apple']} />
    <FontAwesomeIcon icon={['fab', 'microsoft']} />
    <FontAwesomeIcon icon={['fab', 'google']} />

    <FontAwesomeIcon icon="check-square" />
    With Coffee Checked, these companies always know their coffee is hot and ready!
  </div>
)

前面引用并加入到 library 中的 fab 是品牌图标库中的所有 fab 图标。引用一次之后,就都可以调用了。 这里面引用的格式我自己也有点儿晕,如果是直接 import 进来的图标, 比如 import { faCoffee } from '@fortawesome/free-solid-svg-icons' ,那么调用的时候最好用 如果是在 library 里面 add 过的,直接用 也是可以的。 如果是一次引入了一堆的那种情况,则需要用来调用。

这里面还有一个问题,加载了这种方式之后,是不工作的。 需要再加上一段代码:

import { dom } from '@fortawesome/fontawesome-svg-core'

dom.watch()

才可以让工作起来。不过我没太搞清楚这个代码的作用域是什么样的。并不是每次都灵。

最终,因为想要用新的 rails6。各种前端的东西,准备交给 react 来搞定,所以选择了 react-fontawesome 的方式。

顺便说一下,我的 react 并不是直接上来就

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Hello name="React" />,
    document.body.appendChild(document.createElement('div')),
  )
})

生猛开干的。 而是使用了 rails_react 的 gem 包,然后在 erb 文件中写<%=react_component("ComponentName") %>的方式来搞的。 这种方式好像还可以服务端渲染,但是具体能够有什么差异,我也没太搞明白。

老哥 你遇到的问题应该跟我一样

我看了下 实际上是 你需要解决一下 https://github.com/FortAwesome/Font-Awesome/blob/master/less/_variables.less 这个地方的

@fa-font-path: "../webfonts";

你可以参考下我这里的类似问题的解决方案 https://ruby-china.org/topics/40720

react_component 这个方法会帮你生成一个 div , 将参数变为 json 字符串, 传给一个 react 组件, 组件将 json 字符串再转化为 object, 再生成一个 child component , 这个 child component 则是你对应的那个组件, 之后也把 生成好的 object 给到你的组件的 props 里

话说如果是少量图标的话 可以试试 阿里的 https://www.iconfont.cn/ 这个我个人觉得比 fontawesome 好用

jicheng1014 回复

感谢,我学习一下。 现在的问题是,前后端的整合和分割的问题。 后端以后提供 webpack 的后端渲染,以及 graphql 的数据服务。 前端,一边是 web,一边是 flutter,使用同一套后端。 矢量图标,iconfont 也看了,感觉系统性没有 fontawesome 好,比较零碎。

关于 fontawesome,如果用了本地的库,比如 fontawesome-react 或 fontawesome-less 之类的库,引入了之后。如何在发布的时候,再改成直接用 fontawesome 提供的 cdn 模式呢?

现在还在研究 graphq-auth 或 devise-jwt 之类的东西,graphql 还需要加入 jwt 之类的东西保障一下。这东西好像也是很麻烦的。

lukefan 回复

应该是你的 iconfont 打开方式不对,看下这篇文章 手摸手,带你优雅的使用 icon GraphQL 个人感觉没 RESTful 顺手,可能是因为主要工作都一个人做的缘故吧😂

ruby117 回复

RESTful 肯定是最简单,最直接的。GraphQL 的优点是自解释,以及更大的灵活性。 比如 RESTful,你把接口写好了,就是固定的。GraphQL 则可以写一次,依靠不同的 Query 字符串就可以获得不同的结果。比如多传几个字段,少传几个字段。

lukefan 回复

GraphQL 的优点是自解释,以及更大的灵活性 很赞同这点。前后端不同开发团队才有必要上,小型团队就没必要了,徒增无效沟通成本。

ruby117 回复

我是一个业余程序员,写程序的原因是满足业余爱好。所以会学习并尝试使用新技术,并不是以商业效率为第一出发点的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号