Vue-multiselect不一致的反应选项

时间:2017-02-03 22:30:09

标签: vue.js vue-component laravel-spark

所以我正在使用Laravel Spark构建一个应用程序,因此在我参与的时候借此机会学习一些Vue.js。

我需要更长的时间来理解它,但是我几乎让Vue-multiselect为一组选项工作,所选的选项通过get请求检索然后更新。< / p>

我有这么远的方式可能远远不是最好的,所以忍受我,但它似乎只加载选定的选项~60%的时间。要清楚 - 控制台中没有记录任何警告/错误,如果我检查网络选项卡,获取Tutor仪器的请求总是成功返回相同的结果......

我已经宣布了一个全局数组:

var vm = new Vue({
    data: {
        tutorinstruments: []
    }
});

我的主要组件然后发出请求并更新变量:

    getTutor() {
        this.$http.get('/get/tutor')
            .then(response => {
                this.tutor = response.data;
                this.updateTutor();
            });
    },

    updateTutor() {
        this.updateTutorProfileForm.profile = this.tutor.profile;
        vm.tutorinstruments = this.tutor.instruments;
    },

我从Vue-multiselect获得的自定义多重选择然后获取所有可用乐器并更新可用乐器以及所选乐器:

    getInstruments() {
        this.$http.get('/get/instruments')
            .then(response => {
                this.instruments = response.data;
                this.updateInstruments();
            });
    },

    updateInstruments() {
        this.options = this.instruments;
        this.selected = vm.tutorinstruments;
    },

可用选项始终

Here's a YouTube link to how it looks if you refresh the page over and over

我愿意接受任何建议,欢迎提供帮助!

2 个答案:

答案 0 :(得分:1)

您的全局数组var vm = new Vue({...})是一个单独的Vue实例,它位于处理用户界面的主Vue实例之外。

这就是您在组件中同时使用thisvm的原因。在您的方法中,this指向处理用户界面的Vue实例,而vm指向您在Vue实例外部初始化的全局数组。

请再次查看本指南页面:https://vuejs.org/v2/guide/instance.html

如果您查看初始化所有Vue功能的生命周期图,您会注意到它在很多地方提到 Vue实例。这些功能(反应性,数据绑定等)旨在在Vue实例中运行,而不是跨多个实例运行。当时机合适时,它可能会偶尔工作一次,但不能保证工作。

要解决此问题,您可以重新设计应用以使用单个Vue实例来处理用户界面和数据。

理想情况下,我希望您的tutorinstruments能够加载到初始化您应用的代码中(使用根组件中的mounted挂钩),并存储在 Vuex状态。数据处于 Vuex状态后,所有组件都可以访问该数据。

Vuex ref:https://vuex.vuejs.org/en/intro.html

希望它有所帮助!我知道我没有直接解决你的问题。如果您无法将应用程序重组为单个Vue实例,我们可以等待更直接的答案。

答案 1 :(得分:0)

Mani写的是100%正确的,我之所以喜欢,是因为我刚刚用PHP和Vue完成了一个非常大型的项目,我觉得自己很适合给你我在构建PHP(服务器端)网站的过程中学到了一些建议/知识,但是在前端模板中添加了Vue(客户端)。

这可能比您的多项选择问题的范围要大一些,但我也会为您提供一个坚实的起点。

首先,您需要确定Web应用程序中的哪一个将要进行路由(当用户进入处理流量的页面时),因为这将决定您要使用Vue的方式。假设出于讨论目的,您决定使用PHP进行身份验证(如果有登录名),但是您将在前端使用Vue处理路由。在这种情况下,您将要确定有一个主要的Vue实例,并或多或少地从Vue Router设置了类似于此示例的内容,并假装HTML文件是Web根目录中的PHP index.php,这应该最终,它是模板所需要的唯一.php文件,我让它处理了所有标头元数据和页脚版权内容,实际上,您基本上只希望使用ID应用程序一个div。

然后,您只需使用vue路由器和路由即可为所有页面加载到vue组件中(每个页面一个页面或页面类别都可以轻松工作)。如果您在主应用程序中查找并使用动态组件来计算积分,就可以得到奖励点。这可以根据路由来延迟页面组件中的加载,从而使包很小。

*提示您还需要一个带有babel的polyfill来执行此操作 模板

<Component :is="dynamicComponent"/>

脚本

components: {
  Account: () => import('./Account/Account.vue'),
  FourOhFour: () => import('../FourOhFour.vue')
},
computed: {
  dynamicComponent() {
    return this.$route.name;
  }
},

