Можете ли вы заставить Vue.js перезагрузить / перерисовать?


232

Просто быстрый вопрос.

Можно ли заставить Vue.jsк перегрузочной / пересчитывать все? Если да, то как?


Возможно, получит лучшую поддержку здесь github.com/vuejs/Discussion/issues
Кори Дэниелсон

Отлично, не знал об этом месте обсуждения. Я постараюсь там.
Дейв

Вы получили ответ? Я тоже хочу знать.
Оддман

Точно не помню Но вот проблема, которую я открыл с некоторыми подсказками: github.com/vuejs/Discussion/issues/356
Дейв

У меня есть директива v-for в представлении и случай использования, когда я вручную меняю два объекта в этом массиве. После этого Vue автоматически не перерисовывает шаблон. Я использовал обходной путь: просто выполните любое действие с этим массивом (протолкните пустой объект, а затем соедините) - это вызывает повторное рендеринг. Но это особый случай.
Федор Хрущов

Ответы:


237

Попробуйте это волшебное заклинание:

vm.$forceUpdate();

Нет необходимости создавать какие-либо висячие переменные :)

Обновление: я нашел это решение, когда только начал работать с VueJS. Однако дальнейшие исследования подтвердили этот подход как опору. Насколько я помню, через некоторое время я избавился от этого, просто поместив все свойства, которые не обновлялись автоматически (в основном вложенные), в вычисляемые свойства.

Более подробная информация здесь: https://vuejs.org/v2/guide/computed.html


4
это действительно помогло мне, когда я использовал его с компонентом мастера форм в Vue. Мои поля полей формы теряли состояние, хотя переменные данных были целы. Теперь я использую это, чтобы обновить представления, когда я возвращаюсь, мне пришлось поместить его в функцию setTimeout.
Джимми Иленлоа

26
Обратите внимание, что в vue-файлах вам нужно 'this. $ ForceUpdate ();'
Катинка Хесселинк

1
Это прекрасно работает для обновления после длительного вызова axios.
AlfredBr

4
Каким-то совершенно странным образом $forceUpdate()никогда не работал для меня на 2.5.17.
Абана Клара

2
@AbanaClara $ forceUpdate () никогда не был публичным методом, я нашел, что он копает исходный код Vue. И поскольку его использование никогда не было правильным способом Vue'ing, возможно, его можно было бы удалить. Не могу сказать наверняка, если это все еще там, так как я больше не делаю front-end.
Борис Моссунов

82

Это похоже на довольно чистое решение от matthiasg по этому вопросу :

Вы также можете использовать :key="someVariableUnderYourControl"и изменять ключ, когда вы хотите, чтобы компонент был полностью перестроен

Для моего случая использования я кормил геттер Vuex в компонент в качестве опоры. Каким-то образом Vuex будет извлекать данные, но реактивность не будет надежно задействована для повторной визуализации компонента. В моем случае, установка компонента keyдля некоторого атрибута в опоре гарантировала обновление, когда получатели (и атрибут) наконец-то разрешатся.


1
Это аккуратный маленький трюк, он в основном вызывает повторное создание компонента ( mountedбудет запущен и т. Д.)
btk

1
@BTK Я согласен, это, вероятно, не «правильный» способ сделать что-то, но это довольно чистый взлом, для того, что это такое.
Брайан Кунг

1
это полезно. Я использую полный путь маршрута в качестве ключа для повторного отображения того же компонента при изменении маршрута. : key = "$ route.fullPath"
Нирав Ганди

44

Зачем?

... вам нужно форсировать обновление?

Возможно, вы не исследуете Vue в лучшем виде:

Чтобы Vue автоматически реагировал на изменения значений, объекты должны быть первоначально объявлены вdata . Или, если нет, они должны быть добавлены с помощьюVue.set() .

Смотрите комментарии в демоверсии ниже. Или откройте ту же демонстрацию в JSFiddle здесь .

