Прошло довольно много времени с тех пор, как я много сделал с jQuery (или javascript вообще). Я пытаюсь принять наше приложение от всех методов в глобальной области, до точки, где все находится в собственном пространстве имен.Настройка прослушивателей jQuery вне глобальной области
Подход, который я принимаю, заключается в использовании гибрида шаблона раскрывающего модуля и шаблона объектного литерала.
Я использую объект буквального шаблон на каждой отдельной странице, и я использую его, чтобы просто параметры настройки, которые приходят с сервера (ASP.NET MVC Razor)
var st = st || {};
st.SharedContextMenuCommon = {
ContextMenuControllerName: '@Model.ControllerName',
BindingTargetName: '@Model.TargetName',
StratosphereGlobalImageUrl: '@Web_Helpers.StratosphereImageUrl("")' // yes this is empty since we only need the root. we can't pass a JS variable to Razor
};
Отсюда, я есть внешний файл, который делает весь тяжелый подъем. В этом конкретном случае у меня есть Kendo ContextMenu, и мне нужно его инициализировать его слушателей (jQuery) изнутри вложенного пространства имен.
Если я удалю все биты пространства имен, этот код работает так, как ожидалось, однако, когда я использую шаблон раскрывающегося модуля, слушатель не запускается в событии 'click'.
var st = st || {};
st.SharedContextMenu = (function() {
// check to see if menu exists
var menu = $("#contextMenu");
var initMenu = function() {
menu = $("#contextMenu").kendoContextMenu({
orientation: 'vertical',
alignToAnchor: true,
filter: ".contextMenu",
showOn: "click",
animation: {
open: {
effects: "fadeIn"
},
duration: 250
},
select: function(e) {
this.close(); // close the context menu
var action = $(e.item).find("[data-action]").data("action"); // extract the javascript string that is to be actioned on
var id1 = e.target.dataset.recordid; // extract the specific record ID (typically a GUID)
var id2 = e.target.dataset.recordidalt; // extract the specific alt record ID (typically a GUID)
var func = new Function(String.format(action, id1, id2)); // format the action (if the string is a formattable)
return (func()); // execute the string. This is essentially like EVAL, but since this is an internal app, it should be safe.
}
});
};
// only init the menu if it exists.
if (menu) {
initMenu();
$('#' + st.SharedContextMenuCommon.BindingTargetName).on('click', '.contextMenu', function() {
var recordId = $(this).data('recordid');
$.getJSON(st.SharedContextMenuCommon.ContextMenuControllerName + '/?recordId=' + recordId, function(data) {
var contextMenu = $('#contextMenu').data('kendoContextMenu');
var items = [];
$.each(data, function(key, value) {
items.push({
text: '<span data-action="' + value.OnClickJavascript + '">' + value.Text + '</span>',
encoded: false,
imageUrl: st.SharedContextMenuCommon.StratosphereGlobalImageUrl + value.Image
});
});
contextMenu.setOptions({
dataSource: items
});
});
});
}
})();
Может кто-то указать мне на кусок, который мне не хватает?
Вы понимаете, что 'новая функция' на самом деле не создает функцию, которая может быть вызвана позже, она вызывает конструктор функции и сразу же запускает новую функцию. Похоже, вы должны отказаться от ключевого слова 'new'. – adeneo
@adeneo, Вероятно, вы правы в обоих случаях для этого случая. В других областях, используя тот же шаблон, я возвращаю 'st' так, чтобы публичные методы могли быть вызваны. В этом случае я ничего не звоню, а просто слушаю события. 'новый function' позволяет' st.something.publicMethod() 'вместо' st.something(). publicMethod() '... снова, так как я не подвергая публичные методы, это спорный вопрос, просто предпочтение вещь. –