现在我们到了这里,我们可以解决您的多项选择问题(这基本上也将帮助您了解一种将在线找到的Vue组件加载到网站中的简便方法)。在您访问的某个页面组件中,当有人访问路由时,您说/ tutor(我也通过将本地信息本地化,然后使用props,meta字段和路由器防护来将我的身份验证信息从PHP传递到了我的路由中,这些都在该文档中因此,如果您想探索,我会留给您)在tutor.vue上,我们将您的页面组件称为您要在multiselect中调用的位置。同样在这一点上,我们仍然连接到我们的主要Vue实例,因此,如果您要引用它或从tutor.vue引用路由器,则可以使用Vue API几乎可以解决所有Vue或vm的问题。但是,整洁的事情是在Vue外部添加到它的主JS文件/模块中之后,您仍然可以使用API​​在加载主实例并执行所需的任何操作之后,将其引用到Vue中。组件或多或少。

这是我从现在开始处理添加外部组件,将它们包装在您控制的另一个组件中并使它们成为页面组件的子组件的方式。这是一个非常简单的示例,其中的multiselect假装其父节点为tutor.vue。

我还在运行全局事件总线,以为您可能喜欢这个主意 https://alligator.io/vuejs/global-event-bus/

tutor.vue

<template>
  <div
    id="user-profile"
    class="account-content container m-top m-bottom"
  >

    <select-input
      :saved-value="musicPreviouslySelected"
      :options="musicTypeOptions"
      :placeholder="'Choose an your music thing...'"
      @selected="musicThingChanged($event)"
    />

  </div>
</template>

<script>
import SelectInput from './SelectInput';
import EventBus from './lib/eventBus';

export default {
    components: {
        SelectInput
    },

    data() {
        return {
            profileLoading: true,
            isFullPage: false,
            isModalActive: false,
            slackId: null,
            isActive: false,
            isAdmin: false,
            rep: {
                id: null,
                status: '',
                started: '',
                email: '',
                first_name: '',
            },
            musicTypeOptions: []
        };
    },

    created() {
        if (org.admin) {
            this.isAdmin = true;
        }
        this.rep.id = parseInt(this.$route.params.id);
        this.fetchData();
    },

    mounted() {
        EventBus.$on('profile-changed', () => {
          // Do something because something happened somewhere else client side.
        });
    },

    methods: {
      fetchData() {
        // use axios or whatever to fetch some data from the server and PHP to 
        // load into the page component so say we are getting the musicTypeOptions 
        // which will be in our selectbox.
      },

      musicThingChanged(event) {
        // We have our new selection "event" from multiselect so do something
      }
    }
};
</script>

这是我们的子级Multiselect包装器SelectInput.vue

<template>
  <multiselect
    v-model="value"
    :options="options"
    :placeholder="placeholder"
    label="label"
    track-by="value"
    @input="inputChanged" />
</template>

<script>
import Multiselect from 'vue-multiselect';

export default {
    components: { Multiselect },
    props: {
        options: {
            type: [Array],
            default() {
                return [];
            }
        },

        savedValue: {
            type: [Array],
            default() {
                return [];
            }
        },

        placeholder: {
            type: [String],
            default: 'Select Option...'
        }
    },

    data() {
        return {
            value: null
        };
    },

    mounted() {
        this.value = this.savedValue;
    },

    methods: {
        inputChanged(selected) {
            this.$emit('selected', selected.value);
        }
    }
};
</script>

<style scoped>
@import '../../../../../node_modules/vue-multiselect/dist/vue-multiselect.min.css';
</style>

现在,您可以确保自己正在管理页面的生命周期以及何时拥有什么数据,可以等到获得musicTypeOptions,然后将其传递给SelectInput组件,该组件将依次设置Multiselect或任何其他组件,然后通过this。$ emit('hihiwhatever')处理返回的数据,该值由@hihiwhatever在模板中的组件上拾取,该模板调用一个函数,现在您可以使用新选择并传递任何内容与SelectInput和MultiSelect不同的数据将始终保持同步。

现在,根据经验我最后的建议。抵制诱惑,因为您每天阅读650次,似乎是正确的做法,并在这样的设置中使用Vuex。您已经有PHP和数据库,就像在Node.js中使用Vuex一样使用它,而您不是拥有非常出色的PHP服务器端存储,而是尝试在前端Vuex中管理数据,而同时由PHP和数据库服务器端管理的数据也将以灾难而告终,一旦您开始让多个用户登录,弄乱了来自PHP服务器端的Vuex数据,您将无法保持单点真相。如果您没有服务器端数据库,则可以使用Vuex,但要避免头痛,请耐心等待,直到您100%使用Node.js。

如果您要管理某些数据客户端的时间长于页面视图的生命周期,请使用https://github.com/gruns/ImmortalDB之类的东西,它对我非常有用。

对不起,这变成了博客文章哈哈,但我希望它可以帮助某人节省几个星期。