Как сохранить скрипт в частичном представлении от загрузки более одного раза и возникновения ошибок, если частичный используется более одного раза на одной странице - PullRequest
0 голосов
/ 26 мая 2020

Работая в ASP. NET MVC, я создал частичное представление, которое отображается на одной странице 2 раза. Моя проблема в том, что JavaScript включается столько раз, сколько частичное представление , а JavaScript не любит переопределение классов.

Мой вопрос: как мне включить JavaScript в частичном виде, чтобы он оставался модульным, но был ли он включен на страницу только один раз? Меня не интересуют решения, которые требуют включения файла. js отдельно от содержимого частичного представления, например

<script src="some.js"></script>
@Html.Partial("some/partial.cshtml")
@Html.Partial("some/partial.cshtml")

, но я согласен с отдельным файлом. js, который включен внутри частичный вид. Частичное представление должно включать в себя все, что необходимо для его работы.

Мой код структурирован примерно так:

<div id=@ViewBag.id></div>
<script>
    class MyClass{ 
        constructor(divName){
            this._divId = divId;
        }

        doSomething(){
            /* do stuff with element that has id of divId */ 
        }
    }
</script>

Затем в вызывающем файле у меня есть

<body>
    @Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_1"} })
    @Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_2"} })
</body>
<script>
    $().ready(function(){
        id1Functionality = new MyClass("id_1"); // please forgive the poor naming :-)
        id2Functionality = new MyClass("id_2");

        id1Functionality.doSomething();
        id2Functionality.doSomething();
    })
</script>

1 Ответ

0 голосов
/ 26 мая 2020

Одно из решений - реализовать вспомогательную функцию расширения Html, которая загружает скрипт только один раз. Увидеть ниже. (это также может работать для CSS и других включенных файлов).

Реализуйте расширение для класса HtmlHelper и частного резервного класса как синглтона для HttpContext.

public static class YourHtmlHelperExtensionClass 
{
    private class TagSrcAttrTracker
    {
        private TagSrcAttrTracker() { }

        public Dictionary<string, string> sources { get; } = new Dictionary<string, string>();

        public static TagSrcAttrTrackerInstance {
            get {
                IDictionary items = HttpContext.Current.Items;
                const string instanceName = "YourClassInstanceNameMakeSureItIsUniqueInThisDictionary";

                if(!items.Contains(instanceName)) 
                    items[instanceName] = new TagSrcAttrTracker();

                return items[instanceName] as TagSrcAttrTracker;
            }
        }
    }

    public static MvcHtmlString IncludeScriptOnlyOnce(this HtmlHelper helper, string urlOfScript) 
    {
        if(TagSrcAttrTracker.Instance.sources.ContainsKey(urlOfScript))
            return null;

        TagSrcAttrTracker.Instance.sources[urlOfScript] = urlOfScript;

        TagBuilder script = new TagBuilder("script");
        scriptTag.MergeAttribute("src", urlOfScript);

        return MvcHtmlString.Create(script.ToString());
    }
}

Затем , разделите JavaScript и другой код в отдельные файлы.

Пример. js содержимое файла

class MyClass{
    myFunction() {
        constructor(divId){
            this._divId = divId
        }

        doSomething() {
            // do something with a div with id == divId
        }
    }
}

Пример .cs html содержимое файла для частичного просмотра

<link rel="stylesheet" type="text/css" href="~/Content/CustomCSS/MyPartialView.css"/>

<div id="@ViewBag.id">
    Some content!  Yay!
</div>

@Html.IncludeScriptOnlyOnce("/Scripts/CustomScripts/MyPartialView.js")

Пример файла .cs html, который использует частичное представление

...
<body>
    <h1>Here is some content!</h1>
    @Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_1"} })
    @Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_2"} })
    @Html.Partial("/Views/MyPartial.cshtml", new ViewDataDictionary() { { "id", "id_3"} })
</body>
<script>
$().ready(
    const id1Functionality = new MyClass("id_1") // forgive the poor naming :-)
    const id2Functionality = new MyClass("id_3")
    const id3Functionality = new MyClass("id_2")

    id1Functionality.doSomething();
    id2Functionality.doSomething();
    id3Functionality.doSomething();
)
</script>

Частичное представление могло быть включено более одного раза, а JavaScript упакован с частичным представлением, но . js файл включается на страницу только один раз, поэтому браузер не жалуется, что MyClass был объявлен более одного раза.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...