我现在面临一个巨大的问题,因为我有一个包含一个包含大量数据的列表的片段。我到现在为止的工作如下:

当用户单击按钮时,我将执行如下JavaScript文章:

function loadEvaluations() {

    $.ajax({
        url : "/evaluation/data",
        type : "POST",
        headers : createAuthorizationTokenHeader(),
        async : !1,
        data : {
            from: rangeFrom,
            to: rangeTo
        },
        success : function(data) {
            $("#portal_container").html(data);
        },
        error : function(data) {
            $("#portal_container").html(data);
        }
    });
}


在Spring后端中,我从数据库中选择数据,将其放入模型中并返回片段:

@RequestMapping(HelperUrls.URL_WEB_EVALUATION_DATA)
public String data(Model model, HttpServletRequest request,
        @RequestParam(value = Params.PARAM_FROM, required = true) long from,
        @RequestParam(value = Params.PARAM_TO, required = true) long to) {

    final IDM_USER user = this.idm_user_repository.findByEmail(request.getUserPrincipal().getName());

    if (user != null) {
        final int unit = user.getUnit();
        final Locale locale = LocaleContextHolder.getLocale();
        final String unitValue = HelperShortcuts.getUnitForShortcut(this.messageSource, locale, unit);

        Set<IDM_BREAD> breads = this.idm_bread_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_FOOD> foods = this.idm_food_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_INSULIN> insulins = this.idm_insulin_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_MEASURE> measures = this.idm_measure_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_MOOD> moods = this.idm_mood_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_NOTE> notes = this.idm_note_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_SPORT> sports = this.idm_sport_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);

        List<DatatransferListEntry> entries = new ArrayList<>();

        entries.addAll(breads);
        entries.addAll(foods);
        entries.addAll(insulins);
        entries.addAll(measures);
        entries.addAll(moods);
        entries.addAll(notes);
        entries.addAll(sports);
        entries = this.initHeaders(entries, locale);

        model.addAttribute(ReturnKeys.TIME, Helper.getDateTimePatternEvaluation(this.messageSource, locale, from, to));
        model.addAttribute(ReturnKeys.ENTRIES, entries);
        model.addAttribute(ReturnKeys.USER_UNIT_VALUE, unitValue);
    }

    return Htmls.WEB_FRAGMENT_EVALUATION_DATA_F;
}


片段中的内容如下所示:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<body>
    <div th:fragment="fragment_evaluations_data" class="margin-top-100 margin-bottom-100">

        <div th:each="entry: ${ENTRIES}">
            <div class="container page-small page-small-header" th:if="${entry.type == 0}">
                <div class="row page-row-evaluation">
                    <span th:text="${entry.timestampLabel}"></span>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small page-small-header-sub" th:if="${entry.type == 1}">
                <div class="row page-row-evaluation">
                    <span th:text="${entry.timestampLabel}"></span>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 2}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.value} + ' ' + ${USER_UNIT_VALUE}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel} + ' '"></span>
                        <span th:if="${entry.mealtime == 0}" th:text="'- ' + #{label.meal_before}"></span>
                        <span th:if="${entry.mealtime == 1}" th:text="'- ' + #{label.meal_after}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 3}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.units} + ' ' + #{label.insulin_units}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 4}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.units} + ' ' + #{label.bread}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 5}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.sporttype.sporttype}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:if="${entry.intensity == 0}" th:text="#{label.intensity_easy}"></span>
                        <span th:if="${entry.intensity == 1}" th:text="#{label.intensity_moderate}"></span>
                        <span th:if="${entry.intensity == 2}" th:text="#{label.intensity_hard}"></span>
                        <span th:if="${entry.intensity == 3}" th:text="#{label.intensity_very_hard}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.duration} + ' ' + #{label.minutes}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 6}">
                <script>
                    function loadFoodImage(id) {
                        $.ajax({
                            url : "/rest/evaluation/foodiamgeid",
                            type : "POST",
                            headers : createAuthorizationTokenHeader(),
                            async : 1,
                            data : {
                                image_id: id
                            },
                            success : function(data) {
                                var image = JSON.parse(data).USER_IMAGE;

                                if (image != null) {
                                    var selector = "#evaluation_food_image_" + id;

                                    $(selector).attr("src", image);
                                }
                            },
                            error : function(data) {

                            }
                        });
                    }
                </script>

                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="#{label.food}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <img th:id="'evaluation_food_image_' + ${entry.imageId}" src="/img/ic_rolling.gif" class="center-block img-responsiv image-upload-image" th:onload="|loadFoodImage('${entry.imageId}')|" />
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 7}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="#{label.note}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.note}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 8}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="#{label.mood}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                    <div class="col-md-12 text-center">
                        <img th:if="${entry.mood == 1}" class="image-mood" src="/img/ic_mood_very_bad_red.png"></img>
                        <img th:if="${entry.mood == 2}" class="image-mood" src="/img/ic_mood_bad_orange.png"></img>
                        <img th:if="${entry.mood == 3}" class="image-mood" src="/img/ic_mood_neutral_yellow.png"></img>
                        <img th:if="${entry.mood == 4}" class="image-mood" src="/img/ic_mood_good_green.png"></img>
                        <img th:if="${entry.mood == 5}" class="image-mood" src="/img/ic_mood_very_good_green.png"></img>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>
        </div>

    </div>
</body>
</html>


问题

这种方式加载数据是非常糟糕的用户体验,因为加载过程大约需要10秒钟,并且ui冻结,并且用户无法执行某些操作。他停留在旧页面上,必须等待10秒钟,然后“导航”到新片段。

我需要的

我需要一个百里香/弹簧解决方案来异步加载数据。因此,我希望用户单击链接后立即看到新页面,然后在从服务器收集数据的同时呈现某种加载动画。服务器完成后,视图应自动更新。

那可能吗?

最佳答案

您可以有两个单独的控制器,以便在另一页面上单击按钮时,它仅调用URL来显示该页面:

@RequestMapping(HelperUrls.URL_WEB_EVALUATION)
public String page(Model mode, HttpServletRequest request){
   model.addAttribute(ReturnKeys.TIME, new Date());
   model.addAttribute(ReturnKeys.ENTRIES, new ArrayList<>());
   model.addAttribute(ReturnKeys.USER_UNIT_VALUE, "");
   return Htmls.WEB_FRAGMENT_EVALUATION_DATA_F;
}

@RequestMapping(HelperUrls.URL_WEB_EVALUATION_DATA)
public String data(Model model, HttpServletRequest request,
        @RequestParam(value = Params.PARAM_FROM, required = true) long from,
        @RequestParam(value = Params.PARAM_TO, required = true) long to) {

    final IDM_USER user = this.idm_user_repository.findByEmail(request.getUserPrincipal().getName());

    if (user != null) {
        final int unit = user.getUnit();
        final Locale locale = LocaleContextHolder.getLocale();
        final String unitValue = HelperShortcuts.getUnitForShortcut(this.messageSource, locale, unit);

        Set<IDM_BREAD> breads = this.idm_bread_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_FOOD> foods = this.idm_food_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_INSULIN> insulins = this.idm_insulin_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_MEASURE> measures = this.idm_measure_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_MOOD> moods = this.idm_mood_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_NOTE> notes = this.idm_note_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);
        Set<IDM_SPORT> sports = this.idm_sport_repository.findByDatesBetweenAndUser(new Date(from), new Date(to), user);

        List<DatatransferListEntry> entries = new ArrayList<>();

        entries.addAll(breads);
        entries.addAll(foods);
        entries.addAll(insulins);
        entries.addAll(measures);
        entries.addAll(moods);
        entries.addAll(notes);
        entries.addAll(sports);
        entries = this.initHeaders(entries, locale);

        model.addAttribute(ReturnKeys.TIME, Helper.getDateTimePatternEvaluation(this.messageSource, locale, from, to));
        model.addAttribute(ReturnKeys.ENTRIES, entries);
        model.addAttribute(ReturnKeys.USER_UNIT_VALUE, unitValue);
    }

    return Htmls.WEB_FRAGMENT_EVALUATION_DATA_F;
}


