代码之家  ›  专栏  ›  技术社区  ›  BeemerGuy

如何在部分回发时保留脚本块?

  •  7
  • BeemerGuy  · 技术社区  · 15 年前

    这是我目前正在开发的一个webapp所面临的问题。
    因此,我没有用不相关的代码来混淆问题,而是在一个单独的、简化的webapp中重新创建了这个问题,这个webapp只演示了这个问题。
    希望这有助于找到解决办法。

    我有一个web用户控件,其内容是:

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

    它的代码隐藏只不过是 ShowAlertScript .
    这代表了我在大webapp中拥有的一个控件,它有两种模式: 输入模式 ,和 显示模式 . 进入时 输入模式 ,它有一个只有在那时才有用的大型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 ,它只需使用用户控件切换到第二个视图。 注意我是怎么得到的 显示警报脚本 已初始化为 true .
    潜在的输出是,由于我在用户控件中“显示警报脚本”,所以 AlertMe() 当您单击 input-button 元素,因为它是根据内联 if 陈述。

    如果你运行我给你的代码到目前为止,它不会工作。
    浏览器会说它看不到 提醒() 函数;据它所知,它是未定义的。 但是如果你把 UpdatePanel (或禁用 ScriptManager 的部分呈现),当您单击 开关 .

    我希望它可以部分回发,因为与页面的其他部分相比,这整件事是一个小部分,我不希望每次他们切换视图时都执行完整的回发。
    显然 脚本管理器 甚至不用为可能的更改重新呈现ascx文件。
    要么 脚本管理器 不够聪明,或者我缺少一个选项让它呈现 <script> 所以我可以在客户端调用它的方法。

    有人可能会提出一个可能的答案:“为什么不取出javascript,将它放在自己的.js文件中,让页面引用它,以便控件可以使用它呢?”
    这对我来说不太管用,因为脚本块会对该控件实例进行一些初始化和修改,而不是对页面上的所有其他实例。

    反过来,您可能还担心,如果我有多个控件实例,我最终会得到同一脚本的副本。不是真的,只有一个 输入模式 在任何给定的时间,页面中的这个控件,只是我在两个独立的视图中有这两个模式,我让用户在它们之间切换。

    谢谢你看了这么远=)
    感谢您的帮助和意见。

    2 回复  |  直到 15 年前
        1
  •  7
  •   Frédéric Hamidi    15 年前

    使脚本块正确支持 partial page rendering ,您必须在 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);
        }
    }
    

    (以上假设您拥有 AutoEventWireup 属性设置为 true @ Control 你的指令 ascx 文件。)

    另外,由于脚本是从用户控件注册的,但是 ScriptManager 位于页面本身,您可能需要添加 <asp:ScriptManagerProxy> 元素设置为控件标记,以便上面的操作生效。

        2
  •  1
  •   Dan Davies Brackett    15 年前

    updatepanel的内容实际上已经被AJAX框架设置更改了 innerHTML 在对应于UpdatePanel控件的div上。

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

    因此,不可能在部分回发期间执行内联(即声明性)JS。