在Vue.JS中使用图标组件

  • 原文链接: http://github.crmeb.net/u/LXT

  • 本文对原文进行一次翻译,并从React开发者的角度简单地做了一些解读。

  • 此文不包含字体图标和SVG sprite。仅在此讨论允许用户按需导入的图标系统。

There are three major ways of exposing API of an icon component in Vue.js and each one of them has its own pros & cons:

在Vue.js的生态里,有3种主流的API形态,它们有各自的优缺点:

1.使用单一的组件(如),让乃通过name或者type属性来指定真正的图标。

图标的数据通过一个全局的“池子”来注册。

       // v-icon/flag.js
       import Icon from 'v-icon'
       import { mdiFlag } from '@mdi/js'
       Icon.add('flag', mdiFlag)

然后这样子使用:

       <template>
       <v-icon name="flag" />
       </template>

       <script>
       import VIcon from 'v-icon'
       import 'v-icon/flag'
       export default {
       components: {
       VIcon
        }
       }
       </script>

在我维护的VueAwesome(内置了FontAwesome图标的组件库)中用了这个方案,同时我认为这是当前最符合人机工程学的形式。不过图标的name属 性和那些纯副作用的模块的导入之间的关系比较隐式,图标的数据也在全局注册。如果你有多个不同版本的v-icon,就可能出现问题。

FontAwesome官方的Vue.js组件用了一个稍微不同的方案,它们让用户自己主动把图标加到全局的池子中(也可能我不应该把这个方式归类到这个方案中):

       import { library } from '@fortawesome/fontawesome-svg-core'
       import { faUserSecret } from '@fortawesome/free-solid-svg-icons'

       library.add(faUserSecret)

2.用一个单一的维护(如<v-icon),用户通过datacontent之类的属性创建真正的图标。

用户主动把图标的数据传递给组件:

       <template>
       <v-icon :content="mdiFlag" />
       </template>

       <script>
       import VIcon from 'v-icon'
       import { mdiFlag } from '@mdi/js'

       export default {
       components: {
       VIcon
       },
       created() {
       Object.assign(this, {
       mdiFlag
          })
        }
       }
       </script>

这是Vuetify支持的方式(Vuetify通过这种方式支持多种图标的使用方式),这种试在人机工程和直观性上有些损失,但没有方案1的缺点。

3.每个组件代表不同的图标(如<icon-flag /><icon-star />等)。

这个方案里,每个组件通过一个图标工厂创造出来:

       // icon-flag.js
       import { mdiFlag } from '@mdi/js'
       import { createIcon } from 'v-icon'

       export default createIcon('flag', mdiFlag)

并通过这种方式使用:

       <template>
       <icon-flag />
       </template>

       <script>
       import { IconFlag } from 'v-icon'

       export default {
       components: {
	   VIcon,
	   IconFlag
         }
       }
       </script>

这种方案在React社区里被广泛采用,我在本文的后续部分将展开讨论。

每个组件代表一个图标

我将更深入地说一下这种方案在Vue.js中的使用。

在Vue.js中,模板和脚本是分开的,组件通过components选项注册。不过就像我们知道的,如果一个组件要用很多图标的话,这种方式会挺麻烦。

Vue 2

<template>
 <div>
    <!-- inline -->
    <icon-flag />

    <!-- conditional -->
    <icon-flag v-if="flag" />
    <icon-star v-else />

    <!-- dynamic -->
    <component :is="flag ? IconFlag : IconStar" />
  </div>
</template>

<script>
import { IconFlag, IconStar } from 'foo-icons'

export default {
  components: {
    IconFlag,
    IconStar
  },
  data() {
    return {
      flag: true
    }
  },
  created() {
    Object.assign(this, {
      IconFlag,
      IconStar
    })
  }
}
</script>

可以看到如果想用图标的is绑定,我们必须把components手动暴露到渲染上下文中。我们可以用字符串去替换组件定义来绕过,但对代码检查和类型系统来说就不那么友好。

<template>
  <div>
    <!-- inline -->
    <icon-flag />

    <!-- conditional -->
    <icon-flag v-if="flag" />
    <icon-star v-else />

    <!-- dynamic -->
    <component :is="flag ? 'icon-flag' : 'icon-star'" />
  </div>
