Что я сделал
Я создал компонент в donejs, а затем создал две супермодели contact
и email
, используя следующие команды:
donejs add component contactComponent contact-component
donejs add supermodel contact
donejs add supermodel email
Есть API (feathers+mongodb), который предоставляет контакты и электронную почту. Каждое электронное письмо имеет contactId
.
Компонент включает в себя модель Contact
и обрабатывает такие вещи, как сохранение, создание нового элемента, удаление элемента и так далее. При объединении этого с файлом .stache
он успешно извлечет элементы из API и перечислит их соответствующим образом.
Итак, у каждого Contact
есть электронная почта. Поскольку у каждого контакта есть свои электронные письма, contactComponent не может получить их напрямую, но через элемент Contact
.
Здесь начинается моя проблема с дизайном.
Пока что contactComonent создает модель представления, которая обрабатывает способ обработки контактов. Контактная модель обрабатывает соединение API. Это отлично работает, является масштабируемым и чистым.
Но каждому контакту нужна новая модель для загрузки данных (электронной почты), тогда я напрямую использую модель для управления всей логикой, связанной с электронными письмами. Это действительно работает, но кажется, что позволить модели обрабатывать соединение, а модели представления обрабатывать сложные взаимодействия больше подходит для шаблона проектирования MVVM.
Я думаю, что я не первый человек, занимающийся этим типом моделирования данных, и я думаю, что должно быть лучшее решение, особенно при работе с большим количеством отношений и более сложными.
Я думаю, что у меня сейчас есть что-то вроде этого:
contactComponent.js
├── (includes) models/contact.js
│ ├── (includes) models/email.js
И это то, что я ищу (могу ошибаться)
contactComponent.js
├── (includes) models/contact.js
├── (includes / relates / references) emailComponent.js
emailComponent.js
├── (includes) models/email.js
Используемые файлы
File structurecontactComponent
├── contactComponent.js
├── contactComponent.stache
models
├── contact.js
├── email.js
contactComponent/contactComponent.js
/* contactComponent/contactComponent.js */
import Component from 'can/component/';
import Map from 'can/map/';
import 'can/map/define/';
import template from './contactComponet.stache!';
import Contact from '../models/contact.js';
export const ViewModel = Map.extend({
define: {
contactPromise: {
get: function() {
return Contact.getList({});
}
}
},
saveContact: function() {
// do some stuff
},
deleteContact: function() {
// do some stuff
}
});
export default Component.extend({
tag: 'contact-component',
viewModel: ViewModel,
template
});
contactComponent/contactComponent.stache
/* contactComponent/contactComponent.stache */
{{#if contactPromise.isResolved}}
{{#each contactPromise.value}}
Name: {{name}}
{{#if emailPromise.isResolved}}
Emails:
{{#each emailPromise.value}}
{{email}}
{{/each}}
{{/if}}
{{/each}}
{{/if}}
models/email.js
/* models/email.js */
import can from 'can';
import superMap from 'can-connect/can/super-map/';
import tag from 'can-connect/can/tag/';
import 'can/map/define/define';
export const Email = can.Map.extend({
define: {},
type: null,
email: null,
});
Email.List = can.List.extend({
Map: Email
}, {});
export const emailConnection = superMap({
url: '/api/modelEmail',
idProp: '_id',
Map: Email,
List: Email.List,
name: 'email'
});
tag('email-model', emailConnection);
export default Email;
Здесь все становится слишком сложным:
models/contact.js/* models/contact.js */
import can from 'can';
import superMap from 'can-connect/can/super-map/';
import tag from 'can-connect/can/tag/';
import 'can/map/define/define';
import Email from '../models/email.js';
export const Contact = can.Map.extend({
define: {
emailPromise: {
get: function() {
return Email.getList({ contactId: this.attr('id') });
}
}
},
name: null,
});
Contact.List = can.List.extend({
Map: Contact
}, {});
export const contactConnection = superMap({
url: '/api/modelContact',
idProp: '_id',
Map: Contact,
List: Contact.List,
name: 'contact'
});
tag('contact-model', contactConnection);
export default Contact;