使用AngularJS + UI-Router项目。完成了这些(简化的)要求的任务:
Edit
按钮显示表格中的项目列表Edit
按钮应将表格行转换为项目编辑表单(内联编辑)所以我已经定义了我的状态:
// app.js
$stateProvider
.state("list", {
url: "/",
component: "listComponent"
})
.state("list.edit", {
url: "/{id}/edit",
component: "editComponent"
});
}
ListComponent
模板如下所示:
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th> </th>
</tr>
<!-- Hide this row when NOT in edit mode -->
<tr ng-repeat-start="item in $ctrl.items" ng-if="$ctrl.editIndex !== $index">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>
<button type="button" ng-click="$ctrl.onEditClick($index, item.id)">Edit</button>
</td>
</tr>
<!-- Show this row when in edit mode -->
<tr ng-repeat-end ng-if="$ctrl.editIndex === $index">
<td colspan="3">
<ui-view></ui-view>
</td>
</tr>
</table>
ListComponent
本身的主要部分:
function ListController($state) {
this.editIndex = null;
this.items = [
{ id: 1, name: "Y-Solowarm" },
// ...
{ id: 10, name: "Keylex" }
];
this.onEditClick = function(index, id) {
this.editIndex = index;
$state.go("list.edit", { id: id });
};
}
当我处理EditComponent
时,我注意到它启动了http请求两次。几个小时之后,我想出了EditComponent
,显示了实际发生的事情:
function EditController() {
// random number per component instance
this.controllerId = Math.floor(Math.random() * 100);
this.$onInit = function() {
console.log("INIT:", this.controllerId);
};
this.$onDestroy = function() {
console.log("DESTROY:", this.controllerId);
};
}
控制台显示了此输出:
DESTROY: 98
INIT: 80
DESTROY: 80
INIT: 9
第二次点击Edit
时,此输出显示
EditComponent#98
在我们远离它时被破坏(预期)EditComponent#80
已创建并立即销毁(意外)EditComponent#9
已创建,因为我们正在“修改”新项目(预期)这只是告诉我,许多<ui-view>
和ng-if
s一起播放不是很好,但我不知道如何解决这个问题。
我尝试过的一件事是我在<ui-view>
中创建了一个ListComponent
,并通过纯javascript在ui-router状态更改中移动它。但这不起作用,因为我很快就开始从ui-router的框架中获取与缺少HTML节点相关的错误。
我在这里做错了什么?我认为angular的摘要周期(以及相关的DOM更改)晚于ui-router开始转换和相关组件创建和销毁,这可能是EditComponent#80
被创建并快速销毁的原因。但我不知道如何解决这个问题。
这是一个显示正在发生的事情的码本:
https://codepen.io/ramunsk/project/editor/AYyYqd
(别忘了打开开发者控制台,看看发生了什么)
由于
答案 0 :(得分:1)
假设您正在从索引2切换到索引3.我认为这可能是正在发生的事情:
索引2处的ui-view当前处于活动状态。在单击处理程序中,您调用state.go,索引2处的ui-view会短暂地接收更新的状态参数id: 3
。然后当ng-if生效并且创建索引3处的ui-view时,它将被销毁。
更改您的代码,使其破坏索引2 的ui-view 。添加超时,以便调用state.go显示下一个摘要周期中的第二个ui-view 。
this.onEditClick = function(index, id) {
this.editIndex = null;
$timeout(() => {
this.editIndex = index;
$state.go("list.edit", { id: id });
});
};