【问题标题】:Vue2 + Vuex - not rendering array that is set successfully in storeVue2 + Vuex - 不渲染在存储中成功设置的数组
【发布时间】:2018-10-09 13:42:12
【问题描述】:

我正在尝试渲染 209,579 个选项,但我认为我没有正确使用 Vuex 生命周期 + axios

  • 我看到所有选项都通过 Vuex 在控制台中设置为商店状态。
  • 不显示错误
  • 选项为空且不呈现状态cityNamesarray
  • main.js 正在将 store 导出到所有组件

我认为我没有正确应用这个生命周期,我应该在这里使用 getter,有人可以为我的生命周期带来秩序吗?

store.js

import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';

Vue.use(Vuex);

export default new Vuex.Store({
state: {
        isTrue: true,
        cityNames: [],
    },

    getters:{
        getCityNames(state){
            return state.cityNames;
        }
    },
    mutations: {
        SetCityNames(state, cityNames){
            state.cityNames = cityNames
    },
    actions: {
        loadData({commit}){
            axios.get('http://localhost:3000/allCities')
                .then(function (response) {
                    commit('SetCityNames', response.data)
                }).catch(function (error) {
                    console.log(error);
            });

        }
    },
});

脚本

export default {
    name: "Weather",
    methods: {
        allCityNames() {
            this.$store.dispatch('loadData')
        }
    },
    created() {
        this.allCityNames();
    }
}

模板

<select>
    <option disabled value="">Please select one</option>
    <option v-for="cityName in $store.cityNames">{{cityName}}</option>
</select>

谢谢, 芽

【问题讨论】:

  • 看起来不错,但可能没有正确检测到数据的变化。也许试试state.cityNames = [...cityNames]

标签: vue.js vuejs2 vuex


【解决方案1】:

我已更改要从计算执行的代码,但发现错误(终于!)是:maximum stacksize exceeded,此时我明白 Vue 不允许我渲染如此庞大的数组(209,579项目)进入视野。

第一部分 - 代码更改:

我创建了一个 isLoaded 状态,一旦 axios 提交它的响应,它就会设置为 true

由于 axios 调用的异步性质,我仍然不确定这是否是最好的方法,它可能没有用 commit('SetCityNames', response.data); 完成,并且在调用提交之后,它会调用下一个:commit('changeLoadedState');

所以我已经添加到状态:isLoaded: false

添加了一个吸气剂:didItLoad(state){return state.isLoaded}

添加了一个突变:changeLoadedState(state){state.isLoaded = true}

在我的 axios 调用中添加了一个提交 (commit('changeLoadedState');):

loadData({commit}) {
            axios.get('http://localhost:3000/allCities')
                .then(function (response) {
                    commit('SetCityNames', response.data);
                    commit('changeLoadedState');
                }).catch(function (error) {
                console.log(error);
            });
        }

在我的组件中,我仍然在方法中调度 axios 调用,因为它首先被调用,并为渲染端添加了一个 computed 方法,如下所示:

computed:{
          isLoaded(){
              return this.$store.getters.didItLoad;
          },
            renderCities(){
                return this.$store.getters.getCityNames;

            }
        }

在我渲染的模板中,我首先检查我选择的加载状态,然后才填充选项:

<select v-if="isLoaded">
    <option disabled value="">Please select one</option>
    <option v-for="cityName in renderCities">{{cityName}}</option>
</select>

第二部分 - 更改有效负载大小

所以在设置好我的代码之后,我进入了我的节点快递服务器并更改了我的路由循环以停止在 1000 个项目上,一切都很好。

此时我很好奇如果我开始添加零会发生什么情况,所以在 10K 项目时,加载选项需要 1-2 秒,打开下拉菜单开始显示由于压力而出现延迟的迹象,在 50K 项目时打开下拉菜单大约需要 5 秒。

底线

问题不在于数组的大小,Vuex 的工作非常出色,在大约 800 毫秒内获得了 209,579 项数组,其中包括 Express.js 的后端解析(我的整个堆栈都是本地的,因此没有网络延迟)。

我将尝试创建一个自动完成功能,从第二个或第三个字符开始列出。

感谢回复的会员。

【讨论】:

    【解决方案2】:

    你有一个名为getCityNames的getter。它是$store.getters.getCityNames而不是$store.cityNames

    所以改变

    <option v-for="cityName in $store.cityNames">{{cityName}}</option>
    

    <option v-for="cityName in $store.getters.getCityNames">{{cityName}}</option>
    

    重构使用计算属性比在模板中内联更好。

    <option v-for="cityName in cityNames">{{cityName}}</option>
    
    //script
    computed: {
        cityNames() {
            return this.$store.getters.getCityNames;
        }
    }
    

    【讨论】:

    • 太好了,谢谢,等我回来试试看是否有效。总体而言,在选项下拉列表中填充 200k+ 是唯一的途径吗?也许在没有 200k 选项的情况下,使用 handleChange () 从商店自动完成是一个不错的选择。
    • @clusterBuddy 填充超过 20 万个选项看起来效果不佳,因为在 for 循环完成之前不会填充选项。如果您创建一个自定义组件,一次加载 50 个选项并延迟加载接下来的 50 个选项,那会更好。但这似乎也不好,因为谁将滚动浏览 200k 选项。因此,您最好结合一些搜索和自动完成功能来加载选项。就像在 vuetify 中所做的那样 - vuetifyjs.com/en/components/selects#example-custom-filter
    • 嘿vamsi,我已经按照你的建议进行了更改,但仍然没有收到选项表的渲染,因为我没有收到任何错误,有没有办法调试这个?
    • @clusterBuddy 你什么时候调用allCityNames 方法(填充你的getter)?也许您只需要在安装组件时从商店调用操作loadData,而不是在方法中......
    • @sovalina - 更改并放入安装的this.allCityNames(); 进行调度:this.$store.dispatch('loadData'),没有果汁:(
    猜你喜欢
    • 2019-10-27
    • 2021-12-22
    • 2019-02-19
    • 1970-01-01
    • 2017-04-04
    • 2018-01-10
    • 2020-03-26
    • 1970-01-01
    • 2021-09-07
    相关资源
    最近更新 更多