在挖空中引用对象构造函数外部视图模型的属性

Referencing properties of object constructor outside view model in knockout

本文关键字:视图 外部 模型 属性 构造函数 对象 引用      更新时间:2023-09-26

所以,我不完全确定如何表达这个问题,因为它是二合一的。我遇到了一个奇怪的问题,我有一个对象构造函数来从 HTML 表单创建新的"项目",然后在提交表单时将其推送到 observableArray 中。一切正常,但要引用相关的可观察量,我必须使用"值:项目标题"或"值:项目.whatever"。我还没有看到"value: NameOfConstructor.property"在我见过的任何例子中使用。我认为这是这样工作的,因为构造函数在我的视图模型之外。

我的问题是:有没有更好的方法来分配不在我的视图模型中的构造函数中的属性值?换句话说,有没有比"Project.title"更好或更正确的方法?我问的部分原因是我的代码中的一件事目前不起作用;KNOCKOUT ENABLE 属性在我的"新建项目"按钮上不起作用,即使"标题"输入框中写了某些内容,它也会保持禁用状态。我有一种感觉,因为它被写成data-bind='enable: Project.title',但我不知道还能怎么写。

我已经包含一个 jsfiddle 供参考,尽管由于外部依赖关系,它显然不起作用。https://jsfiddle.net/bmLh0vf1/1/

我的网页:

<form id='addBox' action='#' method='post'>
    <label for='pTitle'> Title: </label>
    <input id='pTitle' data-bind='value: Project.title' />
    <br/>
    <label for='pPriority'> Priority </label>
    <select id='pPriority' data-bind='options: priorityOptions, value: Project.priority'></select>
    <br/>
    <button data-bind='enable: Project.title, click: newProject'>New Project</button>
  </form>

还有我的Javascript:

function Project(title, priority) {
  this.title = ko.observable(title);
  this.priority = ko.observable(priority);
};

function ProjectViewModel() {
  var self = this;
  this.priorityOptions = ko.observableArray(['High', 'Medium', 'Low'])
  this.projectList = ko.observableArray([
    new Project('Create App', 'High')
  ]);
  this.newProject = function() {
    var np = new Project(Project.title, Project.priority);
    self.projectList.push(new Project(Project.title, Project.priority));
    console.log(self.projectList().length);
    if (self.projectList().length > 1) {
      console.log(self.projectList()[1].title());
    };
  }
};
var viewModel = new ProjectViewModel();
$(document).ready(function() {
  ko.applyBindings(viewModel);
});

最后,如果我错过了任何发布约定,或者我的代码特别糟糕,我深表歉意。我很新,还在自学。

您的代码正在new Project创建的对象上设置titlepriority属性,但稍后您希望在Project本身上看到这些属性。它没有它们; Project是函数,而不是new Project创建的对象。因此,Project.titleProject.priority 将为您提供undefined(而不是可观察的,因此对于value绑定不是有用的目标)。

相反,有一个你使用的"编辑"Project实例,将输入的value绑定到编辑的实例titlepriority,然后newProject抓取该实例并将其替换为一个新的新实例。

粗略地说,在 ProjectViewModel 的构造函数中:

this.editing = ko.observable(new Project());

Project更新为默认titlepriority

function Project(title, priority) {
  this.title = ko.observable(title || "");
  this.priority = ko.observable(priority || "Medium");
}

在绑定中:

<input id='pTitle' data-bind='value: editing().title' />
<select id='pPriority' data-bind='options: priorityOptions, value: editing().priority'></select>

newProject

var np = this.editing();
this.editing(new Project());

然后在添加到数组时使用 np(而不是另一个new Project)。

下面是一个简化的示例:

function Project(title, priority) {
  this.title = ko.observable(title || "");
  this.priority = ko.observable(priority || "Medium");
}
function ProjectViewModel() {
  var self = this;
  this.priorityOptions = ko.observableArray(["High", "Medium", "Low"]);
  this.projects = ko.observableArray();
  this.editing = ko.observable(new Project());
  this.addProject = function() {
    this.projects.push(this.editing());
    this.editing(new Project());
  };
}
ko.applyBindings(new ProjectViewModel(), document.body);
<div>
  <div>
    <label>
      Title:
      <input type="text" data-bind="value: editing().title, valueUpdate: 'input'">
    </label>
  </div>
  <div>
    <label>
      Priority:
      <select data-bind='options: priorityOptions, value: editing().priority'></select>
    </label>
  </div>
  <div>
    <button type="button" data-bind="click: addProject, enable: editing().title">Add Project</button>
  </div>
  <hr>
  <div>Projects:</div>
  <div data-bind="foreach: projects">
    <div>
      <span data-bind="text: title"></span>
      (<span data-bind="text: priority"></span>)
    </div>
  </div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>