Knockout.js 可观测阵列中的可观测视图模型don';我不能在淘汰赛中工作

Knockout.js 可观测阵列中的可观测视图模型don';我不能在淘汰赛中工作,knockout.js,viewmodel,observable,Knockout.js,Viewmodel,Observable,我有一个简单的HTML标记,其中包含我的视图模型列表和模板。此外,我的viewmodel位于部分: <div class="container"> <div class="row"> <div class="col-md-6"> <div class="col-md-12"> <div class="panel panel-primary"> <div class="pa

我有一个简单的HTML标记,其中包含我的视图模型列表和模板。此外,我的viewmodel位于
部分:

<div class="container">
  <div class="row">
    <div class="col-md-6">
      <div class="col-md-12">
        <div class="panel panel-primary">
          <div class="panel-heading">
            Names
            <button type="button" class="btn btn-link" data-bind="click: addName">
              <span class="glyphicon glyphicon-plus"></span>
            </button>
          </div>
          <div class="panel-body">
            <ul class="list-group" id="namesList" data-bind="foreach: Names">
              <li class="list-group-item"><my-comp></my-comp></li>
            </ul>
          </div>
        </div>
      </div>
    </div>
    <div class="col-md-6">
      <div class="col-md-12">
        <pre data-bind="text: ko.toJSON(Names, null, 2)"></pre>
      </div>
    </div>
  </div>
</div>
<script type="text/html" id="fullNameTmpl">
  <p>First name: <strong data-bind="text: firstName"></strong></p>
  <p>Last name: <strong data-bind="text: lastName"></strong></p>

  <p>First name: <input data-bind="textInput: firstName" /></p>
  <p>Last name: <input data-bind="textInput: lastName" /></p>

  <p>Full name: <input data-bind="textInput: fullName"></p>

  <button data-bind="click: capitalizeLastName">Go caps</button>
</script>
<script>
  function AppViewModel() {
    var self = this;
    self.firstName = ko.observable("Bert");
    self.lastName = ko.observable("Bertington");

    this.fullName = ko.pureComputed({
      read: function () {
        return self.firstName() + " " + self.lastName();
      },
      write: function (value) {
        var lastSpacePos = value.lastIndexOf(" ");
        if (lastSpacePos > 0) { 
          self.firstName(value.substring(0, lastSpacePos)); 
          self.lastName(value.substring(lastSpacePos + 1)); 
        }
      },
      owner: self
    });

    self.capitalizeLastName = function () {
      var currentVal = this.lastName();        
      this.lastName(currentVal.toUpperCase()); 
    };
  }
  ko.components.register('my-comp', {
    viewModel: AppViewModel,
    template: { element: "fullNameTmpl" }
  });

  function NamesViewModel() {
    var self = this;

    self.Names = ko.observableArray();

    self.addName = function () {
      var vm = ko.observable(new AppViewModel());
      self.Names.push(vm);
    }
  }

  ko.applyBindings(new NamesViewModel());
</script>

名字
名字:

姓氏:

名字:

姓氏:

全名:

盖帽 函数AppViewModel(){ var self=这个; self.firstName=ko.可观察(“伯特”); self.lastName=ko.observable(“伯丁顿”); this.fullName=ko.pureComputed({ 读:函数(){ 返回self.firstName()+“”+self.lastName(); }, 写入:函数(值){ var lastSpacePos=value.lastIndexOf(“”); 如果(lastSpacePos>0){ self.firstName(value.substring(0,lastSpacePos)); self.lastName(value.substring(lastSpacePos+1)); } }, 所有者:self }); self.capitalLastName=函数(){ var currentVal=this.lastName(); this.lastName(currentVal.toUpperCase()); }; } ko.组件寄存器('my-comp'{ viewModel:AppViewModel, 模板:{element:“fullNameTmpl”} }); 函数名称ViewModel(){ var self=这个; self.Names=ko.observearray(); self.addName=函数(){ var vm=ko.observable(新的AppViewModel()); self.Names.push(vm); } } applyBindings(新名称视图模型());
它工作得很好,我可以添加一个项目到列表中,这些项目中的数据绑定也可以工作。当我添加新的
AppViewModel
时,我可以在
部分的
Names
数组中看到它。问题是,当我在嵌套的viewmodel中更改某些值时,比如键入新的姓氏,不管怎样,在
名称
数组中当前viewmodel的
部分中没有任何更改

<div class="container">
  <div class="row">
    <div class="col-md-6">
      <div class="col-md-12">
        <div class="panel panel-primary">
          <div class="panel-heading">
            Names
            <button type="button" class="btn btn-link" data-bind="click: addName">
              <span class="glyphicon glyphicon-plus"></span>
            </button>
          </div>
          <div class="panel-body">
            <ul class="list-group" id="namesList" data-bind="foreach: Names">
              <li class="list-group-item"><my-comp></my-comp></li>
            </ul>
          </div>
        </div>
      </div>
    </div>
    <div class="col-md-6">
      <div class="col-md-12">
        <pre data-bind="text: ko.toJSON(Names, null, 2)"></pre>
      </div>
    </div>
  </div>
