简体   繁体   English

如果模型不是顶级对象,如何将模型绑定到模型中?

[英]How to bind a model to knockout if the model is not a top-level object?

I am learning knockout.js. 我正在学习knockout.js。 I did one example earlier , which I am trying to modify in two ways: 我之前做了一个示例 ,尝试通过两种方式进行修改:

  1. I organized the code to minimize global scope so there's just one top-level object inside the window object and I put everything including my model in there. 我组织了代码以最小化全局范围,因此window对象中只有一个顶级对象,并且将包括模型在内的所有内容都放在了其中。

  2. I wanted to see if the text: binding changes the view when the model changes if the model is not an observable. 我想看看如果模型不可观察时,当模型更改时, text:绑定是否会更改视图。 For a finer elaboration of this idea, please see the comments in the HTML code below. 有关此想法的详细说明,请参见下面的HTML代码中的注释。

However, when I run this bit of code, I get a ReferenceError: friend is not defined. 但是,当我运行这段代码时,出现了ReferenceError: friend is not defined.

I am assuming it is because of the fact that my model object is no longer a top-level member of the window object. 我假设是因为我的model对象不再是window对象的顶级成员。

Is it possible to have a model hierarchy like this and have it work with knockout? 是否可以具有这样的模型层次结构并使其与剔除一起工作?

1a.html 1a.html

<html>
    <head>
        <meta charset="utf-8"/>
        <script type='text/javascript' src='knockout-3.4.0.js'></script>
    </head>

    <!-- The purpose of this program is to find out whether just a 
        text: binding also changes the display / view if the model changes.
        Meaning if I explicitly do not create an observable out of a model property
        and use only a text: binding, does the property still behave like an observable?

        To do this, I am using the same code as 1.html and 1.js, 
        except for one change. I am adding another set of textboxes
        in which I will type in a new first name and last name.
        Then, I will click the "Update Name" button
        in whose listener, I will update the model properties friend.firstName
        and friend.lastName.

        Then, I'd like to see if the text box values for txtFirstName and txtLastName
        change.
        -->
    <body>

        <form id = "frm" name = "frm">
            <fieldset>
                <legend>Your friend's basic information:</legend>

                <div>
                    <label for = "FirstName">First Name</label>
                    <input type = "text" name = "FirstName" id = "txtFirstName" data-bind = "value: friend.firstName" />
                </div>

                <div>
                    <label for = "LastName">Last Name</label>
                    <input type = "text" name = "LastName" id = "txtLastName" data-bind = "value: friend.lastName" />
                </div>


                    <fieldset>
                        <legend>New Information:</legend>

                        <div>
                            <label for = "NewFirstName">New Value for First Name</label>
                            <input type = "text" name = "NewFirstName" id = "txtNewFirstName" />
                        </div>

                        <div>
                            <label for = "NewLastName">New Value for Last Name</label>
                            <input type = "text" name = "NewLastName" id = "txtNewLastName" />
                        </div>
                    </fieldset>

                <div>
                    <input type = "button" value = "Update Name" id = "btnUpdateName" name = "Save" />
                </div>
            </fieldset>

        </form>

        <script type='text/javascript' src='1a.js'></script>
    </body>
</html>

1a.js 1a.js

var ThisDocument = function()
{
    this.model = 
    {
        friend : 
        {
            firstName : 'Sathyaish',
            lastName : 'Chakravarthy'
        }
    };

    this.init = function()
    {
        wire(window, "load", wireElementHandlers);
    };

    function wire(element, eventName, listener)
    {
        var ie = document.all ? true : false;

        if (!element) throw new Error("Element " + element + " not found.");

        if (ie)
        {
            element.attachEvent("on" + eventName, listener);
        }
        else
        {
            element.addEventListener(eventName, listener, false);
        }
    };


    function wireElementHandlers()
    {
        var btnUpdateName = document.getElementById('btnUpdateName');
        wire(btnUpdateName, "click", changeName);

        ko.applyBindings(this.model);
    };

    function changeName(event)
    {
        var firstName = document.getElementById('txtNewFirstName').value;
        var lastName = document.getElementById('txtNewLastName').value;

        this.model.friend.firstName = firstName;
        this.model.friend.lastName = lastName;
    };
};

var thisDocument = new ThisDocument();
thisDocument.init();

Making the Model a Top-Level Object Inside Window 使模型成为窗口内的顶级对象

If, however, I make the model a top-level member inside the window object, the code works fine and I get to know the answer to my question described in the HTML comments above and in the bullet point #2 above. 但是,如果我使模型成为window对象内的顶级成员,则代码可以正常工作,并且我知道上面HTML注释和上面第2点中描述的问题的答案。

The answer is: no. 答案是不。 Without having an observable, a simple text: binding does not update the view when the model changes. 如果没有可观察的内容,则简单的text:绑定不会在模型更改时更新视图。

Here is the code with the model as the top-level object: 这是将模型作为顶层对象的代码:

1a.js 1a.js

this.model = 
{
    friend : 
    {
        firstName : 'Sathyaish',
        lastName : 'Chakravarthy'
    }
};

var ThisDocument = function()
{
    this.init = function()
    {
        wire(window, "load", wireElementHandlers);
    };

    function wire(element, eventName, listener)
    {
        var ie = document.all ? true : false;

        if (!element) throw new Error("Element " + element + " not found.");

        if (ie)
        {
            element.attachEvent("on" + eventName, listener);
        }
        else
        {
            element.addEventListener(eventName, listener, false);
        }
    };


    function wireElementHandlers()
    {
        var btnUpdateName = document.getElementById('btnUpdateName');
        wire(btnUpdateName, "click", changeName);

        ko.applyBindings(model);
    };

    function changeName(event)
    {
        var firstName = document.getElementById('txtNewFirstName').value;
        var lastName = document.getElementById('txtNewLastName').value;

        model.friend.firstName = firstName;
        model.friend.lastName = lastName;
    };
};

var thisDocument = new ThisDocument();
thisDocument.init();

Therefore, my suspicion is that the this pointer is being messed up. 因此,我怀疑this指针被弄乱了。

Is there an overload for the applyBindings method or may be another way if not an overload that allows me to tell knockout to use a particular object as the this parameter when binding a model? applyBindings方法是否有重载,或者如果不是重载,则可能是另一种方式,它允许我告诉敲除绑定模型时使用特定对象作为this参数?

For eg 例如

var MyDocument = function()
{
  var model = 
  {
    friend : { firstName: 'Sathyaish', lastName: 'Chakravarthy' }
  };

  this.init : function()
  {
    ko.applyBindings(this.model /*, but this may lead knockout
    to not be able to discover my model, as my experience so far
    shows. I need to recalibrate the 'this' pointer so knockout
    knows to look for the model object inside whatever I tell it to, 
    i.e. inside an instance of the MyDocument class and not inside
    whatever the this pointer happens to reference when knockout 
    is performing the binding. */);
  };
}

var myDocument = new MyDocument();
myDocument.init();

I think you really need the mapping plugin and to change/put a value will need to do: 我认为您确实需要映射插件,并且要更改/输入值需要执行以下操作:

model.friend.firstName(firstName)

I will try your code later and if is necessary i will edit my answer. 稍后,我将尝试您的代码,如有必要,我将编辑我的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM