MVC 3,部分意见和jQuery重用,没有发生冲突的DOM [英] MVC 3, reuse of partial views and jquery, without conflicting the DOM

查看:149
本文介绍了MVC 3,部分意见和jQuery重用,没有发生冲突的DOM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为我还是新的MVC 3和jQuery,我想知道一个最佳实践解决方案,以下是如何可以解决的:

As i am still new to MVC 3 and jquery, i would like to know a best practice solution to how the following can be solved:

我有一个观点,在这里我使用jQuery AJAX来获取和显示与一些产品的细节产品A的局部视图加载的局部视图包含了一堆的HTML和jQuery code,这是联系在一起的的定义的局部视图中的ID。

I have a view, where I use jquery ajax to fetch and display a partial view with some product details for product A. The loaded partial view consist of a bunch of html and jquery code, which is tied to the defined id's within the partial view.

因此​​,我想重复使用相同的局部视图显示在同一视图(在弹出的对话框显示例如产品B的详细信息)与其他产品的详细信息。每当所示的弹出窗口,新获取的局部视图将与产品A​​的部分观点相冲突,因为同一ID是在HTML中使用。

Thus, i would like to reuse the same partial view to show details from other products on the same View (e.g. show product B details in a pop-up dialog). Whenever the pop-up is shown, the newly fetched partial view will conflict with the partial view for product A, as the same id's are used in the html.

有没有办法来封装在局部视图的HTML和JavaScript,并重新使用它几页没有关于使用的ID和东西任何冲突的担心?

Is there a way to encapsulate the html and javascript in the partial view, and reuse it several pages without worry about any conflicts with ID's and stuff?

我希望我的问题是有道理的。谢谢,

I hope my question makes sense. Thanks,

/尼玛

更新时间:

下面是一些伪code,勾勒我的问题:

Here is some pseudo code, outlining my issue:

查看

<script type="text/javascript">
$(document).ready(function () {

    $('.productItems').click(function () {
        var input = { productId: $(this).attr('data-productID') };
        var url = url = '<%: Url.Content("~/ProductDetails/ShowProductDetails") %>';


        // Show the modal box with product details
        $('#dialogBox').dialog({
            title: $(this).attr('data-productTitle')
        });


        // Fetch content in the background
        $.get(url, input, function (result, response) {
            $('#dialogBox').html(result);
            });
    });
});
</script>


<div id="detailsArea">
    <% Html.RenderPartial("ProductDetails", Model.Product); %>
</div>

<div id="productLinks">
  <span class="productItems" data-productID="123">Product B</a>
</div>

<div id="dialogBox" style="display: none;"></div>

控制器 - >动作(ShowProductDetails)

public ActionResult ShowProductDetails(int productId)
{
  // Get product from db. and return the partial view

  return PartialView("ProductDetails", p);
}

局部视图(产品详细)

