knockoutjs中嵌套的可观察对象

时间:2012-07-23 13:01:46

标签: javascript knockout.js sammy.js

在基于Knockoutjs和Sammy.js的网络应用程序中,我有三个以父子方式相互依赖的观察者(第二个是第一个孩子,第三个孩子是第二个孩子)。我的HTML有三个部分,一次只能看到一个部分。每个部分都依赖于使用可见绑定的上述观察者之一。

我的网址方案的布局类似于/ #id-of-parent / id-of-child / id-of-grandchild(在Sammy.js中)。

如果我访问一个完整的URL(一个包含所有三个id),我会遇到observables的麻烦。在Sammy规则函数中,我首先加载并存储父项,然后是子项,最后是孙项(实际上是用户想要查看的数据)。问题是父元素和子元素的绑定也会被触发。

有没有办法避免触发绑定,还是有更好的方法来组织这样的应用程序?

以下是我的Sammy路线:

Sammy(function() {
  this.get('#study/:id', function() {
    self.studylist(null);
    self.currentStudy(Study.loadById(this.params.id));
  });

  this.get('#study/:id/variableGroups', function() {
    self.variableGroupList(self.currentStudy().variableGroups());
    self.currentVariable(null);
  });

  this.get('#study/:id/variable-group/:variableGroup/variables', function() {
    var groupId = this.params.variableGroup;
    $.ajax(apiUrl + "/variable-group/" + groupId, {
      type: "GET",
      async: false,
      cache: false,
      context: this,
      success: function(data) {
        if (!self.currentStudy()) {
          self.currentStudy(Study.loadById(this.params.id));
        }
        self.currentVariableGroup(new VariableGroup(data.variablegroup));
        self.variableList(self.currentVariableGroup().variables);
      }
    });
  });

  this.get('#study/:id/:variableGroupId/:variableId', function() {
    var variableId = this.params.variableId;
    $.ajax(apiUrl + "/variable/" + variableId, {
      type: "GET",
      async: false,
      cache: false,
      context: this,
      success: function(data) {
        if (!self.currentStudy()) {
          self.currentStudy(Study.loadById(this.params.id));
        }
        if (!self.currentVariableGroup()) {
          self.currentVariableGroup(VariableGroup.loadById(this.params.variableGroupId));
        }
        self.currentVariable(new Variable(data.variable));
      }
    });
  });

  this.get("", function() {
    self.currentStudy(null);
    self.currentVariableGroup(null);
    self.currentVariable(null);
    $.get(apiUrl + "/study/all", function(data) {
      var mappedStudies = $.map(data.studies, function(item, index) {
        return new Study(item);
      });
      self.studylist(mappedStudies);
    });
  });

  this.get('', function() { this.app.runRoute('get', "")});

}).run();

1 个答案:

答案 0 :(得分:1)

我不认为这是可能的,而且有充分的理由。它违反了数据绑定原则,无需通知订阅者即可更新可订阅者。我强烈建议您重构您的计划,以便更新currentStudycurrentVariableGroup不会造成不必要的副作用。让其他因素确定所需的效果,可能是activeTemplate可观察的。

在任何情况下,observable都为the source code。请注意,内部值是私有成员,无法从外部访问。它只能通过调用observable(通知订阅者)来设置。

ko.observable = function (initialValue) {
    var _latestValue = initialValue; //Value is in closure, inaccessible from outside

    function observable() {
        if (arguments.length > 0) {
            // Write

            // Ignore writes if the value hasn't changed
            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
                observable.valueWillMutate();
                _latestValue = arguments[0];
                if (DEBUG) observable._latestValue = _latestValue;
                observable.valueHasMutated();
            }
            return this; // Permits chained assignments
        }
        else {
            // Read
            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
            return _latestValue;
        }
    }