Ищу рекомендации о том, как отделить JS-код от представлений - PullRequest
2 голосов
/ 06 ноября 2011

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

Какие методы используютсялюди, которые используют для отделения кода JS, чтобы уменьшить нагрузку на обслуживание и сделать его максимально устойчивым к незначительным изменениям представления?

Чтобы привести конкретный пример, у меня есть представление, которое выглядит какследующее:

<div id="signin" class="auth">
    <h2>Sign in</h2>
    <div id="resultbox" class="box" style="display: none;"></div>

    <div class="form">
        <p>Required fields are marked <span class="yellow">*</span></p>
        <form action="@Url.Action( MVC.Account.Authenticate() )" method="post" id="authform">
            <label for="Identification">Alias or email <span class="yellow">*</span></label></p>
            @Html.TextBoxFor( m => m.Identification, new { size="22", tabindex="1" } )

            <label for="Password">Password <span class="yellow">*</span></label></p>
            @Html.PasswordFor( m => m.Password, new { size="22", tabindex="2" } )

            <a href="#" class="but_styled" id="btn_signin" tabindex="3">Sign in</a>
        </form>
    </div>
</div>

Часть JS разделена на два файла - первый - это мой класс "бизнес-логики", а второй используется главным образом для проводки:

(function (pp, $, undefined) {
    pp.account = {};

    function hideResultBox() {
        var box = $('#resultbox');
        box.hide();
        box.removeClass('info_box').removeClass('error_box');
    }
    function showResultBox(result) {
        var box = $('#resultbox');
        if (result.Success === true) {
            $('#resultbox_content').html(result.Message);
            box.addClass('info_box').show();
        } else {
            $('#resultbox_content').html(result.Message);
            box.addClass('error_box').show();
            var messages = '';
            for (var error in result.Errors) {
                messages += '<li>' + result.Errors[error] + '</li>';
            }
            if (messages !== '')
                $('#resultbox_content').append('<br /><ul>' + messages + '</ul>');
        }
    }

    pp.account.authenticate = function (data) {
        hideResultBox();
        $.post('/account/authenticate', data, function (result) {
            showResultBox(result);
            if (result.Success === true) {
                setTimeout(function () { window.location = result.Url; }, 1000);
            }
        });
    };
})(window.pressplay = window.pressplay || {}, jQuery);

И проводкаpart:

$(document).ready(function () {
    $('#signin a').live('click', function () {
        var form = $(this).closest('form').serialize();
        pressplay.account.authenticate(form);
        return false;
    });
});

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

Мне просто кажется, что, если я продолжу идти по этому пути, файлы JS окажутся в беспорядке должным образом инкапсулированной логики в сочетании со всеми видами специфических для представления вещей.

Этолучшее, что я могу надеяться сделать, или есть какие-то методы, которые я могу применить, чтобы избежать этой путаницы?

Мои собственные идеи о том, как улучшить это вращение вокруг создания каких-то сгенерированных на стороне сервера "селекторов элементов"Класс JS, такой, что я мог написать JS, не используя столько строковых ссылок на классы и идентификаторы элементов.Но я не уверен, как можно было бы сгенерировать это или будет хуже в конце поддерживать.

Ответы [ 3 ]

3 голосов
/ 06 ноября 2011

Некоторые мысли:

  • Не основывайте функциональность на значениях элемента "id", за исключением функций представления, которые действительно включают элементы, которые "естественно" уникальны. Вместо этого используйте классы, когда это возможно.
  • Используйте атрибуты «data-» для передачи информации о конфигурации функции из HTML в JavaScript. (Но не вставляйте код в свои атрибуты «data-»; на мой взгляд, это действительно ужасная идея. Извините, фанаты Knockout . Каждому свое.)
  • Использование паба / подсистемы событий для связи между «пакетами» функций, чтобы держать под контролем взаимозависимости.
  • Используйте <body> классы, чтобы охарактеризовать различные виды страниц, чтобы повысить эффективность вашей "разводки". Таким образом, код функции может очень быстро сказать, нужно ли его даже рассматривать для данной страницы.

изменить & mdash; Чтобы прояснить последнее: допустим, у вас есть некоторые функции, связанные с <form> страницами, такие как выбор даты, вводы с автозаполнением или другие подобные вещи. Иногда есть особенности, которые имеют смысл только для определенных видов форм. В таких случаях использование класса тела позволяет легко определить, стоит ли объекту искать в DOM элементы, на которые он влияет:

if ($('body').is('.password-form')) { 
  // perform specific initializations
}

Веб-приложение, с которым я сейчас работаю, не слишком большое, но и не тривиальное. Я обнаружил, что могу хранить только одну большую коллекцию JavaScript для всего сайта и одинаково включать ее на каждой странице, и у меня нет никаких проблем с производительностью (в настоящее время) (ну, IE7 работает медленно, но этот метод не является причиной тот).

1 голос
/ 06 ноября 2011

Вместо идентификаторов я бы подумал более «функциональным» способом ... то есть сначала подумайте, какова функция кода javascript, затем сделайте код таким образом, чтобыэто может быть использовано вашим взглядом.

Видите ли вы разницу?

То, как вы делаете это: сначала посмотрите, затем код JavaScript ... я предлагаю: Сначала javascript, а затем элементы вида .Таким образом, вы совершенно уверены, что кодируете многократно используемую кодовую базу javascript.

Вместо использования идентификаторов используйте классы.Сделайте код таким, как будто это универсальная библиотека, которую вы можете использовать повторно.Не требуйте фиксированной структуры, например ".myClass div a" ... что div уничтожает возможность повторного использования ... замените его некоторым внутренним классом: ".myClass .innerClass a", таким образом вы можете применять классы к вашему представлениюи не позволяйте представлению доминировать в коде.

Сведите к минимуму столько, сколько вы можете поместить код javascript непосредственно в ваши представления. Просто используйте вызовы методов для своих собственных библиотек, используйте простые и описательныеимена методов.Попробуйте собрать свой JavaScript вместе.Попробуйте не использовать декларативный JavaScript ... как я вижу, вы уже делаете это.Это путь!=)

Не беспокойтесь об удобстве обслуживания, поскольку разъединение - это проверенный способ повышения удобства обслуживания.

1 голос
/ 06 ноября 2011

JavaScript по-прежнему является частью вашего взгляда, поэтому я не считаю, что дизайн слишком плох, чтобы ваш JavaScript переплетался с вашим представлением.

Что касается того, что можно сделать, чтобы упростить жизнь, я думаю, что вам действительно нужно сделать все возможное, чтобы найти общие ситуации кодирования javascript и перестроить их вне поля зрения, в общую библиотеку, где ее можно использовать. и повторно. Например, если вы переписали свой hideResultBox, чтобы он выглядел так:

function hideElement(var jqElementSelector, var cssClass1, var cssClass2 var cssClass3) {
    var element = $(jqElementSelector);
    element.hide();
    element.removeClass(cssClass1).removeClass(cssClass2).removeClass(cssClass3);
}

И тогда вы можете заменить свой вызов в этом представлении следующим образом:

CommonLib.hideElement('#resultbox', 'info_box', 'error_box');

Таким образом, по крайней мере, у вас не так много javascript для поддержки. Это также упростило бы создание точек вызова javascript с сервера, поскольку вы не передаете логику, только имена и или идентификаторы, и вам не нужно беспокоиться о потере каких-либо способностей javascript intellisense в вашей логике javascript.

...