美文网首页vue
添加Font Awesome到Vue.js应用程序

添加Font Awesome到Vue.js应用程序

作者: 开心人开发世界 | 来源:发表于2019-11-13 16:24 被阅读0次

    Font Awesome是一个流行的CSS库,用于向Web应用程序添加图标。它可以作为原始CSS包提供,也有主要前端框架的版本。对于Vue.js,我们可以使用vue-fontawesome在我们的应用程序中添加图标。

    在本文中,我们将制作一个购物清单应用程序,用户可以在其中使用MealDB API搜索想要烹饪的菜肴,并从中添加所需的食材。我们将在按钮上添加涟漪效果,并在鼠标指针移到按钮上并列出项目时使其突出显示。

    要开始构建应用程序,我们可以通过运行来运行Vue CLI npx @vue/cli grocery-app。在向导中,选择“手动选择功能”,然后选择Babel,Vuex,Vue Router和CSS Preprocessor。

    接下来,我们安装一些其他软件包。我们需要Axios来发出HTTP请求,需要BootstrapVue来样式化,需要Vue Font Awesome来添加图标,需要Vee-Validate来进行表单验证,并需要Vue Ripple指令来增加波纹效果。要安装它们,我们运行:

    npm i axios @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/vue-fontawesome axios bootstrap-vue vee-validate vue-ripple-directive
    

    安装所有软件包后,我们可以构建应用程序。我们首先添加用于添加食品的表格。GroceryForm.vue在components文件夹中创建一个文件并添加:

    <template>
      <div>
        <ValidationObserver ref="observer" v-slot="{ invalid }">
          <b-form @submit.prevent="onSubmit" novalidate>
            <b-form-group label="Search for Dish and Add Ingredients From Result">
              <ValidationProvider name="keyword" rules="required" v-slot="{ errors }">
                <b-form-input
                  type="text"
                  :state="errors.length == 0"
                  v-model="form.keyword"
                  required
                  placeholder="Search for Dish and Add Ingredients From Result"
                  name="keyword"
                ></b-form-input>
                <b-form-invalid-feedback :state="errors.length == 0">{{errors.join('. ')}}</b-form-invalid-feedback>
              </ValidationProvider>
            </b-form-group>
    <b-button v-ripple.mouseover.500 type="submit" variant="primary">Find Dishes</b-button>
          </b-form>
        </ValidationObserver>
    <b-card v-for="(m, i) in meals" :title="m.strMeal" :key="i">
          <b-card-text>
            <b-list-group>
              <b-list-group-item
                v-for="(key, index) in Object.keys(m).filter(k => k.includes('strIngredient') && m[k])"
                :key="index"
                v-ripple.mouseover="'rgba(255, 255, 255, 0.35)'"
              >{{m[key]}}</b-list-group-item>
            </b-list-group>
          </b-card-text>
          <b-button
            v-ripple.mouseover.500
            variant="primary"
            @click="addToGroceryList(i)"
          >Add Ingredients to Grocery List</b-button>
        </b-card>
    <h4>Your Chosen Ingredients</h4>
        <b-list-group>
          <b-list-group-item v-for="(ingredient, i) of ingredients" :key="i" v-ripple.mouseover>
            {{ingredient}}
            <font-awesome-icon icon="times" class="float-right" @click="removeIngredient(i)" />
          </b-list-group-item>
        </b-list-group>
    <br />
    <b-button v-ripple.mouseover.500 type="button" variant="primary" @click="saveGroceryList()">Save</b-button>
        <b-button v-ripple.mouseover.500 type="reset" variant="danger" @click="cancel()">Cancel</b-button>
      </div>
    </template>
    <script>
    import { requestsMixin } from "@/mixins/requestsMixin";
    import { faTimes } from "@fortawesome/free-solid-svg-icons";
    export default {
      name: "GroceryForm",
      mixins: [requestsMixin],
      components: {
        faTimes
      },
      data() {
        return {
          form: {},
          meals: [],
          ingredients: []
        };
      },
      computed: {
        grocery() {
          return this.$store.state.grocery;
        }
      },
      methods: {
        cancel() {
          this.$emit("cancelled");
        },
        async onSubmit() {
          const isValid = await this.$refs.observer.validate();
          if (!isValid) {
            return;
          }
          const { data } = await this.findDishes(this.form.keyword);
          this.meals = data.meals;
        },
        addToGroceryList(index) {
          const meal = this.meals[index];
          const keys = Object.keys(meal).filter(
            k => k.includes("strIngredient") && meal[k]
          );
          const ingredients = keys.map(k => meal[k]);
          this.ingredients = Array.from(
            new Set(this.ingredients.concat(ingredients))
          );
        },
        removeIngredient(index) {
          this.ingredients.splice(index, 1);
        },
        async saveGroceryList() {
          const payload = { ingredients: this.ingredients };
          if (!this.groceryListId) {
            await this.addGrocery(payload);
          } else {
            await this.editGrocery(payload);
          }
          const { data } = await this.getGrocery();
          this.$store.commit("setGrocery", data);
          this.$emit("saved");
        }
      },
      watch: {
        grocery: {
          handler(val) {
            this.ingredients = val.ingredients || [];
          },
          deep: true,
          immediate: true
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    .delete {
      cursor: pointer;
    }
    </style>
    

    该表单使用户可以使用给定的关键字搜索菜肴,然后返回菜肴的配料列表,然后用户可以将其添加到已删除重复项的列表中。我们使用Vee-Validate来验证我们的输入。我们使用ValidationObserver组件来监视组件内部表单的有效性,并ValidationProvider检查组件内部输入的输入值的验证规则。在中ValidationProvider,我们有用于文本输入字段的BootstrapVue输入。在b-form-input组件中。我们还添加了Vee-Validate验证,以确保用户在提交之前填写了日期。我们keywordrules道具中设置了必填字段,以便用户在搜索之前必须输入内容。

    我们在表单底部的列表中有包含成分列表的按钮,用于删除每个成分。这就是为什么我们在faTimes此处导入图标的原因,该图标显示为“ x”,以便用户可以单击并删除它。如果单击该元素,removeIngredient则调用该函数。然后,用户单击表单底部的“保存”,然后saveGroceryList调用该函数,将列表保存到我们的后端。

    在此组件中,我们还有一个watch块来监视grocery值,该块是从必须构建的Vuex存储中获得的。随着grocery值的更新,我们将获得最新的配料清单。

    我们使用Vue Ripple将波纹效果应用到按钮和列表行。v-ripple.mouseover.500表示使用此指令将鼠标悬停在元素上时,纹波效果将显示500毫秒。要为波纹效果应用不同于默认颜色的颜色,我们还可以在伪指令的参数中指定颜色值,就像in中一样v-ripple.mouseover=”’rgba(255, 255, 255, 0.35)’”。波纹将具有指定的颜色。

    我们使用样式设置元素以删除表单,cursor:pointer因此鼠标图标将显示一只手而不是箭头。

    接下来,我们创建一个mixins文件夹并添加requestsMixin.js。在文件中:

    const APIURL = "http://localhost:3000";
    const MEAL_DB_URL = "https://www.themealdb.com/api/json/v1/1/search.php?s=";
    const axios = require("axios");
    export const requestsMixin = {
      methods: {
        getGrocery() {
          return axios.get(`${APIURL}/grocery`);
        },
    addGrocery(data) {
          return axios.post(`${APIURL}/grocery`, data);
        },
    editGrocery(data) {
          return axios.put(`${APIURL}/grocery`, data);
        },
    findDishes(keyword) {
          return axios.get(`${MEAL_DB_URL}${keyword}`);
        }
      }
    };
    

    这些是我们在组件中使用的功能,用于发出HTTP请求以获取并保存我们的食品杂货数据并在Meal DB API中搜索菜肴。

    接下来的中Home.vue,将现有代码替换为:

    <template>
      <div class="page">
        <h1 class="text-center">Grocery List</h1>
        <b-button-toolbar class="button-toolbar">
          <b-button
            v-ripple.mouseover.500
            @click="openAddModal()"
            variant="primary"
          >Add Ingredients to Grocery List</b-button>
        </b-button-toolbar>
    <h4>Your Grocery List</h4>
        <b-list-group>
          <b-list-group-item
            v-for="(ingredient, i) of grocery.ingredients"
            :key="i"
            v-ripple.mouseover="'rgba(255, 255, 255, 0.35)'"
          >
            {{ingredient}}
            <font-awesome-icon icon="times" class="float-right" @click="removeIngredient(i)" />
          </b-list-group-item>
        </b-list-group>
    <b-modal id="add-modal" title="Add Ingredients to Grocery List" hide-footer>
          <GroceryForm
            @saved="closeModal()"
            @cancelled="closeModal()"
            :edit="false"
            :groceryListId="grocery.id"
          />
        </b-modal>
      </div>
    </template>
    <script>
    // @ is an alias to /src
    import GroceryForm from "@/components/GroceryForm.vue";
    import { requestsMixin } from "@/mixins/requestsMixin";
    export default {
      name: "home",
      components: {
        GroceryForm
      },
      mixins: [requestsMixin],
      computed: {
        grocery() {
          return this.$store.state.grocery;
        }
      },
      data() {
        return {
          ingredients: []
        };
      },
      beforeMount() {
        this.getGroceryList();
      },
      methods: {
        openAddModal() {
          this.$bvModal.show("add-modal");
        },
        closeModal() {
          this.$bvModal.hide("add-modal");
        },
        async getGroceryList() {
          const { data } = await this.getGrocery();
          this.$store.commit("setGrocery", data);
        },
        async removeIngredient(index) {
          this.ingredients.splice(index, 1);
          const payload = { id: this.grocery.id, ingredients: this.ingredients };
          await this.editGrocery(payload);
          const { data } = await this.getGrocery();
          this.$store.commit("setGrocery", data);
        }
      },
      watch: {
        grocery: {
          handler(val) {
            this.ingredients = val.ingredients || [];
          },
          deep: true,
          immediate: true
        }
      }
    };
    </script>
    };
    

    这是主页的组件。我们在这里显示从后端获得的所选配料列表。另外,我们还有一个按钮来打开一个模式,该模式与GroceryForm我们先前创建的一起添加到购物清单中。获取数据是在getGroceryList函数中完成的。我们将获得的数据放在函数的最后一行中的Vuex存储中。

    此外,我们还允许用户使用该removeIngredient功能删除保存在此页面列表中的成分。我们调用从存储中的状态获得splicethis.ingredients数组,grocery然后将其设置为handlerwatch块中的当前值grocery

    同样,我们使用Vue Ripple将波纹效果应用到按钮和列表行。v-ripple.mouseover.500显示按钮和按钮500毫秒的涟漪效应v-ripple.mouseover=”’rgba(255, 255, 255, 0.35)’”。像我们在中所做的那样,涟漪图将具有在列表项中指定的颜色GroceryForm

    接下来的App.vue,我们将现有代码替换为:

    <template>
      <div id="app">
        <b-navbar toggleable="lg" type="dark" variant="info">
          <b-navbar-brand to="/">Grocery List App</b-navbar-brand>
    <b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
    <b-collapse id="nav-collapse" is-nav>
            <b-navbar-nav>
              <b-nav-item to="/" :active="path  == '/'">Home</b-nav-item>
            </b-navbar-nav>
          </b-collapse>
        </b-navbar>
        <router-view />
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          path: this.$route && this.$route.path
        };
      },
      watch: {
        $route(route) {
          this.path = route.path;
        }
      }
    };
    </script>
    <style lang="scss">
    .page {
      padding: 20px;
    }
    button,
    .btn.btn-primary {
      margin-right: 10px !important;
    }
    .button-toolbar {
      margin-bottom: 10px;
    }
    </style>
    

    这会将Bootstrap导航栏添加到页面顶部,并router-view显示我们定义的路线。本style部分不受范围限制,因此样式将在全球范围内应用。在.page选择器中,我们向页面添加一些填充。我们在剩余style代码中为按钮添加一些填充。

    然后在中main.js,将现有代码替换为:

    import Vue from "vue";
    import App from "./App.vue";
    import router from "./router";
    import store from "./store";
    import BootstrapVue from "bootstrap-vue";
    import "bootstrap/dist/css/bootstrap.css";
    import "bootstrap-vue/dist/bootstrap-vue.css";
    import { ValidationProvider, extend, ValidationObserver } from "vee-validate";
    import { required, min_value, max_value } from "vee-validate/dist/rules";
    import Ripple from "vue-ripple-directive";
    import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
    import { library } from "@fortawesome/fontawesome-svg-core";
    import { faTimes } from "@fortawesome/free-solid-svg-icons";
    library.add(faTimes);
    Vue.component("font-awesome-icon", FontAwesomeIcon);
    Vue.directive("ripple", Ripple);
    extend("required", required);
    Vue.component("ValidationProvider", ValidationProvider);
    Vue.component("ValidationObserver", ValidationObserver);
    Vue.use(BootstrapVue);
    Vue.config.productionTip = false;
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount("#app");
    

    我们在此处添加了我们需要的所有库,包括BootstrapVue JavaScript和CSS,Vee-Validate组件以及验证规则,Vue-Ripple库和Vue Font Awesome软件包。使用Vue Font Awesome faTimeslibrary.add功能将其添加到我们的应用程序中,以便我们可以在我们的应用程序中使用它。

    router.js我们将现有代码替换为:

    import Vue from "vue";
    import Router from "vue-router";
    import Home from "./views/Home.vue";
    Vue.use(Router);
    export default new Router({
      mode: "history",
      base: process.env.BASE_URL,
      routes: [
        {
          path: "/",
          name: "home",
          component: Home
        }
      ]
    });
    

    这包括我们路线中的主页,以便用户可以看到该页面。

    在中store.js,我们将现有代码替换为:

    import Vue from "vue";
    import Vuex from "vuex";
    Vue.use(Vuex);
    export default new Vuex.Store({
      state: {
        grocery: {}
      },
      mutations: {
        setGrocery(state, payload) {
          state.grocery = payload;
        }
      },
      actions: {}
    });
    

    这增加了我们的杂货店状态到店,所以我们可以观察它在computedGroceryFormHomePage组件。我们具有setGrocery更新grocery状态的功能,可以this.$store.commit(“setGrocery”, data);像在GroceryForm和中那样通过调用在组件中使用它HomePage

    最后,index.html我们将现有代码替换为:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width,initial-scale=1.0" />
        <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
        <title>Grocery List App</title>
      </head>
      <body>
        <noscript>
          <strong
            >We're sorry but vue-ripple-tutorial-app doesn't work properly without
            JavaScript enabled. Please enable it to continue.</strong
          >
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    

    这将更改我们应用的标题。

    经过所有艰苦的工作,我们可以通过运行来启动我们的应用程序npm start

    要开始后端,我们首先json-server运行运行该软件包npm i json-server。然后,转到我们的项目文件夹并运行:

    json-server --watch db.json
    

    在中db.json,将文本更改为:

    {
      "grocery": {}
    }
    

    因此,我们groceryrequests.js可用项中定义了端点。

    经过所有的努力,我们得到:

    翻译自:https://levelup.gitconnected.com/how-to-add-font-awesome-icons-to-your-vue-js-app-3641831887fd

    相关文章

      网友评论

        本文标题:添加Font Awesome到Vue.js应用程序

        本文链接:https://www.haomeiwen.com/subject/vqxkictx.html