</template>

<script>
import { IconFlag, IconStar } from 'foo-icons'

export default {
  components: {
    IconFlag,
    IconStar
  },
  data() {
    return {
      flag: true
    }
  }
}
</script>

Vue 3

<template>
  <!-- inline -->
  <icon-flag />

  <!-- conditional -->
  <icon-flag v-if="flag" />
  <icon-star v-else />

  <!-- dynamic -->
  <component :is="flag ? IconFlag : IconStar" />
</template>

<script>
import { ref } from 'vue'
import { IconFlag, IconStar } from 'foo-icons'

export default {
  components: {
    IconFlag,
    IconStar
  },
  setup() {
    const flag = ref(true)

    return {
      flag,
      IconFlag,
      IconStar
    }
  }
}
</script>

如果用:is绑定,<script>部分会变成这样:

import { ref } from 'vue'
import { IconFlag, IconStar } from 'foo-icons'

export default {
  components: {
    IconFlag,
    IconStar
  },
  setup() {
    const flag = ref(true)

    return {
      flag
    }
  }
}

如果我们采纳<script components>这样的形式的话:

<template>
  <!-- inline -->
  <icon-flag />

  <!-- conditional -->
  <icon-flag v-if="flag" />
  <icon-star v-else />

  <!-- dynamic -->
  <component :is="flag ? 'icon-flag' : 'icon-star'" />
</template>

<script components>
export { IconFlag, IconStar } from 'foo-icons'
</script>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const flag = ref(true)

    return {
      flag
    }
  }
}
</script>

后记

这很篇文章很精练地介绍了在Vue中按需引入图标的方式,与React社区做比较,可以看到两个生态的差异还是存在的。在React社区中,使用第3种方式(每个图标一个组件)非常普遍,如NPM上排名较高的react-icons和知名组件库@ant-design/icons、@material-ui/icons都是这一形态。

这可能是由于React社区中并不倾向将“组件”这一概念特殊化,组件就是普通的函数、普通的类,所以它的复用于其它的函数、类的复用相同,如同lodash会导出很多个工具函数一样,一个图标库会导出很多个图标组件非常合理。

在文中对于使用createIcon工厂函数的使用有一些可以优化的点。正常使用工厂函数会让创建的组件不可被tree shaking,其原因是语法分析会认为createIcon函数本身是有副作用的,因此这个调用不能被安全地删除。可以通过terser的特殊注释来标记:

// icon-flag.js
import { mdiFlag } from '@mdi/js'
import { createIcon } from 'v-icon'

export default /*#__PURE__*/createIcon('flag', mdiFlag)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue Devtools 火狐版是一款用于调试 Vue 应用程序的浏览器插件。它是基于 Chrome 插件开发的,可提供一些非常有用的功能来帮助开发人员进行 Vue 应用程序的调试。此外,Vue.js Devtools 火狐版还可以在 Firefox 和 Safari 安装和使用。 要在 Firefox 安装 Vue.js Devtools 火狐版,您可以按照以下步骤操作: 1. 首先,打开 Firefox 浏览器,并前往 Vue.js Devtools 火狐版的官方网站或 Mozilla 的扩展市场。 2. 在插件页面,点击“添加到 Firefox”按钮,开始安装 Vue.js Devtools 火狐版插件。 3. 安装完成后,您会看到一个 Vue.js Devtools 图标出现在 Firefox 浏览器的工具栏。 4. 现在,您可以打开您的 Vue 应用程序,并通过点击 Vue.js Devtools 图标来打开插件面板。 5. 在插件面板,您可以查看 Vue 组件的层次结构、数据和状态的变化,以及其他有关 Vue 应用程序的调试信息。 6. 此外,您还可以使用插件面板提供的一些交互式工具来修改应用程序的状态和数据,以帮助您进行更深入的调试。 请注意,为了在 Firefox 使用 Vue.js Devtools 火狐版,您可能需要更新您的 Firefox 浏览器到最新版本,并确保您已启用了扩展程序的安装。 总结一下,Vue.js Devtools 火狐版是一款用于调试 Vue 应用程序的浏览器插件,您可以在 Firefox 安装并使用它来提高您的调试效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值