ui-router/sample-app-angularjs 中的子状态绑定

Sub state bindings in ui-router/sample-app-angularjs

我正在研究 sample app of UI-Router 并得到了问题。

sample-app-angularjs/app/contacts/editContact.component.js行71~74有:

export const editContact =  {
  bindings: { pristineContact: '<' },

  controller: EditContactController,

sample-app-angularjs/app/contacts/contacts.states.js行29~38有:

export const viewContactState = {
  name: 'contacts.contact',
  url: '/:contactId',
  resolve: {
    // Resolve the contact, based on the contactId parameter value.
    // The resolved contact is provided to the contactComponent's contact binding
    contact: ['Contacts', '$transition$', (Contacts, $transition$) => Contacts.get($transition$.params().contactId)]
  },
  component: 'contactView'
};

并且在 sample-app-angularjs/app/contacts/contacts.states.js line49~61 它有:

export const editContactState = {
  name: 'contacts.contact.edit',
  url: '/edit',
  views: {
    // Relatively target the grand-parent-state's $default (unnamed) ui-view
    // This could also have been written using ui-view@state addressing: $default@contacts
    // Or, this could also have been written using absolute ui-view addressing: !$default.$default.$default
    '^.^.$default': {
      bindings: { pristineContact: "contact" },
      component: 'editContact'
    }
  }
};

我的问题是关于参数 pristineContact:

  1. 它是如何从状态 contacts.contact 传递到 contacts.contact.edit然后到组件 editContact?我了解状态 contacts.contact 中的解析 contact 在其子状态 contacts.contact 中直接可用。编辑,但我找不到任何与contacts.states.js的子句'bindings: { pristineContact: "contact" }'(第57行)相关的知识库文档。我猜它会将解析传递给它的组件,因此它的组件可以使用“绑定{...}”来输入它。

  2. 我在组件editContact的模板中没有看到是used/referenced,但是$ctrl.contact 改为 used/referenced。 -- 我完全不明白为什么会有“pristineContact”这个名字。

在示例应用程序中,editContact 组件使用脏检查来确定联系人是否已被编辑。脏检查用于提示用户是否要在切换到不同的 URL.

时放弃更改

1) 它是如何通过contact解析的?

如您所述,contact 解析在嵌套状态下可用。但是,editContact 组件没有 contact 绑定。相反,它有一个 pristineComponent 绑定。

为了将 contact 解析映射到 pristineContact 组件绑定,将 bindings 映射添加到状态。

      bindings: { pristineContact: "contact" },

这提供 pristineContact 组件与来自 contact 解析的数据的绑定。

本指南介绍解析绑定: https://ui-router.github.io/guide/ng1/route-to-component#resolve-bindings

... 而这个 API 文档有更多血淋淋的细节: https://ui-router.github.io/ng1/docs/latest/interfaces/ng1.ng1viewdeclaration.html#bindings

2) 模板中的$ctrl.contact是什么,pristineContact在哪里?

editContact 组件的脏检查会在 $onInit() 中创建原始(原始)联系人的副本。表格中的任何更改都会应用到副本 ($ctrl.contact):

  $onInit() {
    // Make an editable copy of the pristineContact
    this.contact = angular.copy(this.pristineContact);
  }

当用户点击保存时,可编辑的副本被保存,然后激活父状态,reload: true重新加载更改的数据。

  /** Save the contact, then go to the grandparent state ('contacts') */
  save(contact) {
    this.Contacts.save(contact)
        .then(() => this.canExit = true)
        .then(() => this.$state.go("^", null, { reload: true }));
  }

pristineContact仅用于制作初始副本,然后执行脏检查:

  uiCanExit() {
    if (this.canExit || angular.equals(this.contact, this.pristineContact)) {
      return true;
    }

    let message = 'You have unsaved changes to this contact.';
    let question = 'Navigate away and lose changes?';
    return this.DialogService.confirm(message, question);
  }