使用Office-UI-Fabric-JS创建ChoiceFieldGroup时KnockoutJS绑定失效
我之前在开发Outlook加载项时,也碰到过Office-UI-Fabric-JS的ChoiceFieldGroup和KnockoutJS绑定不生效的问题——本质是Fabric初始化时会修改DOM结构,导致Knockout的绑定没被正确应用。下面是我亲测有效的解决步骤:
解决ChoiceFieldGroup与KnockoutJS绑定失效问题
1. 严格控制初始化顺序
Fabric的ChoiceFieldGroup组件初始化时会重新渲染DOM元素,如果先初始化Fabric再绑定Knockout,绑定会被覆盖。必须先完成Knockout绑定,再初始化Fabric组件:
// 先应用Knockout绑定到外层容器 ko.applyBindings(viewModel, document.getElementById('choicefield-container')); // 再初始化Fabric的ChoiceFieldGroup const choiceFieldEl = document.getElementById('choicefieldgroup'); new fabric['ChoiceFieldGroup'](choiceFieldEl);
2. 确保绑定目标不被Fabric替换
不要直接把Knockout绑定在Fabric会修改的根元素上,同时要给每个单选框正确设置checked和value绑定:
<div id="choicefield-container"> <div class="ms-ChoiceFieldGroup" id="choicefieldgroup" role="radiogroup"> <div class="ms-ChoiceFieldGroup-title"> <label class="ms-Label">Include email attachments:</label> </div> <!-- 每个选项的input必须绑定Knockout的checked和value --> <div class="ms-ChoiceFieldGroup-option"> <input type="radio" id="opt-all" name="attachments" class="ms-ChoiceField-input" data-bind="checked: selectedOption, value: 'all'"> <label for="opt-all" class="ms-ChoiceField-field"> <span class="ms-Label">All attachments</span> </label> </div> <div class="ms-ChoiceFieldGroup-option"> <input type="radio" id="opt-none" name="attachments" class="ms-ChoiceField-input" data-bind="checked: selectedOption, value: 'none'"> <label for="opt-none" class="ms-ChoiceField-field"> <span class="ms-Label">No attachments</span> </label> </div> </div> </div>
3. 同步Fabric事件与Knockout双向绑定
有时候Fabric的组件事件会和Knockout绑定不同步,你可以手动监听Fabric的change事件,更新ViewModel:
const choiceField = new fabric['ChoiceFieldGroup'](choiceFieldEl); choiceField.addEventListener('change', (e) => { viewModel.selectedOption(e.target.value); });
对应的ViewModel要正确定义observable:
const ViewModel = function() { this.selectedOption = ko.observable('all'); // 默认选中第一个选项 }; const viewModel = new ViewModel();
4. 动态生成选项的正确姿势
如果需要动态生成选项,用Knockout的foreach绑定生成DOM,不要用Fabric的API添加选项,之后再初始化Fabric组件:
<div class="ms-ChoiceFieldGroup" id="choicefieldgroup" role="radiogroup"> <div class="ms-ChoiceFieldGroup-title"> <label class="ms-Label">Include email attachments:</label> </div> <!-- Knockout foreach动态生成选项 --> <!-- ko foreach: attachmentOptions --> <div class="ms-ChoiceFieldGroup-option"> <input type="radio" class="ms-ChoiceField-input" data-bind="attr: {id: 'opt-' + $index(), name: 'attachments'}, checked: $parent.selectedOption, value: value"> <label class="ms-ChoiceField-field" data-bind="attr: {for: 'opt-' + $index()}"> <span class="ms-Label" data-bind="text: label"></span> </label> </div> <!-- /ko --> </div>
ViewModel对应的部分:
const ViewModel = function() { this.selectedOption = ko.observable('all'); this.attachmentOptions = ko.observableArray([ { value: 'all', label: 'All attachments' }, { value: 'none', label: 'No attachments' }, { value: 'selected', label: 'Selected attachments' } ]); };
内容的提问来源于stack exchange,提问作者vcRobe
相关产品推荐
相关产品推荐

