vue, локальные данные и реактивное обновление
От: DenisCh Россия  
Дата: 15.09.19 07:59
Оценка:
Добрый...
Наткнулся тут на штуку, которую не понимаю, как обойти. (Я даже не чайник в веб-программировании, а так... Кипятильник)
Есть простой vue-компонент (схема упрощена до предела):
<template>
  <div>{{dPagedata}}</div>
</template>

<script lang='ts'>
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component
export default class Page extends Vue {
  @Prop() public Pageid: string;
  private Pagedata: string;
  private data() {
    return {
      dPagedata: this.Pagedata,
    }
  }

  private created() {
    DataModule.GetDataAsync(this.Pageid)
    .then((val) => {
      this.$data.dPagedata = val;
    });

}

Параметр Pageid устанавливается родителем, идёт получение данных и всё более-менее нормально рисуется при переходе, например, с / на /Page?Pageid=1.
Но потом, когда мы переходим c/Page?Pageid=1 на /Page?Pageid=2 (например, по прямой ссылке) — created, разумеется, не срабатывает. А срабатывает updated() вида, аналогичного create.
И вот тут загвоздка. Поскольку меняются реактивно связанные данные — тут же возникает опять updated() и мы зацикливаемся.

Понимаю, что я что-то делаю не так, но что не так — я не понимаю...

Подскажите, куда копать?
[url=https://github.com/abbat/avalon1.0.449[/url]
Re: vue, локальные данные и реактивное обновление
От: Somescout  
Дата: 15.09.19 09:30
Оценка: +1
Здравствуйте, DenisCh, Вы писали:

DC>Параметр Pageid устанавливается родителем, идёт получение данных и всё более-менее нормально рисуется при переходе, например, с / на /Page?Pageid=1.

DC>Но потом, когда мы переходим c/Page?Pageid=1 на /Page?Pageid=2 (например, по прямой ссылке) — created, разумеется, не срабатывает. А срабатывает updated() вида, аналогичного create.
DC>И вот тут загвоздка. Поскольку меняются реактивно связанные данные — тут же возникает опять updated() и мы зацикливаемся.

Do not use if: You need to know when a reactive property on your component changes. Use computed properties or watchers for that instead.


Вам, вероятно, подойдёт второй вариант: https://vuejs.org/v2/api/#watch ( https://alligator.io/vuejs/typescript-class-components/#watchers )
ARI ARI ARI... Arrivederci!
Отредактировано 15.09.2019 9:32 Somescout . Предыдущая версия .
Re[2]: vue, локальные данные и реактивное обновление
От: DenisCh Россия  
Дата: 15.09.19 10:15
Оценка:
Здравствуйте, Somescout, Вы писали:

S> DC>Параметр Pageid устанавливается родителем, идёт получение данных и всё более-менее нормально рисуется при переходе, например, с / на /Page?Pageid=1.

S> DC>Но потом, когда мы переходим c/Page?Pageid=1 на /Page?Pageid=2 (например, по прямой ссылке) — created, разумеется, не срабатывает. А срабатывает updated() вида, аналогичного create.
S> DC>И вот тут загвоздка. Поскольку меняются реактивно связанные данные — тут же возникает опять updated() и мы зацикливаемся.
S> Do not use if: You need to know when a reactive property on your component changes. Use computed properties or watchers for that instead.
S> Вам, вероятно, подойдёт второй вариант: https://vuejs.org/v2/api/#watch ( https://alligator.io/vuejs/typescript-class-components/#watchers )

Я тут не совсем понимаю.
myProperty: string

  @Watch('myProperty')
  onPropertyChanged(value: string, oldValue: string) {
    // Do stuff with the watcher here.
  }


И как потом мне это отразить в шаблоне? Поймал я изменение моей Pagedata, а дельше? как его в шалон рисовать?
[url=https://github.com/abbat/avalon1.0.449[/url]
Re: vue, локальные данные и реактивное обновление
От: Буравчик Россия  
Дата: 15.09.19 10:19
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Понимаю, что я что-то делаю не так, но что не так — я не понимаю...


DC>Подскажите, куда копать?


Вот сюда:
VueJs 2.0 &mdash; how to listen for `props` changes
Best regards, Буравчик
Re[2]: vue, локальные данные и реактивное обновление
От: DenisCh Россия  
Дата: 15.09.19 11:49
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б> DC>Понимаю, что я что-то делаю не так, но что не так — я не понимаю...

Б> DC>Подскажите, куда копать?
Б> Вот сюда:
Б> VueJs 2.0 &mdash; how to listen for `props` changes

Не то. Наверное, я неправильно объясняю. Или не понимаю этих ссылок. Попробую ещё раз.
1. есть @Prop() PageId и computed PageTitle {return this._PageTitle}
2. Родитель обновляет PageId
3. Я попадаю в beforeUpdate и должен запросить с сервера PageTitle
4. Полученное значение я пишу в this._PageTitle
5. Вычисляемое PageTitle изменяется и я опять попадаю в 3.
Круг замыкается. Вот хочется разорвать это самый замкнутый...
[url=https://github.com/abbat/avalon1.0.449[/url]
Re[3]: vue, локальные данные и реактивное обновление
От: Буравчик Россия  
Дата: 15.09.19 12:16
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>1. есть @Prop() PageId и computed PageTitle {return this._PageTitle}

DC>2. Родитель обновляет PageId
DC>3. Я попадаю в beforeUpdate и должен запросить с сервера PageTitle
DC>4. Полученное значение я пишу в this._PageTitle
DC>5. Вычисляемое PageTitle изменяется и я опять попадаю в 3.
DC>Круг замыкается. Вот хочется разорвать это самый замкнутый...

1. Создаешь метод updateData, который делает две вещи:
— запрашивает бэкенд для данного this.PageId
— устанавливает поле this._PageTitle
2. Обрабатываешь событие created (сработает при инициализации компонента) — вызываешь updateData.
3. Обрабатываешь изменение свойства this.PageId с помощью watch (сработает, когда родительский компонент изменит свойство) — вызываешь updateData

beforeUpdate в данном случае не нужен
Best regards, Буравчик
Re[4]: vue, локальные данные и реактивное обновление
От: DenisCh Россия  
Дата: 15.09.19 14:52
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б> DC>1. есть @Prop() PageId и computed PageTitle {return this._PageTitle}

Б> DC>2. Родитель обновляет PageId
Б> DC>3. Я попадаю в beforeUpdate и должен запросить с сервера PageTitle
Б> DC>4. Полученное значение я пишу в this._PageTitle
Б> DC>5. Вычисляемое PageTitle изменяется и я опять попадаю в 3.
Б> DC>Круг замыкается. Вот хочется разорвать это самый замкнутый...
Б> 1. Создаешь метод updateData, который делает две вещи:
Б> — запрашивает бэкенд для данного this.PageId
Б> — устанавливает поле this._PageTitle
Б> 2. Обрабатываешь событие created (сработает при инициализации компонента) — вызываешь updateData.
Б> 3. Обрабатываешь изменение свойства this.PageId с помощью watch (сработает, когда родительский компонент изменит свойство) — вызываешь updateData

Сделал так. В шаблон указал {{compTitle}}, написал
get compTitle() { return this.PageTitle } (возвращает, проверил через console)
Сделал функцию ГзвфеуВфеф(), которая заполняет this.PageTitle (проверил через console.log).
Но в макете нужная строка не появляется, то есть страница не перерисовывается... Т.е. в шаблон ижёт пустое (начальное) значение. И функция compTitle() не вызывается после изменения PageTitle...
Что-то я совсем запутался...
[url=https://github.com/abbat/avalon1.0.449[/url]
Re[5]: vue, локальные данные и реактивное обновление
От: Буравчик Россия  
Дата: 15.09.19 16:39
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Здравствуйте, Буравчик, Вы писали:


DC>Сделал так. В шаблон указал {{compTitle}}, написал

DC>get compTitle() { return this.PageTitle } (возвращает, проверил через console)
DC>Сделал функцию ГзвфеуВфеф(), которая заполняет this.PageTitle (проверил через console.log).
DC>Но в макете нужная строка не появляется, то есть страница не перерисовывается... Т.е. в шаблон ижёт пустое (начальное) значение. И функция compTitle() не вызывается после изменения PageTitle...
DC>Что-то я совсем запутался...

Похоже, не срабатывает реактивность по изменению this.PageTitle. Может это поле в data как-то неправильно описал, может еще что.
Выкладывай минимальный (но полный) нерабочий код. Лучше на jsfiddle
Best regards, Буравчик
Re[6]: vue, локальные данные и реактивное обновление
От: DenisCh Россия  
Дата: 18.09.19 01:57
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б> Похоже, не срабатывает реактивность по изменению this.PageTitle. Может это поле в data как-то неправильно описал, может еще что.

Б> Выкладывай минимальный (но полный) нерабочий код. Лучше на jsfiddle

Вот обрезанный код.

<template>
  <div>
    <h2>{{compDescr}}</h2>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
import { ForumTopic, GetForumTopics, GetForumDescr } from '@/Modules/DataProvider';

@Component
export default class ForumsTopics extends Vue {
  @Prop() public ForumId: string;
  private ForumDescr: string | undefined;

  private get compDescr() {
    console.log('compDescr');
    console.log(this.ForumDescr);
    return this.ForumDescr;
  }

  @Watch('ForumId') private onForumIdChanged(val: string, oldVal: string) {
    console.log('onForumIdChanged ' + val);
    this.ForumDescr = val;
  }

  private UpdateData(): void {
    console.log('UpdateData');
    if (this.ForumId !== undefined && this.ForumId !== '') {
      console.log('try to get data');
      const res2 = GetForumDescr(this.ForumId)
        .then((data) => {
          this.ForumDescr = data;
          console.log('Got descr ' + this.ForumDescr);
          console.log(this.ForumDescr);
          this.$forceUpdate();
        })
        .catch((reason) => {
          console.log('error ' + reason);
          this.ForumDescr = 'Ошибка получения описания ' + reason;
        });
    }
  }

  private created() {
    console.log('topics created ' + this.ForumId);
    this.UpdateData();
    }
  }
</script>


Вот вывод консоли.

topics created 1
UpdateData
try to get data
compDescr
undefined
Got descr Тестовая строка 1
Тестовая строка 1

То есть видно, что вычисляемое поле зовётся один раз, после создания. После изменения внутренней переменной вычисляемое не пересчитывается...
[url=https://github.com/abbat/avalon1.0.449[/url]
Re[7]: vue, локальные данные и реактивное обновление
От: Буравчик Россия  
Дата: 20.09.19 13:47
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>То есть видно, что вычисляемое поле зовётся один раз, после создания. После изменения внутренней переменной вычисляемое не пересчитывается...


Твой код не могу запустить. Вот, лови, изменный, на JS (не TS).

Заходишь на jsfiddle и нажимаешь Run. Создается компонент. Потом пауза 2 секунды ("запрос к бэкенду"), затем видно, что вычисляемое значение обновляется (т.е. вызывается дважды).

https://jsfiddle.net/9nztwsp6/
Best regards, Буравчик
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.