如何在knockoutjs中绑定点击处理程序到模板,而不需要全局视图模型
How to bind click handlers to templates in knockoutjs without having a global viewModel?
我对KnockoutJs很陌生,所以我希望有一个众所周知的最佳实践来解决这种情况,我只是没能找到。
我有一个包含项目数组的视图模型。我想使用模板显示这些项目。我还希望每个项目能够在视图和编辑模式之间切换。我认为最适合Knockout的是在主视图模型上或(可能更好)在数组中的每个项目上创建相关函数,然后在模板中绑定此函数。因此,我在我的页面上创建了以下代码:
<ul data-bind="template: {name: testTemplate, foreach: items}"></ul>
<script id="testTemplate" type="text/x-jquery-tmpl">
<li>
<img src="icon.png" data-bind="click: displayEditView" />
<span data-bind="text: GBPAmount"></span>
<input type="text" data-bind="value: GBPAmount" />
</li>
</script>
<script>
(function() {
var viewModel = new TestViewModel(myItems);
ko.applyBindings(viewModel);
})();
</script>
在一个单独的文件中:
function TestViewModel(itemsJson) {
this.items = ko.mapping.fromJS(itemsJson);
for(i = 0; i < this.items.length; ++i) {
this.items[i].displayEditView = function () {
alert("payment function called");
}
}
this.displayEditView = function () {
alert("viewmodel function called");
}
};
由于环境我的JS运行在我不能添加任何到全局命名空间,因此匿名函数来创建和设置视图模型。(如果有必要,我可以在一个名称空间中添加东西。)这个限制似乎打破了我发现的所有示例,这些示例似乎依赖于全局viewModel变量。
注:如果有一种方法比我想做的更适合knockoutJS,请随时提出建议!
当您的viewModel无法全局访问时,有几个选项。
首先,您可以使用templateOptions
参数将任何相关方法传递给模板绑定。
它看起来像(也要注意静态模板名应该带引号):
data-bind="template: {name: 'testTemplate', foreach: items, templateOptions: { vmMethod: methodFromMainViewModel } }"
则在模板内部,vmMethod
将作为$item.vmMethod
可用。如果您使用templateOptions作为最后一个参数,那么请确保在括号之间有一个空格,{ {
或jQuery模板会尝试将其解析为自己的。
你可以这样绑定它:
<img src="icon.png" data-bind="click: $item.vmMethod" />
另一种选择是在每个项上放置一个方法和对视图模型中任何相关内容的引用。看起来你正在探索这个选项。
最后,在KO 1.3中(希望在9月发布并很快进入测试版)将有一个很好的方法来使用jQuery的live/delegate功能并将其与viewModel连接(如本示例:http://jsfiddle.net/rniemeyer/5wAYY/)
另外,这篇文章的"在事件绑定中避免匿名函数"一节也可能对你有所帮助。如果您正在寻找使用动态选择的模板进行就地编辑的示例,那么这篇文章可能会有所帮助。
这是为那些询问如何将变量methods
(函数)传递给Knockout Template的人准备的。template的核心特性之一是使用可变数据,它可以是String
或function
。在KO
中,这些变量可以嵌入到data
或foreach
属性中,以便模板呈现。嵌入在data
或foreach
中的对象,无论是String
, function
等,都可以使用$data
在此上下文中访问。
您可以查看这段代码,看看它是否可以帮助您将函数传递给Knockout Template。
function ViewModel() {
this.employees = [
{ fullName: 'Franklin Obi', url: 'employee_Franklin_Obi', action: methodOne },
{ fullName: 'John Amadi', url: 'employee_John_Amadi', action: methodTwo }
],
this.methodOne = function(){ alert('I can see you'); },
this.methodTwo = function(){ alert('I can touch you'); }
}
ko.applyBindings(new ViewModel());
<ul data-bind="template: { name: employeeTemplate, foreach: employees }" ></ul>
<script type="text/html" id="employeeTemplate">
<li><a data-bind="attr: { href: '#/'+url }, text: fullName, click: $data.action"></a></li>
</script>
如果你想服务多个模板结构,你可以像这样在你的ViewModel
中引入一个switch方法,并使用as
属性为每个项目(雇员)引入别名。确保将开关键linkable
添加到项目对象中。
...
this.employees = [
{ fullName: 'Franklin Obi', linkable : false },
{ fullName: 'John Amadi', url: 'employee_John_Amadi', action: methodTwo, linkable : true }
],
this.methodLinkTemplate = function(employee){return employee.linkable ? "link" : "noLink"; } //this is a two way switch, many way switch is applicable.
...
则模板表单的id
将被命名为;
<ul data-bind="template: { name: employeeTemplate, foreach: employees, as: 'employee' }" ></ul>
<script type="text/html" id="noLink">
<li data-bind="text: fullName"></li>
</script>
<script type="text/html" id="link">
<li><a data-bind="attr: { href: '#/'+url }, text: fullName, click: $data.action"></a></li>
</script>
我没有运行过这个代码,但我相信这个想法可以节省一些人的时间。
- 将不在模型中的数据返回到mvc控制器
- 如何在不需要单击按钮的情况下获取选项的值
- Javascript不需要的关闭行为
- 删除客户端浏览器上不需要的内容
- 不允许在字段中输入不需要的字符
- 不需要的JSON响应
- 如何使图像适合TD,而不需要包装在不同的屏幕分辨率上
- 使用一个Javascript函数提交多个表单可以在FF中工作,而不需要其他浏览器
- 如何在不通过模型验证的情况下屏蔽文本输入中输入的字符
- jQuery自动完成显示不需要的动态html标记
- 在Knockout js中创建一个包含多行的表,而不需要推送
- AngularJs正在解码HTML字符(不需要)
- jQuery regex从文本链接-添加不需要的域到链接
- 防止从浏览器到应用商店的不需要的重定向
- 外部解析RSS提要,不需要像谷歌和服务器端那样的任何库
- 不需要的异步事件调度
- 如何将控制器's content属性设置为模型数组,而不需要相应的路由
- Spring MVC将模型数据从视图发送到控制器,而不需要表单
- 如何在knockoutjs中绑定点击处理程序到模板,而不需要全局视图模型
- 获取骨干模型父关系而不需要额外的请求