Knockout.js ViewModel报Cannot read properties of undefined错误解决
报错根因
报错由两个核心问题导致:
- 初始化顺序错误:在
viewModel对象字面量内部访问viewModel变量时,整个对象还未完成创建和赋值,此时viewModel值为undefined,自然无法读取loadingVisible属性。 - 响应式逻辑错误:就算绕开初始化顺序问题,写
viewModel.loadingVisible()是直接执行observable拿到了初始静态布尔值,后续loadingVisible更新时,loadOptions.visible不会同步变化,绑定会完全丢失响应式能力。
可行解决方案
方案1:拆分初始化步骤(最适配现有写法,推荐)
不要在对象字面量里一次性定义所有属性,先初始化核心的observable,再追加定义loadOptions。注意visible属性直接传observable本身,不要加括号调用,DevExtreme的KO绑定原生支持识别observable,会自动追踪依赖更新组件:
var viewModel = { loadingVisible: ko.observable(false) }; // 对象初始化完成后再定义loadOptions viewModel.loadOptions = { visible: viewModel.loadingVisible, showIndicator: true, showPane: true, shading: true, hideOnOutsideClick: false, shadingColor: 'rgba(0,0,0,0.4)' }; return viewModel;
方案2:构造函数写法
如果习惯用构造函数模式写viewModel,可以通过this访问实例属性,避开变量未初始化的问题:
var ViewModel = function() { this.loadingVisible = ko.observable(false); this.loadOptions = { visible: this.loadingVisible, showIndicator: true, showPane: true, shading: true, hideOnOutsideClick: false, shadingColor: 'rgba(0,0,0,0.4)' }; }; return new ViewModel();
方案3:直接在绑定中写配置
如果配置项不多,可以不单独在js里定义loadOptions对象,直接在HTML绑定中书写配置,直接引用作用域内的loadingVisible即可:
<div class="loadpanel" data-bind="dxLoadPanel: { visible: loadingVisible, showIndicator: true, showPane: true, shading: true, hideOnOutsideClick: false, shadingColor: 'rgba(0,0,0,0.4)' }"></div>
注意事项
- 给DevExtreme组件的KO绑定传配置值时,凡是需要响应式更新的属性,直接传入
ko.observable引用即可,不需要手动加括号调用取值。 - 对象字面量的解析赋值是同步完成的,解析过程中引用的外部变量如果指向对象本身,会因为还未完成赋值拿到
undefined。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