<script type="text/javascript">

   function SetProductTabContent(selectedTab) {
        $("#productDescriptionContent > div").css('display', 'none');

        switch (selectedTab) {

            case '#tab-1':
                $('#productDescriptionText').css('display', 'block');
                break;

            case '#tab-2':
                $('#productSpecificationText').css('display', 'block');
                break;   
        }


$(document).ready(function () {
    // Get all the menu items
    var menuItems = $("#productMenu a");

    // Select the first tab as default
    menuItems.first().addClass("menuItemActive");

    // Handle the look of the tabs, when user selects one. 
    menuItems.click(function () {

        var item = $(this);

        // Get content for the selected tab
        SetProductTabContent(item.attr('href'));

        menuItems.removeClass("menuItemActive");
        item.addClass("menuItemActive");
        return false;
    });
});
</script>


<div id="productMenu" style="">
    <a href="#tab-1">
        <div class="menuItemHeader">Menu1</div>
    </a>
    <a href="#tab-2">
        <div class="menuItemHeader">Menu2 </div>
    </a>
</div>


<div id="productDescriptionContent">

        <div id="productDescriptionText" style="display: none;">
            <%: Model.Product.Description %>
        </div>
        <div id="productSpecificationText" style="display: none;">
            <%: Model.Product.Description2%>
        </div>
</div>

问题
当部分视图获取在DOM中,冲突的div两次加载。

ISSUE When the partial view gets loaded twice in the DOM, the divs conflicts.

推荐答案

是的。正如你指出的,不要在你的JavaScript中使用的ID和ID选择。而是使用类选择:

Yes. As you pointed out, do not use ids and id selectors in your JavaScript. Instead use class selectors:

例如,在您看来的标记

<div class="container">Partial View content</div>

JS:

var $div = $('div.container');
// do something

要消除选择具有相同的类名其他标记的可能性,分配一个纲领性的名字是仅用作选择器手柄,而不是作为一个CSS类的局部视图中的元素。

To eliminate possibility of selecting other tags with same class name, assign a programmatic name the elements in partial view which is used only as a selector handle and not as a CSS class.

虽然基于ID查找是最佳的性能明智的,在这种情况下,它更有意义的[标签+级]根据查找去避免ID冲突。 [标签+级]根据查找自带pretty接近ID选择在性能方面。

While ID based lookup is the best performance wise, in this case, it makes more sense to go by the [tag+class] based lookup to avoid id conflicts. [tag+class] based lookup comes pretty close to id selectors in terms of performance.

此外,您还可以通过限制查找范围得到进一步的改进:

Also, you can gain further improvement by limiting the lookup scope:

<div class="container">Partial View content <span class="child">Child content </span></div>

var $span = $(span.child')  // scope of lookup here is entire document

但是,如果你知道孩子是容器div里面,可以说限制范围:

However, if you know that child is inside container div, you can limit the scope by saying:

var $div = $('div.container').children('span.child'); // or just '.child'

另一个技巧是做查找一次,重复使用它:

Another tip is to do the lookup once and reuse it:

// less performant
function doSomething() {

    // do something here
    $('div.container').css('color', 'red');

    // do other things
    $('div.container').find('.child');

   // do more things
    $('div.container').click(function() {...});
}


// better
function doSomething() {
    var $div = $('div.container');

    // do something here
    $div.css('color', 'red');

    // do other things
    $div.find('.child');

   // do more things
    $div.click(function() {...});

   // or chaining them when appropriate
   $('div.container').css('color', 'red').click(function() { ... });


}

更新:重构OP的帖子试玩概念:

Update: Refactoring OP's post to demo the concept:

<script type="text/javascript">

       function SetProductTabContent(selectedTab, ctx) {
            var $container = $("div.pv_productDescriptionContent", ctx);

            // this will find only the immediate child (as you had shown with '>' selector)
            $container.children('div').css('display', 'none');  

            switch (selectedTab) {

                case '#tab-1':
                    $('div.pv_productDescriptionText', $container).css('display', 'block');
                    // or $container.children('div.pv_productDescriptionText').css('display', 'block');
                    break;

                case '#tab-2':
                    $('div.pv_productSpecificationText', $container).css('display', 'block');
                    // or $container.children('div.pv_productSpecificationText').css('display', 'block');
                    break;   
            }


    function SetUpMenuItems(ctx) {
        // Get all the menu items within the passed in context (parent element)
        var menuItems = $("div.pv_productMenu a", ctx);

        // Select the first tab as default
        menuItems.first().addClass("menuItemActive");

        // Handle the look of the tabs, when user selects one. 
        menuItems.click(function () {

            var item = $(this);

            // Get content for the selected tab
            SetProductTabContent(item.attr('href'), ctx);

            menuItems.removeClass("menuItemActive");
            item.addClass("menuItemActive");
            return false;
        });
    }
    </script>


<div style="" class="pv_productMenu">
    <a href="#tab-1">
        <div class="menuItemHeader">
            Menu1</div>
    </a><a href="#tab-2">
        <div class="menuItemHeader">
            Menu2
        </div>
    </a>
</div>
<div class="pv_productDescriptionContent">
    <div class="pv_productDescriptionText" style="display: none;">
        <%: Model.Product.Description %>
    </div>
    <div class="pv_productSpecificationText" style="display: none;">
        <%: Model.Product.Description2%>
    </div>
</div>

注意:当您加载的局部视图,因为这我删除的document.ready 包装将不火。相反,我重构视图的JS调用设置功能,并通过在范围之内(这将避免选择与同级别其他的div):

Note: I removed document.ready wrapper since that will not fire when you load the partial view. Instead, I refactored your View's JS to call the setup function and also pass in the scope (which will avoid selecting other divs with same class):

// Fetch content in the background
$.get(url, input, function (result, response) {
       $('#dialogBox').html(result);
       SetUpMenuItems($('#dialogBox'));   
});

显然,你可以进一步修改成你认为合适你的应用程序,我已经证明是一个想法,而不是最终的解决方案。

Obviously, you can modify this further as you deem fit in your app, what I've shown is an idea and not the final solution.


  • 如果您加载 #dialog 再次,他们将覆盖现有的标记,因此不会有重复。

  • 如果您在其他容器中再次加载局部视图,可以传递的情况下,这将prevent您访问<$ C的孩子 $ C> #dialog

  • 我想出了这个任意preFIX 光伏_ 用于编程类处理。这样,你可以告诉看它是否对CSS或在脚本中使用的类名。

  • If you load #dialog again, they will overwrite existing markup, hence there won't be duplicate.
  • If you load the partial view again in some other container, you can pass that as the context and that will prevent you accessing the children of #dialog
  • I came up with this arbitrary prefix pv_ for programmatic class handles. That way, you can tell looking at the class name if it is for CSS or for use in your script.

这篇关于MVC 3,部分意见和jQuery重用,没有发生冲突的DOM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