如何在部分页面回传时保留脚本块?

8
这是我目前正在开发的Web应用程序中遇到的问题。
因此,我没有在问题中混杂无关的代码,而是在一个独立的、简化的Web应用程序中重新创建了这个问题,该应用程序仅演示了这个问题。
希望这有助于找到解决方案。

我有一个Web用户控件,其内容只有这些:

<% if (ShowAlertScript)
   { %>
       <script type="text/javascript">
           function AlertMe() 
           {
               alert('Hello World!');
           }
       </script>
<% } %>
<input type="button" onclick="AlertMe()" value="Say Hello" />

它的代码后台除了定义 ShowAlertScript 布尔值之外,没有其他内容。
这代表我在大型 Web 应用程序中拥有的一个控件,它具有两种模式:输入模式显示模式。当处于输入模式时,它有一个庞大的 JavaScript 代码块,只有在此时才有用;它执行一些很酷的操作来帮助用户输入信息。
这个控件在整体设计中的布局如下:
<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:MultiView ActiveViewIndex="0" runat="server" ID="mvw">
      <asp:View runat="server">
        <asp:Button runat="server" ID="btnSwitch" 
            OnClick="btnSwitch_Click" Text="Switch" />
      </asp:View>
      <asp:View runat="server">
        <uc:MyInputControl runat="server" ID="micInput" ShowAlertScript="true" />
      </asp:View>
    </asp:MultiView>
  </ContentTemplate>
</asp:UpdatePanel>

当单击 btnSwitch 时,它会简单地切换到带有用户控件的第二个视图。请注意我已将ShowAlertScript初始化为true
潜在的输出是由于我在用户控件中“显示警报脚本”,所以当您单击input-button元素时,AlertMe()函数将执行,因为它根据内联if语句编写出来。
如果按原样运行我给你的这段代码,它不会起作用。
浏览器将说它看不到AlertMe()函数;它按照它所知道的方式是未定义的。但是,如果您删除UpdatePanel(或禁用ScriptManager的部分渲染),那么当您单击btnSwitch时,它将在完整的提交回发上正常工作。
我希望它能在部分回发上运行,因为相对于页面的其余部分,整个东西都很小,我不想每次切换视图时都进行完整的提交回发。
显然,ScriptManager甚至不费心重新渲染ascx文件以进行可能的更改。
要么ScriptManager不够聪明,要么我错过了一个选项让它渲染<script>,以便我可以在客户端调用其方法。
有人可能会提出的一个潜在答案是“为什么不将javascript取出来,放入自己的.js文件中,并使页面引用它,以便它对控件可用?”这对我来说并不真正起作用,因为脚本块执行了一些初始化和修改,与页面上所有其他控件实例无关。
接下来,您可能还担心如果我有多个控件实例,我最终会得到同样脚本的副本。不是真的;页面中任何时候只会有一个此控件的,只是我将这两种模式放在两个不同的视图中,并允许用户在它们之间切换。
感谢您阅读到这里 =)
感谢任何帮助和输入。
2个回答

8

为了使您的脚本块正确支持部分页面渲染, 您需要在用户控件的PreRender阶段使用ScriptManager.RegisterClientScriptBlock()方法进行注册:

protected void Page_PreRender(object sender, EventArgs e)
{
    if (ShowAlertScript) {
        ScriptManager.RegisterClientScriptBlock(this,
            typeof(YourUserControl), "AlertScript",
            @"function AlertMe() 
              {
                  alert('Hello World!');
              }",
            true);
    }
}

(以上假设您在ascx文件的@ Control指令中将AutoEventWireup属性设置为true。)
另外,由于脚本是从用户控件注册的,但您的ScriptManager位于页面本身上,因此您可能需要在控件标记中添加一个<asp:ScriptManagerProxy>元素才能使上述内容起作用。

1

UpdatePanels实际上通过AJAX框架设置对应于UpdatePanel控件的div的innerHTML来更改其内容。

当设置innerHTML时,不执行脚本元素。

因此,在部分回发期间没有行内(即声明式)JS可执行的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接