3

我目前正在开发一个应用程序,该应用程序需要单击按钮在浏览器中打开一个新窗口,然后当用户在主窗口上的文本框中键入时,新窗口将相应更新。我以前使用过淘汰赛,但由于某种原因,我在更新第二个 Windows 视图时遇到了问题。这是我当前的代码。

//main.js
   $(function () {
        var viewModel = new ViewModel();
        ko.applyBindings(viewModel);
        var newwindow;
        $("#new-window-btn").click(function () {
            newwindow = window.open("a/path/to/newwindow.html", "New Window","status=1,width=350,height=350");
            newwindow._ViewModel = viewModel;
        });

    });

    function ViewModel() {
        var self = this;
        self.textbox = ko.observable("");
    };

这是 index.html 并包含一个非常基本的按钮,它将打开新窗口,一个用户将输入的文本框和一个 span 标签,以显示我没有疯。

//index.html
<div id="new-window-btn" class="btn">new window</div>
<textarea cols="3" rows ="3" data-bind="value:textbox,valueUpdate:'afterkeydown'"></textarea>
<span data-bind="text: textbox"></span>

这是当用户单击 index.html 中的新窗口按钮时弹出的第二个窗口的代码

//newwindow.html
    <script type="text/javascript">
        $(function () {
            var viewModel = window._ViewModel;
            ko.applyBindings(viewModel);
            $("#alert-viewModel").click(function () {
                alert(viewModel.textbox());
            });
        });
    </script>
<span data-bind="text:textbox()"></span>
<div id="alert-viewModel" class="btn">show texbox value</div>

当用户在主页上的文本框中输入内容时,该页面上的 span 标签会自动更新。当用户单击新窗口按钮时,新窗口会弹出用户刚刚输入的文本,当用户继续在主窗口文本框中键入时,辅助窗口中的 span 标签不会更新。但是,当用户按下“显示 texbox 值”按钮时,文本会显示在警告框中,并且已更新!所以我的问题是为什么我在第二个窗口中的 span 标签在 ViewModel 明显已经更新时没有更新(因为从“显示 texbox 值”按钮显示的值)。

快速评论:出于某种原因,通过 window.open("somepath"); 访问文件 在这个问题的上下文中实际上不能正常工作。我发现我需要在一个小型 HTTP 服务器中加载新的窗口文件,并使“somepath”成为一个实际的 url。(这就是为什么这个问题没有附加一些示例代码的原因)。

4

2 回答 2

9

ko如果两个窗口共享相同的视图模型,它们也必须共享相同的实例。那是因为用一个 Knockout 实例创建的 observables 不能在另一个实例上工作。

这是一个使用 的示例iframe,但相同的原则适用于window.open

家长:http: //jsfiddle.net/eZMTM/;孩子:http: //jsfiddle.net/GrXhv/7/

父代码:

childWindow = ...;
childWindow.initChild(ko, viewModel);

子代码:

window.initChild = function(ko, viewModel) {
    window.ko = ko;
    ko.applyBindings(viewModel, document.body);
}
于 2013-03-26T10:50:52.920 回答
1

正如迈克尔所提到的,您可以将绑定应用于打开的窗口的主体,如下所示:

var mywindow = window.open('', '', 'height=400,width=600');
mywindow.document.write('<input id="testText" type="text" data-bind="textInput: text1"/>');
ko.applyBindings(viewmodel, mywindow.document);

如果您想尝试一个带有弹出窗口的工作示例,这里有一个 fiddle

我在下面的代码段中附加了完整的代码,但是由于 stackoverflow 沙箱不允许弹出窗口,它会在此处的代码段中失败。仍然在帖子中保留代码似乎很有价值。

PS:虽然老了,但这是我在谷歌上第一次点击,所以我认为添加一个工作示例会有所帮助......

$(function() {
  var viewModel = function() {
    var self = this;

    //creating our observables
    self.text1 = ko.observable("Hello World ...");
    self.text2 = ko.observable("... how's it going");

    //The magic happens here
    self.newKOWindow = function() {
      var mywindow = window.open('', '', 'height=400,width=600');

      //just adding the html boilerplate Part1
      mywindow.document.write('<html><head><title>The KO Popup</title>');
      mywindow.document.write('</head><body>');

      //manually creating the input the window      
      mywindow.document.write('<div class="dontCopyMe">');
      mywindow.document.write('<h2>A Manually created input which is bound</h2>');
      mywindow.document.write('<input id="testText" type="text" data-bind="textInput: text1"/>');

      //just adding the html boilerplate Part2      
      mywindow.document.write('</div>');
      mywindow.document.write('</body></html>');
      mywindow.document.close();

      //just copy our inputs into the new window
      $(".copyMe").clone().appendTo(mywindow.document.body);

      //copy our css
      $("#compiled-css").clone().appendTo(mywindow.document.head);

      //bind the viewmodel
      window.ko = ko;
      ko.applyBindings(self, mywindow.document.body);

      return true;
    }
  };

  model = new viewModel();
  ko.applyBindings(model);

});
.copyMe,
.dontCopyMe {
  border: 3px dashed limegreen;
  padding: 0.5rem;
  margin: 0.5rem;
  max-width: 30rem;
}

.dontCopyMe {
  border-color: grey;
}

h2 {
  margin: 0 0 0.5rem;
  font-size: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<body>
  <div>
    <div class="copyMe">
      <h2>Our inputs (will be copied into the popup window)</h2>
      <input type="text" data-bind="textInput: text1" />
      <input type="text" data-bind="textInput: text2" />
    </div>
    <div class="copyMe">
      <h2>Same Inputs just to show this is working :)</h2>
      <input type="text" data-bind="textInput: text1" />
      <input type="text" data-bind="textInput: text2" />
    </div>
    <input id="NWO" type="button" value="NEW KO WIN OPEN" data-bind="click: newKOWindow" />
  </div>
</body>

于 2019-12-12T10:00:16.840 回答