new Vue({
  el: '#app',
  data: {
    person: {
      name: 'Edson'
    }
  },
  methods: {
    changeName() {
      // because name is declared in data, whenever it
      // changes, Vue automatically updates
      this.person.name = 'Arantes';
    },
    changeNickname() {
      // because nickname is NOT declared in data, when it
      // changes, Vue will NOT automatically update
      this.person.nickname = 'Pele';
      // although if anything else updates, this change will be seen
    },
    changeNicknameProperly() {
      // when some property is NOT INITIALLY declared in data, the correct way
      // to add it is using Vue.set or this.$set
      Vue.set(this.person, 'address', '123th avenue.');
      
      // subsequent changes can be done directly now and it will auto update
      this.person.address = '345th avenue.';
    }
  }
})
/* CSS just for the demo, it is not necessary at all! */
span:nth-of-type(1),button:nth-of-type(1) { color: blue; }
span:nth-of-type(2),button:nth-of-type(2) { color: red; }
span:nth-of-type(3),button:nth-of-type(3) { color: green; }
span { font-family: monospace }
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <span>person.name: {{ person.name }}</span><br>
  <span>person.nickname: {{ person.nickname }}</span><br>
  <span>person.address: {{ person.address }}</span><br>
  <br>
  <button @click="changeName">this.person.name = 'Arantes'; (will auto update because `name` was in `data`)</button><br>
  <button @click="changeNickname">this.person.nickname = 'Pele'; (will NOT auto update because `nickname` was not in `data`)</button><br>
  <button @click="changeNicknameProperly">Vue.set(this.person, 'address', '99th st.'); (WILL auto update even though `address` was not in `data`)</button>
  <br>
  <br>
  For more info, read the comments in the code. Or check the docs on <b>Reactivity</b> (link below).
</div>

Чтобы освоить эту часть Vue, проверьте Официальные документы по реактивности - Предупреждения об обнаружении изменений . Это необходимо прочитать!


2
Определенно согласитесь, что вы должны подвергнуть сомнению это требование обновления, но иногда вам просто нужен пользовательский интерфейс для повторного рендеринга, потому что область просмотра изменилась, и вам нужно показать разные активы (в качестве одного примера). Данные, возможно, фактически не изменились.
the_dude_abides

1
Зачем вам нужно перезагрузить? В некоторых случаях файлы ресурсов (stylesheets / js), кэшированные браузером, необходимо перезагрузить через определенный промежуток времени. У меня была таблица стилей, которую нужно было перезагружать через 7 дней, и если пользователь оставлял открытую вкладку с доступом к странице и возвращался через 7 дней для навигации по этой странице, css было более 7 дней.
Ауроврата

@AchielVolckaert Вы, вероятно, уже нашли ответ, но да, Vue.set()также работает внутри компонентов.
acdcjunior

1
@the_dude_abides и @ Aurovrata, это законное использование освежения, я согласен. Я задал вопрос, что люди нередко освежаются по неправильным причинам.
acdcjunior

1
Возможно, вы просто пытаетесь исправить ошибку в плохо спроектированном веб-приложении, которое использует vue исключительно в качестве инструмента рендеринга и, например, перезагружает все приложение всякий раз, когда оно отправляется на сервер, игнорируя возможности приложения vue на стороне клиента. В реальном мире у вас не всегда есть время, чтобы исправить каждую мерзость, которую вы найдете.
Уоррен Дью

30

Пожалуйста, прочитайте это http://michaelnthiessen.com/force-re-render/

Ужасный способ: перезагрузка всей страницы
Ужасный путь: использование хака v-if
Лучший способ: использование встроенного метода Vue forceUpdate
Лучший способ: смена ключа в вашем компоненте

<template>
   <component-to-re-render :key="componentKey" />
</template>

<script>
 export default {
  data() {
    return {
      componentKey: 0,
    };
  },
  methods: {
    forceRerender() {
      this.componentKey += 1;  
    }
  }
 }
</script>

Я также использую часы: в некоторых ситуациях.


Абсолютно, я с тобой согласен!
Бриллиант

Я почти разочаровался в Vue. Но благодаря этому моя вера в Vue была восстановлена.
Иокаб

Ссылка на самом деле не показывает, как это сделать ужасным образом, а это, к сожалению, то, что мне нужно, так как мое приложение разработано для навигации по этому ужасному пути. Простой URL-адрес текущей страницы, похоже, не работает, по крайней мере, в приложении, с которым я имею дело, поэтому мне действительно нужны инструкции о том, как сделать это ужасным способом.
Уоррен Дью

@WarrenDew Пожалуйста, следуйте: stackoverflow.com/questions/3715047/…
Яш

25

Попробуйте использовать, this.$router.go(0);чтобы вручную перезагрузить текущую страницу.


3
Проще: это. $ Router.go ()
Мариус

На самом деле @MariusAndreiana - функции .go () требуется 1 необязательный параметр
a_lovelace


15

Конечно, вы можете просто использовать атрибут ключа для принудительного повторного рендеринга (воссоздания) в любое время.

<mycomponent :key="somevalueunderyourcontrol"></mycomponent>

