简体   繁体   English

Vue.js 无法切换字体真棒图标

[英]Vue.js can't toggle a font-awesome icon

I am trying to toggle a font awesome icon based on a boolean value but it seems that the font-awesome icon remains on the screen after it is drawn:我正在尝试根据布尔值切换字体真棒图标,但似乎字体真棒图标在绘制后仍保留在屏幕上:

https://jsfiddle.net/50wL7mdz/200312/ https://jsfiddle.net/50wL7mdz/200312/

HTML: HTML:

<script src="https://unpkg.com/vue"></script>
<script defer src="https://use.fontawesome.com/releases/v5.0.8/js/all.js" integrity="sha384-SlE991lGASHoBfWbelyBPLsUlwY1GwNDJo3jSJO04KZ33K2bwfV9YBauFfnzvynJ" crossorigin="anonymous"></script>



<div id="app">
  <input v-model="marked" type="checkbox"/>
  <i v-if="marked" class="far fa-check-square"></i>
</div>

JS: JS:

new Vue({
  el: '#app',
  data: {
    marked: false
  }
})

Am I doing something wrong or is there a bug in font-awesome or vue.js?我做错了什么还是 font-awesome 或 vue.js 中有错误?

I ran into this issue recently when using Vue.js 2.5.x with FontAwesome 5.5.x — the icon classes were not being updated as expected.我最近在使用 Vue.js 2.5.x 和 FontAwesome 5.5.x 时遇到了这个问题——图标类没有按预期更新。

After switching from the FontAwesome Web Fonts + CSS implementation to SVG + JS , the following code no longer worked:从 FontAwesome Web Fonts + CSS 实现切换到 SVG + JS后,以下代码不再起作用:

<i :class="[sortByFirstNameAsc ? 'fa-chevron-up' : 'fa-chevron-down', 'fa']"></i>

What would happen is that FontAwesome JavaScript would fire and wrap the <i> tag and replace it with an SVG element, as in the following simplified example:会发生什么情况是 FontAwesome JavaScript 将触发并包装<i>标记并将其替换为 SVG 元素,如下面的简化示例所示:

<span data-v-2614dbd6="">
  <svg data-v-2614dbd6="" class="svg-inline--fa fa-caret-up" ...">
    ...
  </svg>
  
  <!-- <i data-v-2614dbd6="" class="fa fa-caret-up"></i> -->
</span>

Unfortunately, the active class was being toggled on the inner, hidden <i> tag and not the outer, visible SVG element.不幸的是,活动类是在内部隐藏的<i>标记而不是外部可见的 SVG 元素上切换的。

The workaround that restored the dynamic active class toggling was to wrap the FontAwesome icons in a span and use the v-show directive , as illustrated in the following code snippet:恢复动态活动类切换的解决方法是将 FontAwesome 图标包装在一个 span 中并使用v-show指令,如以下代码片段所示:

<span v-show="sortByFirstNameAsc"><i class="fa fa-caret-up"></i></span>
<span v-show="sortByFirstNameDesc"><i class="fa fa-caret-down"></i></span>

The FontAwesome documentation now recommends using their Vue component to avoid conflicts in the DOM: FontAwesome 文档 现在建议使用他们的 Vue 组件来避免 DOM 中的冲突:

Compatibility Heads Up!兼容性提示! If you are using Vue you need the vue-fontawesome package or Web Fonts with CSS.如果您使用 Vue,则需要vue-fontawesome包或带有 CSS 的 Web 字体。

