@time_is_always_against_us

Как сделать, чтобы JS метод выполнятся после полного рендеринга страницы во Vue.js?

Что делаю?
1. Ajax запрос к серверу через библиотеку axios. Получаю, к примеру, список машин (id -> name).
2. В цикле строю option для select.
3. К данному select применяю bootstrap-select. Он нужен, чтобы кастомизировать select: 5e9447945cb94974637101.png

В чем проблема?
JS скрип selectpicker не успевает дождаться, пока Vue.js отрендерит select-> option, считая, что там элементов нет.

Упрощенно код выглядит так:
<template>
    <div>
        <select name="cars" class="selectpicker">
            /* 2. Vue.js, получив данные, начал рендерить option */
            <option v-for="(val, key) in cars" :key="key" :value="key">{{val}}</option>
        </select>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                cars: []
            }
        },
        mounted() {
            axios.get('/info/car')
                .then((result) => {
                    this.cars = result.data; /* 1. Получили данные от сервера и записали в переменную. */
                    $('.selectpicker').selectpicker(); /* 3. Иногда не успевает дождаться рендеринга и 
в select не отображает элементы, ибо vue.js их еще не создал. */
                });
        }
    }
</script>


Upd:
this.$nextTick - не помог:
5e9466a9f0843885644272.png

Доку прочитал, в теории это должно было решить проблему, но увы.
Подробнее опишу всю цепочку того, что реально происходит может быть ошибка в другом.
1. В модуле Vuex делаются запросы и получаются все списки всех select на сайте из БД.
2. Создаю computed свойство listCar и отслеживаю его в watch. Если изменится, значит данные с сервера загружены и можно применять selectpicker.
<template>
    <div>
        <select name="cars" class="selectpicker" id="carList">
            /* Использует computed listCar */
            <option v-for="(val, key) in listCar" :key="key" :value="key">{{val}}</option>
        </select>
    </div>
</template>

computed: {
            ...mapState(['list']), // Получили
            listCar() {
                return this.list.cars;
            }
        },

        watch: {
            listCar() { // Отслеживает, чтобы список с сервера уже был загружен.
                this.$nextTick(function () { // Ждем пока отрендерит.
                    $('#carList').selectpicker(); // Применяет selectpicker
                })
            }
        }
  • Вопрос задан
  • 477 просмотров
Решения вопроса 2
0xD34F
@0xD34F Куратор тега Vue.js
nextTick

И ещё вот такого

$('.selectpicker')

быть не должно. Вместо селектора используйте ссылку на элемент.
Ответ написан
Fragster
@Fragster
помогло? отметь решением!
Упрощенно как-то так:
https://ru.vuejs.org/v2/api/#vm-nextTick
....
axios.get("/info/car").then(result => {
    this.cars = result.data; /* 1. Получили данные от сервера и записали в переменную. */
    this.$nextTick(function() {
        $(".selectpicker").selectpicker(); /* 3. Иногда не успевает дождаться рендеринга и 
в select не отображает элементы, ибо vue.js их еще не создал. */
    });
});
....

но лучше избавиться от jquery и прочего.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
ViperOMG
@ViperOMG
Столкнулся с аналогичной проблемой в Nuxt 2.17

мое решение проблемы:

mounted() {
     this.refreshSelectPicker()
    },
 methods: {
        refreshSelectPicker() {
            $('.selectpicker2').selectpicker('render');
        },

P.s. Переименовал selectpicker в selectpicker2, чтобы не срабатывал автоматический рендеринг. В текущем коде select формируется только после формирования контента на странице.

p.p.s Для тех, кому нужно динамическое обновление bootstap select на основе каких-то параметров:

refreshSelectPicker2() {
            $('.selectpicker3').selectpicker('destroy');
            $('.selectpicker3').selectpicker('render');
        },

// дописываем к классу selectpicker2 еще один класс selectpicker3 и вместо выполнения render/refresh - удаляем и рендерим список заного, в противном случае может двоить и троить контент.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы