Knockout foreach循环数组项如何传递至局部视图实现data-bind绑定
绑定失效的核心根源
你现在拿不到循环内数组项的本质原因,是混淆了Razor服务端渲染和Knockout客户端绑定的执行边界,再叠加HTML表格的严格嵌套解析规则导致的:
@await Html.PartialAsync()是服务端跑Razor引擎时就完成静态HTML拼接输出的,根本感知不到客户端Knockout foreach循环里的当前项——毕竟服务端执行的时候,客户端的可观察数组还没初始化值。- 你之前尝试用
ko with: $data包裹不生效,大概率是把局部视图的HTML直接塞在<tr>标签下,没有用合法的<td>包裹。浏览器解析表格结构时,会自动把非<td>/<th>类的非规范子节点移出<tr>作用域,直接扔到表格外层,把你写的ko with注释绑定块和内部的局部视图内容拆成两个独立的DOM节点,Knockout根本没法把作用域正确绑定到元素上。
满足约束条件的可落地方案
在不改动现有foreach结构、不拆分局部视图的前提下,按下面调整即可实现循环项的作用域传递:
1. 修正表格内的节点嵌套结构
把局部视图的输出从<tr>的直接子节点位置,挪到合法的<td>标签内部,从根源上避免浏览器把DOM节点移位:
<!--ko with: myProperty--> <table class="table"> <thead> <tr> <th>Column 1</th> <th>Column 2</th> </tr> </thead> <tbody> <!-- ko foreach: myListB()--> <tr> <td data-bind="text: Property1"></td> <td data-bind="text: Property2"></td> <!-- 用合法td包裹局部视图,不影响布局因为modal是fixed定位 --> <td style="display: none;"> <!-- 显式声明当前作用域为foreach循环的当前项 --> <!-- ko with: $data --> @await Html.PartialAsync("~/Views/MyView.cshtml", this) <!-- /ko --> </td> </tr> <!-- /ko --> </tbody> </table> <!-- /ko -->
这里给
<td>加display: none完全不影响modal的展示,因为modal本身是脱离文档流的fixed定位元素,只是用来给节点找个合法的表格“落点”,避免被浏览器结构解析移位。
2. 调整局部视图的绑定表达式
当上面的ko with: $data生效后,局部视图内部的绑定作用域已经是当前foreach循环的Model1对象了,不需要再手动写$data.前缀,不然反而会因为作用域嵌套错位拿不到值:
把局部视图MyView.cshtml的绑定改成:
<div class="modal" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content "> <div class="modal-header"> <h4 class="modal-title">MyTitle</h4> </div> <!--ko if: Property1 != null --> <div class="modal-body "> <span data-bind="text: Property1"></span> </div> <!-- /ko --> </div> </div> </div>
常见排错点
- 之前你写的
ko with: $data不生效,还有一个原因是外层的作用域是myProperty(也就是Foo类的实例),如果没有foreach的上下文,$data本来就指向Foo对象,根本不是Model1类型的数组项。只有把ko with: $data的位置放在foreach循环的内部、且DOM节点不被移位,$data才会指向当前循环的Model1实例。 - 如果改完还是绑定异常,可以在浏览器控制台输入
ko.dataFor(对应的modal DOM节点),检查绑定上下文是不是指向当前循环的Model1对象;同时在Elements面板里确认,<!-- ko with: $data -->和<!-- /ko -->两个注释块完整包裹了局部视图输出的全部HTML,没有被浏览器拆开。
内容的提问来源于stack exchange,提问作者David Shepard
相关产品推荐
相关产品推荐

