我为CodeMirror创建了一个自定义绑定。自定义绑定使用简单的字符串,但在foreach
绑定内,它不再被初始化,尽管添加了所有HTML和CSS。
这是一个工作片段:
var viewModel = {
options: {
mode: "text/x-csharp",
lineNumbers: true
},
//IT WORKS
fileContent: "public sealed class DictionaryAttribute : Attribute{}1",
//IT DOESN'T WORK
codes: ["public sealed class DictionaryAttribute : Attribute{}1"]
};
ko.bindingHandlers.codemirror = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var options = viewModel.options || {};
options.value = ko.unwrap(valueAccessor());
var editor = CodeMirror(element, options);
editor.on('change', function(cm) {
var value = valueAccessor();
value(cm.getValue());
});
element.editor = editor;
}
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<link href="https://codemirror.net/lib/codemirror.css" rel="stylesheet" />
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="https://codemirror.net/mode/clike/clike.js"></script>
<!-- This works -->
<div data-bind="codemirror: fileContent" style="width: 700px; height: 100px"></div>
<!-- This doesn't work -->
<div data-bind="foreach: codes">
<div data-bind="codemirror: $data" style="width: 700px; height: 100px"></div>
</div>
答案 0 :(得分:2)
问题在于自定义绑定中的var options = viewModel.options || {};
。 viewModel
参数是指上下文中的当前$data
,而不是applyBindings
中使用的viewModel。它适用于一个简单的字符串,因为在这种情况下,viewModel
参数 是您传递给viewModel
的主applyBidnigs
对象。在foreach
内,viewModel
将是您阵列中的每个$data
。
因此,请改用bindingContext
参数的$root
属性。此外,在Knockout 3.x中不推荐使用viewModel
参数:
像这样:
var options = bindingContext.$root.options || {};
更新了代码段:
var viewModel = {
options: {
mode: "text/x-csharp",
lineNumbers: true
},
//IT WORKS
fileContent: "public sealed class DictionaryAttribute : Attribute{}1",
//IT DOESN'T WORK
codes: ["public sealed class DictionaryAttribute : Attribute{}1"]
};
ko.bindingHandlers.codemirror = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var options = bindingContext.$root.options || {};
options.value = ko.unwrap(valueAccessor());
var editor = CodeMirror(element, options);
editor.on('change', function(cm) {
var value = valueAccessor();
value(cm.getValue());
});
element.editor = editor;
}
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<link href="https://codemirror.net/lib/codemirror.css" rel="stylesheet" />
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="https://codemirror.net/mode/clike/clike.js"></script>
<div data-bind="codemirror: fileContent" style="width: 700px; height: 100px"></div>
<div data-bind="foreach: codes">
<div data-bind="codemirror: $data" style="width: 700px; height: 100px"></div>
</div>
以上代码适用于您的情况。但是,绑定期望顶级$root
对象具有options
属性。另一种方法是在绑定中添加codeMirrorOptions
参数并完全删除该依赖项。
var viewModel = {
options: {
mode: "text/x-csharp",
lineNumbers: true
},
//IT WORKS
fileContent: "public sealed class DictionaryAttribute : Attribute{}1",
//IT DOESN'T WORK
codes: ["public sealed class DictionaryAttribute : Attribute{}1"]
};
ko.bindingHandlers.codemirror = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// use allBindings
var options = ko.unwrap(allBindings().codeMirrorOptions) || {};
options.value = ko.unwrap(valueAccessor());
var editor = CodeMirror(element, options);
editor.on('change', function(cm) {
var value = valueAccessor();
value(cm.getValue());
});
element.editor = editor;
}
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<link href="https://codemirror.net/lib/codemirror.css" rel="stylesheet" />
<script src="https://codemirror.net/lib/codemirror.js"></script>
<script src="https://codemirror.net/mode/clike/clike.js"></script>
<div data-bind="codemirror: fileContent, codeMirrorOptions:options" style="width: 700px; height: 100px"></div>
<div data-bind="foreach: codes">
<div data-bind="codemirror: $data, codeMirrorOptions:$parent.options" style="width: 700px; height: 100px"></div>
</div>
在这种情况下,自定义绑定独立于viewModel。即使您的viewModel
不是$root
对象,自定义绑定也会有效。