How to clear/remove observable bindings in Knockout.js?

后端 未结 9 1849
忘了有多久
忘了有多久 2020-11-29 16:40

I\'m building functionality onto a webpage which the user can perform multiple times. Through the user\'s action, an object/model is created and applied to HTML using ko.app

相关标签:
9条回答
  • 2020-11-29 17:18

    Have you thought about this:

    try {
        ko.applyBindings(PersonListViewModel);
    }
    catch (err) {
        console.log(err.message);
    }
    

    I came up with this because in Knockout, i found this code

        var alreadyBound = ko.utils.domData.get(node, boundElementDomDataKey);
        if (!sourceBindings) {
            if (alreadyBound) {
                throw Error("You cannot apply bindings multiple times to the same element.");
            }
            ko.utils.domData.set(node, boundElementDomDataKey, true);
        }
    

    So to me its not really an issue that its already bound, its that the error was not caught and dealt with...

    0 讨论(0)
  • 2020-11-29 17:19

    I have found that if the view model contains many div bindings the best way to clear the ko.applyBindings(new someModelView); is to use: ko.cleanNode($("body")[0]); This allows you to call a new ko.applyBindings(new someModelView2); dynamically without the worry of the previous view model still being binded.

    0 讨论(0)
  • 2020-11-29 17:23

    For a project I'm working on, I wrote a simple ko.unapplyBindings function that accepts a jQuery node and the remove boolean. It first unbinds all jQuery events as ko.cleanNode method doesn't take care of that. I've tested for memory leaks, and it appears to work just fine.

    ko.unapplyBindings = function ($node, remove) {
        // unbind events
        $node.find("*").each(function () {
            $(this).unbind();
        });
    
        // Remove KO subscriptions and references
        if (remove) {
            ko.removeNode($node[0]);
        } else {
            ko.cleanNode($node[0]);
        }
    };
    
    0 讨论(0)
  • 2020-11-29 17:26

    I had a memory leak problem recently and ko.cleanNode(element); wouldn't do it for me -ko.removeNode(element); did. Javascript + Knockout.js memory leak - How to make sure object is being destroyed?

    0 讨论(0)
  • 2020-11-29 17:30

    I think it might be better to keep the binding the entire time, and simply update the data associated with it. I ran into this issue, and found that just calling using the .resetAll() method on the array in which I was keeping my data was the most effective way to do this.

    Basically you can start with some global var which contains data to be rendered via the ViewModel:

    var myLiveData = ko.observableArray();
    

    It took me a while to realize I couldn't just make myLiveData a normal array -- the ko.oberservableArray part was important.

    Then you can go ahead and do whatever you want to myLiveData. For instance, make a $.getJSON call:

    $.getJSON("http://foo.bar/data.json?callback=?", function(data) {
        myLiveData.removeAll();
        /* parse the JSON data however you want, get it into myLiveData, as below */
        myLiveData.push(data[0].foo);
        myLiveData.push(data[4].bar);
    });
    

    Once you've done this, you can go ahead and apply bindings using your ViewModel as usual:

    function MyViewModel() {
        var self = this;
        self.myData = myLiveData;
    };
    ko.applyBindings(new MyViewModel());
    

    Then in the HTML just use myData as you normally would.

    This way, you can just muck with myLiveData from whichever function. For instance, if you want to update every few seconds, just wrap that $.getJSON line in a function and call setInterval on it. You'll never need to remove the binding as long as you remember to keep the myLiveData.removeAll(); line in.

    Unless your data is really huge, user's won't even be able to notice the time in between resetting the array and then adding the most-current data back in.

    0 讨论(0)
  • 2020-11-29 17:31

    You could try using the with binding that knockout offers: http://knockoutjs.com/documentation/with-binding.html The idea is to use apply bindings once, and whenever your data changes, just update your model.

    Lets say you have a top level view model storeViewModel, your cart represented by cartViewModel, and a list of items in that cart - say cartItemsViewModel.

    You would bind the top level model - the storeViewModel to the whole page. Then, you could separate the parts of your page that are responsible for cart or cart items.

    Lets assume that the cartItemsViewModel has the following structure:

    var actualCartItemsModel = { CartItems: [
      { ItemName: "FirstItem", Price: 12 }, 
      { ItemName: "SecondItem", Price: 10 }
    ] }
    

    The cartItemsViewModel can be empty at the beginning.

    The steps would look like this:

    1. Define bindings in html. Separate the cartItemsViewModel binding.

        
          <div data-bind="with: cartItemsViewModel">
            <div data-bind="foreach: CartItems">
              <span data-bind="text: ItemName"></span>
              <span data-bind="text: Price"></span>
            </div>
          </div>
        
      
    2. The store model comes from your server (or is created in any other way).

      var storeViewModel = ko.mapping.fromJS(modelFromServer)

    3. Define empty models on your top level view model. Then a structure of that model can be updated with actual data.

        
          storeViewModel.cartItemsViewModel = ko.observable();
          storeViewModel.cartViewModel = ko.observable();
       
      
    4. Bind the top level view model.

      ko.applyBindings(storeViewModel);

    5. When the cartItemsViewModel object is available then assign it to the previously defined placeholder.

      storeViewModel.cartItemsViewModel(actualCartItemsModel);

    If you would like to clear the cart items: storeViewModel.cartItemsViewModel(null);

    Knockout will take care of html - i.e. it will appear when model is not empty and the contents of div (the one with the "with binding") will disappear.

    0 讨论(0)
提交回复
热议问题