knockout绑定继承了javascript对象

时间:2016-08-21 20:16:56

标签: javascript knockout.js

我有两种类型的活动:

function Activity(type, name) {
  this.Type = type
  this.Name = ko.observable(name)
}

function MeetingActivity(name, place) {
  Activity.call(this, 1500, name)
  this.Place = ko.observable(place)
}

function TeachingActivity(name, place, teacherId) {
  Activity.call(this, 1600, name)
  this.Place = ko.observable(place)
  this.TeacherId = ko.observable(teacherId)
}

并尝试将不同类型的活动绑定到某个容器,如下所示:

Activity:
<select data-bind='value: ActivityTypeId'>
  <option value='1500'>Meeting</option>
  <option value='1600'>Teaching</option>
</select>
<div data-bind='if: ActivityTypeId()==1500'>
  <div data-bind='with: Activity'>
    <span data-bind='text:Name'></span>
    <span data-bind='text:Place'></span>
  </div>
</div>
<div data-bind='if: ActivityTypeId()==1600'>
  <div data-bind='with: Activity'>
    <span data-bind='text:Name'></span>
    <span data-bind='text:Place'></span>
    <span data-bind='text:TeacherId'></span>
  </div>
</div>

我写了this fiddle来完成工作,但没有运气,我做错了什么?

2 个答案:

答案 0 :(得分:0)

您提供的小提琴错误来自subscribe ActivityTypeId方法。请注意,在创建function时,this会被当前的函数范围覆盖,因此Activity现在会丢失在您当前的this中。

function ViewModel() {
  this.ActivityTypeId = ko.observable(1500);
  this.Activity = ko.observable(new MeetingActivity('meeting 1', 'g12', 155))

  this.ActivityTypeId.subscribe(function(typeId) {
    if (typeId == 1500) this.Activity(new MeetingActivity('meeting 1', 'g12'))
    else if (typeId == 1600) this.Activity(new TeachingActivity('meeting 2', 'g13', 155))
  })
}

要修复它,您可以将其分配给另一个变量并通过它访问活动。像:

function ViewModel() {
  var self = this; //this is what i meant in assigning in another variable
  this.ActivityTypeId = ko.observable(1500);
  this.Activity = ko.observable(new MeetingActivity('meeting 1', 'g12', 155))

  this.ActivityTypeId.subscribe(function(typeId) {
    if (typeId == 1500) self.Activity(new MeetingActivity('meeting 1', 'g12')) //use self on accessing Activity
    else if (typeId == 1600) self.Activity(new TeachingActivity('meeting 2', 'g13', 155)) //use self on accessing Activity
  })
}

答案 1 :(得分:0)

original fiddle的问题在于您更新了Activity以包含新类型,并且显示更改为显示该类型,但是包含类型的时间和预期显示的类型不一样。

为了确保没有同步问题,您应该在Activity.Type(应该是可观察的)上进行测试。此外,不是让Activity成为可观察的并且订阅更改其值,而是将其设为计算值。

function Activity(type, name) {
  this.Type = ko.observable(type)
  this.Name = ko.observable(name)
}

function MeetingActivity(name, place) {
  Activity.call(this, 1500, name)
  this.Place = ko.observable(place)
}

function TeachingActivity(name, place, teacherId) {
  Activity.call(this, 1600, name)
  this.Place = ko.observable(place)
  this.TeacherId = ko.observable(teacherId)
}

function ViewModel() {
  var self = this
  self.ActivityTypeId = ko.observable(1500);
  self.Activity = ko.computed(
    function() {
      var typeId = +self.ActivityTypeId();

      if (typeId == 1500) return new MeetingActivity('meeting 1', 'g12');
      else if (typeId == 1600) return new TeachingActivity('meeting 2', 'g13', 155);
      else console.warn('Type ID:', typeId);
    });
}
var VM = null
$(document).ready(function() {
  VM = new ViewModel()
  ko.applyBindings(VM)
  console.log(VM)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
Activity:
<select data-bind='value: ActivityTypeId'>
  <option value='1500'>Meeting</option>
  <option value='1600'>Teaching</option>
</select>
<div data-bind="with: Activity">
  <div data-bind='if: Type()==1500'>
    <span data-bind='text:Name'></span>
    <span data-bind='text:Place'></span>
  </div>

  <div data-bind='if: Type()==1600'>
    <span data-bind='text:Name'></span>
    <span data-bind='text:Place'></span>
    <span data-bind='text:TeacherId'></span>
  </div>
</div>