如何保持从服务器加载的数据不被“空白”?通过Knockout JS加载页面

How do I keep data loaded from the server from getting "blanked out" by Knockout JS on page load?

本文关键字:加载 通过 Knockout 空白 JS 服务器 何保持 数据      更新时间:2023-09-26

我试图理解Knockout JS。令我困扰的是,我绑定的数据被消去了。这很烦人,因为我想显示从服务器检索到的数据。

一个例子:

Name: <span class="name"><?php echo $data->name; ?></span>
结果是:Name: John B

现在,如果我将这个与Knockout绑定到这个:

Name: <span data-bind="text: name" class="name"><?php echo $data->name; ?></span>
结果是:Name:

JS将是这样的:

var viewModel = {
    name: ko.observable() // Initially blank <--- this is the culprit
};
ko.applyBindings(viewModel); 

那么我需要做些什么来显示/保存数据呢?
Knockout就不能像Angular JS那样保存数据吗?

注意我使用Yii MVC框架来处理很多服务器端东西。使用它在页面加载时加载数据,节省了我编写大量JS Ajax代码的时间。我想使用Knockout来减少我拥有的jQuery代码的数量,而不是添加到它:)

另一种方法是构造视图模型,将服务器上的值直接提供给可观察对象。

<span data-bind="text: name"></span>

var viewModel = {
  name: ko.observable(<?php echo $data->name; ?>);
};
ko.applyBindings();

试图从HTML中初始化一个可观察对象的值是很危险的,因为有很多方法可以重置可观察对象的值,特别是当一个元素包含在一个使用显式/隐式模板的父绑定中,比如if绑定。

<div data-bind="if: someFlag">
    <span data-bind="text: name">John Doe</span>
<div>

在上面的例子中,每次someFlag值从false变为true时,span元素上的文本绑定将被重新初始化。

这里有两种方法可以尝试避免两次声明数据(注意它们不直接提供将数据保存在html文件中的方法):

解决方案1:把你的默认模型放在一个单独的js/php文件

创建一个php文件

var defaultVm = {
    name: '<?php echo $data->name; ?>',
    anyVariable: '<?php echo $data->anyVariable; ?>'
}

然后你把这个php文件作为一个js文件,用它初始化你的视图模型:

var viewModel = {
    name: ko.observable(defaultVm.name);
    anyVariable: ko.observable(defaultVm.anyVariable);
};
ko.applyBindings(viewModel); 

方案二:使用ko。映射插件

创建一个php文件

{
    "name": "<?php echo $data->name; ?>",
    "anyVariable": "<?php echo $data->anyVariable; ?>"
}

然后在js中,你可以使用ko。映射插件:

var viewModel = function (data) {
    ko.mapping.fromJS(data, {}, this);
};
ko.applyBindings(new viewModel(getYourPhpFileTheWayYoulike)); 

这允许你异步获取你的数据(如果你想的话),如:

$.getJSON("yourphpmodelurl", function (data) {
    ViewModelInstance = new viewModel(data);
    ko.applyBindings(ViewModelInstance);
}

您可以创建一个自定义绑定处理程序来做到这一点:

ko.bindingHandlers.textInitialized= {
    init: function (element, valueAccessor) {
        valueAccessor()(element.innerHTML); // get the current value and update the observable
    },
    update: function (element, valueAccessor) {
        var value = valueAccessor();
        element.innerHTML = ko.utils.unwrapObservable(value);
    }
};

然后你可以像这样绑定你的视图模型:

Name: <span data-bind="textInitialized: name" class="name">John B</span>

EDIT after jsFiddle:

您已经在jsFiddle中创建了一个完全不同的东西。几件事:

    在你的autocomplethandler中,你使用我提供的代码,但是:你想设置"value"属性,而不是innerHTML,所以你应该把它改成element.value而不是element.innerHTML。你有一个自动完成绑定和一个值绑定。它们都在value属性上工作(如果您遵循我的第一个注释)。第二个将在第一个之后出现,并撤销该更改。

我已经修改了小提琴与这些变化:http://jsfiddle.net/P8N77/24/