Давайте на минутку рассмотрим, что делает ваш код, чтобы убедиться, что мы понимаем, что происходит не так:
Конструктор в ChatServices
создает новый объект в памяти (Object A
), этот объект имеетсвойство 1
, которое содержит массив в памяти (Array 1
)
constructor() {
this.collection = {
1: [
{
chat: 'Hi',
},
{
chat: 'Hello',
},
{
chat: 'How are you?',
},
],
};
}
В конструкторе компонента вы используете ChatService
для извлечения Array 1
из памяти и сохранения его в this.chats
свойство из вашего компонента
this.chats = ChatService.getChatById(this.id);
Итак, в настоящее время у нас есть две переменные, указывающие на один и тот же массив (Array 1
) в памяти: свойство chats
вашего компонента и collection
'* 1
свойство в ChatService
.
Однако, когда вы добавляете сообщение в ChatService, вы используете следующее:
addChat(id, chat) {
this.collection[id] = this.collection[id].concat(chat);
}
Что это делает: Обновляет collection
* свойство 1
не указывает на Array 1
, но вместо этого создает новый массив, объединяя как текущий Array 1
, так и новый message
, сохраняет его в памяти (Array 2
) и присваивает его collection[id]
.
Примечание. Это означает, что Object A
объектСвойство t 1
также указывает на Array 2
Даже если свойство collection
1
было правильно обновлено, когда дело доходит до неизменности, свойство chats
вашего компонентав памяти все еще указывает на Array 1
.
Ничто не указывает на то, что следует указывать на Array 2
.
Вот простой пример, демонстрирующий, что происходит:
const obj = { 1: ['a'] };
function get() {
return obj['1'];
}
function update() {
obj['1'] = obj['1'].concat('b');
}
const result = get();
console.log('result before update', result );
console.log('obj before update', obj['1']);
update();
console.log('result after update', result );
console.log('obj after update', obj['1']);
Как видно из приведенного выше фрагмента, указание obj['1']
на новый массив не приводит к изменению массива result
точек на.
Вот почему следующее работает правильно:
Один из способов, с помощью которого $ onChanges срабатывает, - это когда я получаю всю коллекцию чатов, а затем использую ctrl.id для получения определенных чатов при прохождении через привязки, например<chat-list chats="$ctrl.chats[$ctrl.id]"
вместо <chat-list chats="$ctrl.chats
.
В этом случае вы сохраняете ссылку на Object A
.Как упоминалось выше, 1
свойство ChatService
collection
обновляется правильно, поэтому это будет отражаться в вашем компоненте, так как он также использует тот же Object A
.
.используя вышеуказанный способ (то есть, передав Object A
вашему компоненту), вы должны убедиться, что компонент знает об изменениях, внесенных в Object A
(поскольку он не может знать об этом, когда не имеет к нему доступа).
Типичный способ, которым подобные вещи делаются в Angular (я знаю, что это AngularJS, но просто указываю, как можно решить эту проблему так, как Angular будет работать и отлично работает с Angular JS), это использование RXjs и подписка наизменения чатов в вашем компоненте.