2

I have a problem that seems complicated that I don't know how to solve.

My single page application uses knockoutJS and I want to cache my view model every time one of my input values change on my view.

Where the problem lies is the complexity of my view model. To use local storage I need to stringify my object but it has recursive values. I have some logic to handle this and stringify my object. But when I try to parse the JSON string back to an object, I lose my functions.

function cacheForm(agency) {
        //var serialized = stringifyOnce(agency);
        //var serialized = amplify.store("Agency", agency);#
        //var obj = new Object();
        //obj.test = "test";

        value = agency;

        var cache = [];
        parsed = JSON.stringify(value, function (key, value) {
            if (typeof value === 'object' && value !== null) {
                if (cache.indexOf(value) !== -1) {
                    // Circular reference found, discard key
                    return;
                }
                    // Store value in our collection
                    cache.push(value);
            }

            return value;
        });

        //var jsonString = JSON.stringify(cache);


        //cache = null; // Enable garbage collection

        var parsedRecursive = "{" + '"data"' + ":" + parsed + "," + '"expires"' + ":" + null + "}"; // Build the string based on how amplify likes it

        var obj = eval('(' + parsed + ')')

        var obj = jQuery.parseJSON(parsedRecursive);
        //// Put the object into storage
        //localStorage.setItem('Agency', parsedRecursive);

        myData = JSON.parse(parsedRecursive, function (key, value) {
            var type;
            if (value && typeof value === 'object') {
                type = value.type;
                if (typeof type === 'string' && typeof window[type] === 'function') {
                    return new (window[type])(value);
                }
            }
            return value;
        });

        //// Retrieve the object from storage
        //    var retrievedObject = localStorage.getItem('Agency');

        //    var obj = jQuery.parseJSON(parsedRecursive);

        //var agency2 = mapping.fromJS(obj);
        //agency;
        //amplify.store("Agency", agency);
        //amplify.store("Obj", obj);
        //var store = amplify.store(); // Look at all items by not providing a key
    }
});

I tried using eval but this returned an object without my data. To help you understand this is what my view model looks like, which is the agency parameter of cachForm.

Also I tried using amplify but because of my view model structure I run into the same issue.

I have also attached some screenshots to show what happens with my viewmodel in the code.

My Agency view model before stringifying it using JSON format

My JSON string

My JSON string parsed and assigned to an object

4

2 回答 2

2

缓存整个 viewModel 不是一个好主意。viewModel 包含可观察对象、计算对象和函数或事件处理程序。您最好缓存视图模型数据,仅缓存原始数据。

关于序列化:

所以只需序列化视图数据(使用ko.mapping.toJSON):

  var json = ko.mapping.toJSON(viewModel);

为了重建正确的视图模型,最好有一个初始化函数。这是您的视图模型构造函数,即添加事件处理程序、函数和计算的函数。

  var initializer  = your_constructor;

您还需要确定缓存键,例如页面路径。

  var cacheItem = {data : json, constructor : initializer};
  cache[key] = cacheItem;

关于反序列化:

获取缓存项:

var cacheItem = cache[key];
var viewModel = JSON.parse(cacheItem.data);

现在 viewModel 包含原始数据。

viewModel = ko.mapping.fromJS(viewModel);

这些属性被转换为可观察的。

如果有构造函数调用它。

if(cacheItem.constructor)
     cacheItem.constructor.call(viewModel);

然后您的视图模型与您存储的一样。

我希望它有所帮助。

于 2013-08-17T09:35:53.860 回答
1

这是我在另一篇文章中发布的答案。它们都是相关的。

JSON.parse 返回具有空值的子对象,子值不被解析

于 2013-08-23T14:23:45.673 回答