</div>
<script type="text/html" id="fullNameTmpl">
  <p>First name: <strong data-bind="text: firstName"></strong></p>
  <p>Last name: <strong data-bind="text: lastName"></strong></p>

  <p>First name: <input data-bind="textInput: firstName" /></p>
  <p>Last name: <input data-bind="textInput: lastName" /></p>

  <p>Full name: <input data-bind="textInput: fullName"></p>

  <button data-bind="click: capitalizeLastName">Go caps</button>
</script>
<script>
  function AppViewModel() {
    var self = this;
    self.firstName = ko.observable("Bert");
    self.lastName = ko.observable("Bertington");

    this.fullName = ko.pureComputed({
      read: function () {
        return self.firstName() + " " + self.lastName();
      },
      write: function (value) {
        var lastSpacePos = value.lastIndexOf(" ");
        if (lastSpacePos > 0) { 
          self.firstName(value.substring(0, lastSpacePos)); 
          self.lastName(value.substring(lastSpacePos + 1)); 
        }
      },
      owner: self
    });

    self.capitalizeLastName = function () {
      var currentVal = this.lastName();        
      this.lastName(currentVal.toUpperCase()); 
    };
  }
  ko.components.register('my-comp', {
    viewModel: AppViewModel,
    template: { element: "fullNameTmpl" }
  });

  function NamesViewModel() {
    var self = this;

    self.Names = ko.observableArray();

    self.addName = function () {
      var vm = ko.observable(new AppViewModel());
      self.Names.push(vm);
    }
  }

  ko.applyBindings(new NamesViewModel());
</script>

我怎样才能制作出一个真正可观测的阵列?添加这样的组件最有利可图的方法是什么?我已经完成了嵌套viewmodel observable,但它似乎不起作用。

您的代码中有几个问题。问题不一定与可观测阵列有关,而是与组件的使用有关。列出了组件的用途。需要注意的一些事项:

  • 可观察的数组元素不需要设置为可观察的
    。因此无需执行
    var vm=ko.observable(新的AppViewModel())只需使用
    var vm=new-AppViewModel()并推到阵列上。但是,如果您想使用组件,那么这也不正确!我们正在做的基本上是两次更新AppViewModels!你知道为什么吗?在上面的行中显式执行一次,然后组件隐式执行一次。每次创建组件时,它都与AppViewModel关联—这就是注册组件时发生的情况
    
  • 组件与关联您可以将其视为一个具有自己属性、功能、计算结果等的迷你viewModel。因此,在您的情况下,您可能不需要使用组件->复制并将
    标记的内部内容粘贴到
  • 中,它应该可以正常工作
  • 我不确定这是否是你想要的答案,但这应该是你想要的。如果您愿意,您可以使用组件,但您必须进行更多的更改,并具有一点点不必要的复杂性。我擅自更改了变量名。我认为这样可能更合适。希望这有帮助

    编辑

    我已经编辑了代码片段以使用组件。这个具体实现的问题在于,组件现在通过名称observableArray与
    AppViewModel
    紧密耦合。在您的情况下,这可能没有问题,但通常会导致不希望的行为,尤其是当视图模型开始变得更大、更复杂时。当然,为了更好地解耦,您可以传入
    firstName
    lastName
    的未包装值,但随后您将回到原点,因为
    不会注册对名称所做的任何更改

    ko.components.register('my-comp'){
    viewModel:函数(参数){
    var self=这个;
    self.firstName=params.data.firstName
    self.lastName=params.data.lastName
    self.fullName=ko.pureComputed({
    读:函数(){
    返回self.firstName()+“”+self.lastName();
    },
    写入:函数(值){
    var lastSpacePos=value.lastIndexOf(“”);
    如果(lastSpacePos>0){
    self.firstName(value.substring(0,lastSpacePos));
    self.lastName(value.substring(lastSpacePos+1));
    }
    },
    所有者:self
    });
    self.capitalLastName=函数(){
    var str=self.lastName();
    self.lastName(str.toUpperCase());
    };
    },
    模板:{
    元素:“fullNameTmpl”
    }
    });
    var Name=function(){
    this.firstName=ko.可观察(“伯特”);
    this.lastName=ko.observable(“麦克伯丁顿”);
    }
    函数AppViewModel(){
    var self=这个;
    self.names=ko.observearray();
    self.addName=函数(){
    self.names.push(新名称());
    }
    }
    应用绑定(新的AppViewModel())
    
    
    名字
    加上花花公子
    
  • 名字:

    姓氏:

    名字:

    姓氏:

    全名:

    盖帽
  • 我认为