那么当页面加载时,您可以在body标签中或页面中的某个地方具有onload函数,该函数调用javascript函数,并在页面中的某处显示动画图像,并在ajax调用返回时将其隐藏:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<body onload="loadEvaluations()">
    <img src="animation-image.jpg" style="display:none" id="animationImage"/>
    <div th:fragment="fragment_evaluations_data" class="margin-top-100 margin-bottom-100">

        <div th:each="entry: ${ENTRIES}">
            <div class="container page-small page-small-header" th:if="${entry.type == 0}">
                <div class="row page-row-evaluation">
                    <span th:text="${entry.timestampLabel}"></span>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small page-small-header-sub" th:if="${entry.type == 1}">
                <div class="row page-row-evaluation">
                    <span th:text="${entry.timestampLabel}"></span>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 2}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.value} + ' ' + ${USER_UNIT_VALUE}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel} + ' '"></span>
                        <span th:if="${entry.mealtime == 0}" th:text="'- ' + #{label.meal_before}"></span>
                        <span th:if="${entry.mealtime == 1}" th:text="'- ' + #{label.meal_after}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 3}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.units} + ' ' + #{label.insulin_units}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 4}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.units} + ' ' + #{label.bread}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 5}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="${entry.sporttype.sporttype}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:if="${entry.intensity == 0}" th:text="#{label.intensity_easy}"></span>
                        <span th:if="${entry.intensity == 1}" th:text="#{label.intensity_moderate}"></span>
                        <span th:if="${entry.intensity == 2}" th:text="#{label.intensity_hard}"></span>
                        <span th:if="${entry.intensity == 3}" th:text="#{label.intensity_very_hard}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.duration} + ' ' + #{label.minutes}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 6}">
                <script>
                    function loadFoodImage(id) {
                        $.ajax({
                            url : "/rest/evaluation/foodiamgeid",
                            type : "POST",
                            headers : createAuthorizationTokenHeader(),
                            async : 1,
                            data : {
                                image_id: id
                            },
                            success : function(data) {
                                var image = JSON.parse(data).USER_IMAGE;

                                if (image != null) {
                                    var selector = "#evaluation_food_image_" + id;

                                    $(selector).attr("src", image);
                                }
                            },
                            error : function(data) {

                            }
                        });
                    }
                </script>

                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="#{label.food}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <img th:id="'evaluation_food_image_' + ${entry.imageId}" src="/img/ic_rolling.gif" class="center-block img-responsiv image-upload-image" th:onload="|loadFoodImage('${entry.imageId}')|" />
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 7}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="#{label.note}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.note}"></span>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>

            <div class="container page-small" th:if="${entry.type == 8}">
                <div class="row page-row-evaluation">
                    <div class="col-md-12">
                        <span class="evaluation-font" th:text="#{label.mood}"></span>
                    </div>
                    <div class="col-md-12 margin-top-5">
                        <span th:text="${entry.timestampLabel}"></span>
                    </div>
                    <div class="col-md-12 text-center">
                        <img th:if="${entry.mood == 1}" class="image-mood" src="/img/ic_mood_very_bad_red.png"></img>
                        <img th:if="${entry.mood == 2}" class="image-mood" src="/img/ic_mood_bad_orange.png"></img>
                        <img th:if="${entry.mood == 3}" class="image-mood" src="/img/ic_mood_neutral_yellow.png"></img>
                        <img th:if="${entry.mood == 4}" class="image-mood" src="/img/ic_mood_good_green.png"></img>
                        <img th:if="${entry.mood == 5}" class="image-mood" src="/img/ic_mood_very_good_green.png"></img>
                    </div>
                </div>

                <div class="row page-row-evaluation"></div>
            </div>
        </div>

    </div>
</body>
</html>


那么您的javascript可以做到:

function loadEvaluations() {
    $('#animationImage').show();
    $.ajax({
        url : "/evaluation/data",
        type : "POST",
        headers : createAuthorizationTokenHeader(),
        async : !1,
        data : {
            from: rangeFrom,
            to: rangeTo
        },
        success : function(data) {
            $('#animationImage').hide();
            $("#portal_container").html(data);
        },
        error : function(data) {
            $('#animationImage').hide();
            $("#portal_container").html(data);
        }
    });
}

09-25 16:10
查看更多