【问题标题】:How to add a loading icon while searching? (Vue.js 2)如何在搜索时添加加载图标? (Vue.js 2)
【发布时间】:2017-07-16 04:39:06
【问题描述】:

我的组件是这样的:

<template>
    ...
        <input type="text" class="form-control" v-model="rawFilter" placeholder="Search" @keyup="getPlayers">
    ...
</template>

<script>
    import _ from 'lodash'
    ...
    export default {
        ...
        data() {
            return{
                msg:'hello vue',
                rawFilter:'',
                loading:false
            }
        },
        ...
        methods: {
            getPlayers: _.debounce(function(e) {
                const text = e.target.value.trim()
                this.$store.dispatch('getPlayers', {
                  q: text
                })
            },1000),
            ...
        }
    }
</script>

当我搜索时,在显示数据之前,我想添加一个加载图标

如何在 vue.js 2 中做到这一点?

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    为了可用性,我建议使用一个有自己的 vuex 状态的加载器。

    1. 这将允许您从任何组件对其进行控制。
    2. 您可以通过简单的函数调用轻松使用它。
    3. 自然避免道具和事件。

    首先定义你需要这个特定加载器的位置:

    1. 是否用于所有 api 调用?
    2. 一些浏览器密集型任务(例如处理加载的文件)。
    3. 或更具体的性质(可能仅在用户尝试登录时显示加载器)

    如果您的加载程序没有像案例 1 那样紧密耦合到任何组件。那么将您的加载程序保留在您的主 vue 文件中会更有意义(如果您使用的是 vue-cli,然后是 App.vue)

    类似这样的:

    <template>
      <div id="app">
        <loader></loader>
        <router-view></router-view>
      </div>
    </template>
    
    <script>
    import Loader from './components/shared/loader/Loader'
    
    export default {
      name: 'app',
      components: {
        Loader
      }
    }
    </script>
    

    这样,您不必在每个其他组件文件中添加 loader.vue。 但首先,我将向您展示我正在使用的加载器组件和存储。

    <template>
      <div class='loader-container' :class='{"show": show, "hidden": !show}'>
        <div class="curved-div">
          <div class="colour-magic">
            <i class='fa fa-circle-o-notch rotate'></i>
          </div>
          <div class="loading">
            {{ loading }}
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import { mapGetters } from 'vuex'
    import * as NameSpace from '../../../store/NameSpace'
    
    export default {
      data () {
        return {
          loading: 'Loading...'
        }
      },
      computed: {
        ...mapGetters({
          show: NameSpace.GET_LOADER_STATE
        })
      }
    }
    </script>
    
    <style scoped>
    .loader-container {
      position: fixed;
      width: 100%;
      height: 100%;
      background: rgba(0,0,0,0.8);
    }
    
    .curved-div {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translateX(-50%);
      border-radius: .3rem;
      width: 20rem;
      padding:1rem;
      background: white;
      box-shadow: 0 0 .1rem #fefefe;
    }
    
    .curved-div > * {
      display: inline-block;
    }
    
    .rotate {
      border-radius: 50%;
      padding: .5rem;
      animation-name: rotate;
      animation-duration: .7s;
      animation-iteration-count: infinite;
      animation-delay: 0s;
    }
    
    .loading {
      text-align: center;
      width: 12rem;
      font-size: 1.8rem;
    }
    
    .show {
      visibility: visible;
      opacity: 1;
      z-index: 1;
      transition: opacity 0.5s ease-out, visibility 0.5s ease-out, z-index 0.5s ease-out;
    }
    
    .hidden {
      opacity: 0;
      visibility: hidden;
      z-index: 0;
      transition: opacity 0.5s ease-out, visibility 0.5s ease-out, z-index 0.5s ease-out;
    }
    
    @keyframes rotate {
      0% {
        transform: rotateZ(0deg);
      }
      100% {
        transform: rotateZ(360deg);
      }
    }
    
    .colour-magic {
      animation-name: colorMagic;
      animation-duration: 20s;
      animation-iteration-count: infinite;
      animation-delay: 0s;
    }
    
    @keyframes colorMagic {
      0% { color: rgb(179,10,10); }
      10% { color: rgb(227,132,22); }
      20% { color: rgb(164,153,7); }
      30% { color: rgb(26,171,19); }
      40% { color: rgb(19,144,177); }
      50% { color: rgb(14,16,221); }
      60% { color: rgb(27,9,98); }
      70% { color: rgb(58,11,111); }
      80% { color: rgb(126,14,129); }
      90% { color: rgb(208,19,121); }
      100% { color: rgb(198,18,18); }
    }
    </style>
    

    请注意,我正在为加载程序使用 font-awesome。

    这里是商店:

    import * as NameSpace from '../NameSpace'
    // you can also use the namespace: true in your store and eliminate the need of NameSpace.js    
    
    const state = {
      [NameSpace.LOADER_STATE]: false
    }
    
    const getters = {
      [NameSpace.GET_LOADER_STATE]: state => {
        return state[NameSpace.LOADER_STATE]
      }
    }
    
    const mutations = {
      [NameSpace.MUTATE_LOADER_STATE]: (state, payload) => {
        state[NameSpace.LOADER_STATE] = payload
      }
    }
    
    const actions = {
      [NameSpace.LOADER_SHOW_ACTION]: ({ commit }, payload) => {
        commit(NameSpace.MUTATE_LOADER_STATE, payload)
      }
    }
    
    export default {
      state,
      getters,
      mutations,
      actions
    }
    

    使用示例:

    // This is not a .vue file it is a .js file, therefore a different way of using the store.
    import Vue from 'vue'
    import * as NameSpace from 'src/store/NameSpace'
    import loaderState from 'src/store/modules/loader'
    
    /**
    * Pass the mutation function to reduce the text length
    * This function can now be used in the api calls to start/stop the loader
    * as the api starts and finishes.
    */
    let loaderSwitch = loaderState.mutations[NameSpace.MUTATE_LOADER_STATE].bind(null, loaderState.state)
    
    login (username, password) {
      loaderSwitch(true)
      return new Promise((resolve, reject) => {
        SomeEndpoint.logIn(username, password, {
          success (user) {
            loaderSwitch(false)
            resolve(user.attributes)
          },
          error (user, error) {
            loaderSwitch(false)
            reject(errorHelper(error.code))
          }
        })
      })
    

    现在,无论使用哪个组件登录,加载器组件都不需要保留在那里。

    【讨论】:

      【解决方案2】:

      你只需要将它附加到一个标志并使用v-if,如果你正在使用vue资源,你可以在before回调中将loading标志设置为true并将其设置回false收到回复后:

      Vue 实例

        methods: {
          loadData() {
            this.$http.get('/search', {
              before: () => {
                this.loading = true;
              }
            }).then(response => {
              // Deal with response
            }).then(() => {
                //set loading flag to false
                this.loading = false;
            })
          }
        },
        data: {
          loading: false
        }
      

      HTML

      <div id="app">
        <button @click="loadData">
          Get Data
        </button>
      
        <!-- Only show if loading is true -->
        <div v-if="loading" v-cloak>
          <i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i>
          <span>Loading...</span>
        </div>
      </div>
      

      这是 JSFiddle:https://jsfiddle.net/hyeycoan/

      【讨论】:

        【解决方案3】:

        您可以在模板上添加一个加载 div,并根据loading 标志切换它的显示。像这样的

        new Vue({
          el: '#app',
          data: {
            show: true,
        	isLoading: false,  
          },
        	methods:{
        		loadData: function(){
        			this.isLoading = true;
        			setTimeout(function(){
        				this.isLoading = false;
        			}.bind(this),1000);
        		}
        	}
        })
        .loading{
        	display: none;
        	position: absolute;
            width: 100%;
            height: 100%;
            top: 0;
            background: rgba(128, 128, 128, 0.5);
        }
        .loading.show{
        	display: initial;
        }
        <!DOCTYPE html>
        <html>
        <head>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width">
          <title>JS Bin</title>
        </head>
        <body>
        <div id="app">
        	<div class="loading" v-bind:class="{ show: isLoading }">
        		<span>Loading</span>
        	</div>
        	<button @click="loadData">Load</button>
        </div>	
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
        </body>
        </html>

        您可以使用 css 使加载指示器漂亮,或者您可以使用现有的,例如您可以使用 http://tobiasahlin.com/spinkit/http://loading.io/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-18
          • 1970-01-01
          相关资源
          最近更新 更多