См. Https://jsfiddle.net/mgoetzke/epqy1xgf/ для примера.

Это также обсуждалось здесь: https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875


12
<my-component :key="uniqueKey" />

наряду с этим используйте this.$set(obj,'obj_key',value) и обновляйте uniqueKeyдля каждого обновления в значении объекта (obj) для каждого обновленияthis.uniqueKey++

у меня так получилось


6

Есть два способа сделать это,

1). Вы можете использовать $forceUpdate()внутри вашего обработчика метода, т.е.

<your-component @click="reRender()"></your-component>

<script>
export default {
   methods: {
     reRender(){
        this.$forceUpdate()
     }
   }
}
</script>

2). Вы можете присвоить :keyсвой компонент атрибуту и ​​увеличить его, когда хотите перерисовать

<your-component :key="index" @click="reRender()"></your-component>

<script>
export default {
   data() {
     return {
        index: 1
     }
   },
   methods: {
     reRender(){
        this.index++
     }
   }
}
</script>

5

используя директиву v-if

<div v-if="trulyvalue">
    <component-here />
 </div>

Таким образом, простое изменение значения truevalue с false на true вызовет повторное рендеринг компонента между div.


1
На мой взгляд, это самый чистый способ перезагрузить компонент. Хотя в методе create () вы можете добавить кое-что для инициализации.
Петр Чак

5

Для перезагрузки / повторного рендеринга / обновления компонента остановите длинное кодирование. Есть способ Vue.JS сделать это.

Просто используйте :key атрибут.

Например:

<my-component :key="unique" />

Я использую это в слоте BS Vue Table. Сказать, что я сделаю что-то для этого компонента, чтобы сделать его уникальным.


3

Это сработало для меня.

created() {
            EventBus.$on('refresh-stores-list', () => {
                this.$forceUpdate();
            });
        },

Другой компонент запускает событие refresh-stores-list, что приведет к перерисовке текущего компонента


2

Я нашел путь. Это немного глупо, но работает.

vm.$set("x",0);
vm.$delete("x");

Где vmнаходится ваш объект модели представления, иx это несуществующая переменная.

Vue.js пожалуется на это в журнале консоли, но вызывает обновление всех данных. Протестировано с версией 1.0.26.


2

Работал для меня

    data () {
        return {
            userInfo: null,
            offers: null
        }
    },

    watch: {
        '$route'() {
            this.userInfo = null
            this.offers = null
            this.loadUserInfo()
            this.getUserOffers()
        }
    }


0

: key = "$ route.params.param1" просто используйте ключ с любыми параметрами для его автоматической перезагрузки потомков.


4
попробуйте дать подробную информацию о вашем решении. добавьте свой код, выделите ключевые слова
Агиланбу

0

У меня была эта проблема с галереей изображений, которую я хотел отрендерить из-за изменений, внесенных на другой вкладке. Итак, tab1 = imageGallery, tab2 = любимые изображения

tab @ change = "updateGallery ()" -> это заставляет мою директиву v-for обрабатывать функцию FilterImages каждый раз, когда я переключаю вкладки.

<script>
export default {
  data() {
    return {
      currentTab: 0,
      tab: null,
      colorFilter: "",
      colors: ["None", "Beige", "Black"], 
      items: ["Image Gallery", "Favorite Images"]
    };
  },
  methods: {
    filteredImages: function() {
      return this.$store.getters.getImageDatabase.filter(img => {
        if (img.color.match(this.colorFilter)) return true;
      });
    },
    updateGallery: async function() {
      // instance is responsive to changes
      // change is made and forces filteredImages to do its thing
      // async await forces the browser to slow down and allows changes to take effect
      await this.$nextTick(function() {
        this.colorFilter = "Black";
      });

      await this.$nextTick(function() {
        // Doesnt hurt to zero out filters on change
        this.colorFilter = "";
      });
    }
  }
};
</script>

0

извините, ребята, кроме метода перезагрузки страницы (мерцание), ни один из них не работает для меня (: ключ не работал).

и я нашел этот метод из старого форума vue.js, который работает для меня:

https://github.com/vuejs/Discussion/issues/356

<template>
    <div v-if="show">
       <button @click="rerender">re-render</button>
    </div>
</template>
<script>
    export default {
        data(){
            return {show:true}
        },
        methods:{
            rerender(){
                this.show = false
                this.$nextTick(() => {
                    this.show = true
                    console.log('re-render start')
                    this.$nextTick(() => {
                        console.log('re-render end')
                    })
                })
            }
        }
    }
</script>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.