The SVG core package is helpful and recommended in the following cases: SVG 核心包在以下情况下很有帮助和推荐:

  • to subset a large number of icons into only the icons that you are using将大量图标子集到仅您正在使用的图标中
  • as base libraries for larger integrations with tools like React, Angular, Vue, or Ember (in fact our own components use these packages)作为与 React、Angular、Vue 或 Ember 等工具进行更大集成的基础库(实际上我们自己的组件使用这些包)
  • as CommonJS/ES6 Modules bundling tool like Webpack, Rollup, or Parcel作为 CommonJS/ES6 模块捆绑工具,如 Webpack、Rollup 或 Parcel
  • as UMD-style loader library like RequireJS像 RequireJS 这样的 UMD 风格的加载器库
  • directly on the server with CommonJS (see our Server Side Rendering docs使用 CommonJS 直接在服务器上(请参阅我们的服务器端渲染文档

“i”标签在火灾转向 svg 后注释掉,使用一些 wrap <span v-if="marked"><i class="far fa-check-square"></i></span>

This answer applies to using Font Awesome with SVG.此答案适用于将 Font Awesome 与 SVG 一起使用。

For some reason, you need to wrap the i tag twice.出于某种原因,您需要将i标签包装两次。 For example, instead of this:例如,而不是这个:

<div v-if="condition">
  <i class="fal fa-caret-left"></i>
</div>
<div v-else>
  <i class="fas fa-caret-left"></i>
</div>

do this:做这个:

<template v-if="condition">
  <div>
    <i class="fal fa-caret-left"></i>
  </div>
</template>
<template v-else>
  <div>
    <i class="fas fa-caret-left"></i>
  </div>
</template>

Not entirely sure why you need to wrap it twice since I'd think you decouple the i tag enough by wrapping it once, but it worked for me this way so there's apparently something else going on.不完全确定为什么需要将其包装两次,因为我认为您通过包装一次来充分解耦i标签,但它以这种方式对我有用,所以显然还有其他事情发生。

Also, keep in mind that the inner div can't be replaced with template for obvious reasons (template tags do not get rendered).另外,请记住,由于明显的原因,内部div不能用template替换(模板标签不会被渲染)。

The Font Awesome library you used doesn't know about Vue.您使用的 Font Awesome 库不了解 Vue。 It takes the <i> that you wrote and turns it into an <svg> , and at that point, it's been stolen from Vue.它将您编写的<i>转换为<svg> ,此时它已从 Vue 中窃取。 Vue no longer controls it. Vue 不再控制它。 The answer that Dialog gave was a good one: wrap it with a <span> . Dialog 给出的答案很好:用<span>包裹它。 But then you pointed out another scenario it doesn't work for.但是后来你指出了另一种情况它不起作用。

To solve your scenario where wrapping with a <span> still doesn't work, use key="fa-sort-up" .要解决使用<span>包装仍然不起作用的情况,请使用key="fa-sort-up" This will force Vue to re-render the wrapper, at which point Font Awesome will update the icon.这将强制 Vue 重新渲染包装器,此时 Font Awesome 将更新图标。 Here's the updated jsFiddle for your example:这是您示例的更新后的 jsFiddle

<span key="fa-sort-up" v-if="sort && descending"><i class="fas fa-sort-up"></i></span>
<span key="fa-sort-down" v-else-if="sort"><i class="fas fa-sort-down"></i></span>
<span key="fa-sort" v-else><i class="fas fa-sort"></i></span>

You can use anything you want for the key, as long as it's unique.您可以使用任何您想要的密钥,只要它是唯一的。

Toggle a checkbox in vue with FontAwesome使用 FontAwesome 在 vue 中切换复选框

<style>
  .fa-check-square::before {
    color: green; 
  }
</style>

<script>
  Vue.component('some',
    {
      data: 
        function() {
          return{
            isclick: false
          }
        },
      methods: {
        isClicked: function() {
          this.isclick = !this.isclick;
        }
      },
      template: '<div id="test" v-on:click="isClicked">' +
        '<i v-if="isclick" class="fa fa-check-square" style="font-size: 40px;"></i>' +
        '<i v-if="!isclick" class="far fa-square" style="font-size: 40px;"></i>' +
        '</div>'
    });

</script>

<div id="componentsDemo">
  <some></some>
  <some></some>
  <some></some>
  <some></some>
</div>

<script>
  new Vue({ el: '#componentsDemo' });
</script>

I fixed this by creating a template for each icon, then loading either template conditionally based on a boolean.我通过为每个图标创建一个模板来解决这个问题,然后根据布尔值有条件地加载任一模板。

Here's my main template:这是我的主要模板:

 <div v-if="minimised"> <maximise-icon> </maximise-icon> </div> <div v-if="!minimised"> <minimise-icon> </minimise-icon> </div>

Then just create the icons like so:然后像这样创建图标:

 FontAwesomeConfig = { autoReplaceSvg: 'nest' }//important addition! Vue.component('minimise-icon', { template: ` <i class="fas fa-minus "></i> ` }) Vue.component('maximise-icon', { template: ` <i class="fas fa-plus "></i> ` })

If there's a more elegant way I'm all ears!如果有更优雅的方式,我会全神贯注!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM