Knockout - 更改另一个viewmodel值

时间:2015-09-29 14:56:40

标签: javascript knockout.js

我在主版面中有一个标题,每个页面都有内容。主布局有自己的视图模型,每个页面中的每个内容都有自己的模型。

我遇到的问题是当我尝试更新用户配置文件时,由于两个视图模型已分离,因此更改未反映在标头中。当我更新配置文件时,如何使标题立即反映实例?

// Header View Model (serve from Master Layout)
function HeaderViewModel() {
  var self = this;
  self.headerusername = ko.observable();
  self.headerprofileImage = ko.observable(); // base 64 image
}
ko.applyBindings(new HeaderViewModel(), document.getElementById('header');

// Profile View Model (profile.html)
function ProfileViewModel() {
  var self = this;
  self.username = ko.observable();
  self.profileImage = ko.observable(); // base 64 image
}
ko.applyBindings(new ProfileViewModel(), document.getElementById('profile');
<!-- Header (serve from master layout) -->
<header id="header">
  <span data-bind="text:headerusername"></span>
  <img data-bind="attr: {src:headerprofileImage }">
</header>


<!-- Update profile (profile.html) -->
<form id="profile>
<input type="text" data-bind="value:username">
<input type="file" data-bind="value:profileImage">
<button type="submit">Save</button>
</form>

2 个答案:

答案 0 :(得分:1)

您可以使用ko.contextFor(element)从配置文件视图模型的方法中使用以下代码访问标题的binding context

var headerContext = ko.contextFor(document.getElementById('header'));
headerContext.$data.headerusername(self.username());
headerContext.$data.headerprofileImage(self.profileImage());

答案 1 :(得分:1)

我通常使用viewModel在其自己的模块中组织每个require.js

然后我将定义一个单独的组件模块(一个总是返回同一个类的实例的模块),称为ProfileService,作为共享的配置文件数据。

HeaderViewModelProfileViewModel都需要ProfileService

ProfileService可以包含与API接口的方法,并且可以公开usernameprofileImage个可观察对象。

HeaderViewModelProfileViewModel会从ProfileService导入共享的观察值:

档案ProfileService

define(function() {
    function ProfileService() {
        var self = this;
        self.username = ko.observable();
        self.profileImage = ko.observable();

        // logic to retrieve/update data
    }
    return new ProfileService();
});

档案ProfileViewModel

define(['path/to/ProfileService', 'path/to/knockout.js'], function(ProfileService, ko) {
    function ProfileViewModel() {
        var self = this;
        self.username = ProfileService.username;
        self.profileImage = ProfileService.profileImage;
    }
    ko.applyBindings(new ProfileViewModel(), document.getElementById('profile');
});

[编辑]

正如@Kal_Torak的评论中所建议的,你可以在没有require.js的情况下实现类似的东西,只需在全局命名空间中共享数据。类似的东西:

window.ProfileService = {
    username: ko.observable(),
    profileImage: ko.observable()
}

但如果您还不知道require.js,我建议您抽出时间尝试一下。