淘汰——改变另一个视图模型值

Knockout - changing another viewmodel value

本文关键字:模型 视图 另一个 改变 淘汰      更新时间:2023-09-26

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

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

// 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>

您可以使用ko.contextFor(element)从概要视图模型的方法中访问标题的绑定上下文,使用如下代码:

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

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

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

HeaderViewModelProfileViewModel都需要ProfileService

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

HeaderViewModelProfileViewModel将从ProfileService中导入共享的可观察对象:

File ProfileService:

define(function() {
    function ProfileService() {
        var self = this;
        self.username = ko.observable();
        self.profileImage = ko.observable();
        // logic to retrieve/update data
    }
    return new ProfileService();
});

File 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,我建议你花点时间试一试。