gpt4 book ai didi

javascript - 如何在母版页和单个页面上应用 KnockoutJS?

转载 作者:行者123 更新时间:2023-11-28 08:40:06 24 4
gpt4 key购买 nike

我被困在一个较旧的 WebForms 项目上,我想知道是否有适合我的场景的推荐方法。

目标

  • 我在使用 KnockoutJS 绑定(bind)的模式对话框中有一个反馈表。
  • 我希望通过网站页脚中的链接在所有页面上提供反馈表。
  • 我希望其他几个页面也使用 knockout 以及他们自己的单独脚本和绑定(bind),无论模式中的反馈表单绑定(bind)如何。
  • 我有一些页面根本不使用 knockout 。我希望他们不必插入代码来完成此操作。
  • 如果可能的话,我想避免使用全局变量来支持命名空间的 JavaScript。
  • 本质上,我希望页面上的 View 模型和反馈 View 模型不知道彼此的存在。

  • 当前设置
  • 我们的页脚链接位于 Site.master 文件中,因此我放置了 Feedback.js 脚本和具有绑定(bind)的模式的 div。所以在母版页上,我调用 ko.applyBindings(vm, referenceToFeedbackDiv) ,它可以很好地连接反馈表。
  • 我们的各个页面偶尔会有一个 knockout View 模型,因此他们可能会调用 ko.applyBindings(vm),因为据他们所知,他们希望将 vm 应用于他们的整个页面。

  • 问题
  • 这会导致 knockout 冲突,因为通过 Site.master 调用将一个 vm 应用于反馈表单,而其后的页面将一个 vm 应用于整个正文。



  • 我怎样才能使这两个东西——一个跨所有使用 knockout 的页面的模式对话框和单独的 knockout 页面——协调工作?

    (当前)代码中的问题演示

    请记住,问题是我希望能够拥有一个仅适用于整个客户端站点的反馈 div 的反馈 VM,并且我希望能够应用其他不需要了解任何有关反馈的 VM虚拟机。

    母版页文件 (Site.Master) -- 摘录

    这是在每一页上:
    <div class="page">
    <div class="main">
    <asp:ContentPlaceHolder ID="MainContent" runat="server" />
    </div>
    </div>
    <div class="footer">
    &copy; <%=DateTime.Now.Year.ToString() %> Company, Inc. | <a href="/">Home</a> | <a
    href="/about.aspx">About</a> |

    <!-- begin feedback area -->

    <span id="FeedbackArea">
    <a data-bind="click: showModal">Feedback</a>

    <div id="feedback-modal" title="What's on your mind?">
    <div class="btn-group" id="feedbackButtonGroup">
    <button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
    <i class="fa fa-warning fa-2x fa-align-center"></i>

    <br />
    <span>Problem</span>

    </button>
    <button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
    <i class="fa fa-question-circle fa-2x fa-align-center"></i>

    <br />
    <span>Question</span>

    </button>
    <button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
    <i class="fa fa-lightbulb-o fa-2x fa-align-center"></i>

    <br />
    <span>Suggestion</span>

    </button>
    <button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
    <i class="fa fa-thumbs-o-up fa-2x fa-align-center"></i>

    <br />
    <span>Praise</span>

    </button>
    <button class="btn" data-bind="click: UpdateFeedbackType" style="padding-top: 6px;">
    <i class="fa fa-info-circle fa-2x fa-align-center"></i>

    <br />
    <span>General</span>

    </button>
    </div>
    <br />
    <br />
    <textarea rows="5" placeholder="Enter feedback here" data-bind="value: feedbackText, valueUpdate: 'afterkeydown'"></textarea>
    <br />
    <br />
    <button>Send Feedback</button>&nbsp;&nbsp;
    <button data-bind="click: CancelFeedback">Cancel</button>
    <h3>Other Information: </h3>

    <ul>
    <li><strong>Feedback Type:</strong> <span data-bind="text: feedbackType"></span></li>
    <li><strong>Current URL:</strong> <span data-bind="text: pageUserIsOn"></span></li>
    <li><strong>Current User: </strong><%=hdnLoggedInUsername.Value %></li>
    <li><strong>Current Client: </strong>[Not yet captured]</li>
    <li><strong>Current Tab: </strong>[Not yet captured]</li>
    </ul>
    </div>
    </span>
    <!-- End feedback area -->
    </div>

    Feedback.JS——这也包含在每个页面中

    ...FeedbackVM 的命名空间定义:
    var FeedbackNamespace = FeedbackNamespace || {};

    ..命名空间本身的定义:
    FeedbackNamespace = {
    ViewModel: function () {
    // etc. etc.
    }
    };

    ...以及 VM 变量的声明以及将其连接到 document.ready() :
    var FeedbackVM;
    $(document).ready(function () {
    FeedbackVM = new FeedbackNamespace.ViewModel();
    ko.applyBindings(FeedbackVM, $('#FeedbackArea')[0]);
    FeedbackVM.Start();
    log('FeedbackVM started');
    });

    其他没有 Knockout/JS 的页面

    其他页面上可能有也可能没有任何 javascript,更不用说 knockout 了。在这些页面上,FeedbackVM 当前运行良好。

    具有自己的 Knockout ViewModel 的页面

    这些页面将拥有自己的命名空间 JS 文件和自己的 document.ready()事件,它创建了一个虚拟机,比如 invoiceUploaderVM = new InvoiceUploader.ViewModel() ,然后调用 ko.applyBindings(invoiceUploaderVM) .

    这就是我们遇到麻烦的地方。

    更新:一种潜在的方法和一个小麻烦

    在 Site.master 页面中,我将整个页脚包裹在“stopBindings: true”div 中:
    <div data-bind="stopBindings: true">
    <div class="footer" id="footerDiv">
    <!-- Feedback Viewmodel stuff in here -->
    </div>
    </div>

    我已经定义了 stopBindings作为:
    ko.bindingHandlers.stopBindings = {
    init: function () {
    return { controlsDescendantBindings: true };
    }
    };

    我的 Feedback.js 文件作为全局 JS 文件的一部分加载到每个页面上,它具有:
    var FeedbackNamespace = FeedbackNamespace || {};
    FeedbackNamespace = {
    // defines viewmodel, etc. etc.
    };
    var FeedbackVM;
    $(document).ready(function () {
    FeedbackVM = new FeedbackNamespace.ViewModel();
    ko.applyBindings(FeedbackVM, $('#footerDiv')[0]);
    FeedbackVM.Start();
    log('FeedbackVM started');
    });

    这种方法效果很好——只要没有绑定(bind)其他 View 模型。在从我的母版页继承的页面上,我可能有类似的内容:
    $(document).ready(function () {
    'use strict';
    vm = new invoiceUploader.ViewModel();
    ko.applyBindings(vm);
    });

    我希望这是:
  • 设置应用于 div 的反馈 View 模型,停止其他 View 模型
  • 设置 invoiceUploader View 模型并将其应用到正文(然后由 stopBindings div 停止)

  • 但是,相反,我在加载子页面时出现错误:

    enter image description here

    注释行以应用反馈绑定(bind)使这项工作再次正常。

    我究竟做错了什么?

    最佳答案

    我想我会把你的模态视图模型放在一个全局对象中,然后做任何你需要做的事情除了应用绑定(bind)在共享脚本中:

    window.feedbackModal = {
    foo: ko.observable("Whatever you need to do here"),
    bar: ko.observable("assuming it can be done the same on every page")
    };

    然后在 Site.master
    <div class="feedback-modal" data-bind="with: feedbackModal">
    <p data-bind="text: foo"></p>
    <p data-bind="text: bar"></p>
    </div>

    在每个单独页面的脚本中:
    function ViewModel() {
    this.individualProperty = ko.observable(true);
    this.specificAction = function() { /* do something specific to this page */ };

    this.feedbackModal = window.feedbackModal;
    }

    ko.applyBindings(new ViewModel());

    所以 window.feedbackModal 可能是未定义的,它不会给你带来问题,但如果你 ko.applyBindings ,你必须有一个 feedbackModal View 模型中公开的属性,否则应用这些绑定(bind)时会出错。

    当然,还有更聪明的方法可以实现这个基本思想,以便最好地适应您的模式,但重要的是,正如您所知,您不能两次应用绑定(bind),因此您需要将该任务推迟到您的最具体的代码并将您的可重用代码公开给它。

    关于javascript - 如何在母版页和单个页面上应用 KnockoutJS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20613150/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com