Bra*_*roy 10 jquery global-variables instance-variables jquery-plugins
我正在开发一个项目,最初只是构建一个带有参数(XML文件)的函数,并将其转换为HTML/CSS结构(此处可以找到早期版本).这很有效.但是,我想实现更多选项和更多灵活性.我读过的主题(如1,2,3),但我不能换我的头周围.
我的插件有很多特定于实例的需求:
并且有一些重要的选择:
我将描绘插件当前状态的基本结构.
两个第一选项是最重要的选项.但默认为true,如果用户同时打开它们false,则插件将不会执行.
然后,插件会分配全局变量,并根据此信息创建新的DOM元素.在实践中它看起来像这样(注意全局变量在我的脚本的顶部声明).
function initVars(args) {
fontsizes = fsFontSizes;
errorContainer = $(".tv-error");
var trees = [],
tooltips = [];
if (args.normalView) {
normalView = true;
$(args.container).append('<div id="tree-visualizer" style="display: none"></div>');
SS = $("#tree-visualizer");
var SSHTML = '<div class="tv-error" style="display: none"><p></p></div>' +
'<div class="tree" style="font-size: ' + args.fontSize + 'px;"></div>' +
'<aside class="tooltip" style="display: none"><ul></ul>' +
'<button>✕</button></aside>';
if (args.fsView) {
SSHTML += '<button class="tv-show-fs">Fullscreen</button>';
}
SS.append(SSHTML);
treeSS = SS.find(".tree");
tooltipSS = SS.find(".tooltip");
trees.push("#tree-visualizer .tree");
tooltips.push("#tree-visualizer .tooltip");
}
if (args.fsView) {
fsView = true;
$("body").append('<div id="fs-tree-visualizer-" class=""fs-tree-visualizer" style="display: none"></div>');
FS = $("#fs-tree-visualizer");
var FSHTML = '<div class="tv-error" style="display: none"><p></p></div>' +
'<div class="tree"></div><aside class="tooltip" style="display: none"><ul></ul>' +
'<button>✕</button></aside><div class="zoom-opts"><button class="zoom-out">-</button>' +
'<button class="zoom-default">Default</button><button class="zoom-in">+</button>' +
'<button class="close">✕</button></div>';
FS.hide().append(FSHTML);
treeFS = FS.find(".tree");
tooltipFS = FS.find(".tooltip");
zoomOpts = FS.find(".zoom-opts");
zoomCounter = Math.round(fontSizes.length / 2);
trees.push("#fs-tree-visualizer .tree");
tooltips.push("#fs-tree-visualizer .tooltip");
}
if (args.fsBtn != "") {
$(args.fsBtn).addClass("tv-show-fs");
}
anyTree = $(trees.join());
anyTooltip = $(tooltips.join());
}
Run Code Online (Sandbox Code Playgroud)
您将看到我正在使用ID,这使得很难处理多个实例.我想,解决这个问题的一种方法是添加一个样式类,并使用一个跟踪实例化的全局计数器(counter++在每个实例上)为每个实例添加一个ID .注意,anyTree当我希望定位FS树以及普通视图树时使用.这并不意味着我想要定位所有实例的所有树!这也必须在每个实例中受到限制.
所以我的问题是,如何允许多个实例,尤其是:如何在不失去现有功能的情况下从全局变量转移到局部变量?此时我可以使用全局变量并在任何我想要的地方访问每个变量.但是如何限制每个实例的全局变量?像我提议的那样使用那个柜台?
另外,我在哪里分配事件?目前这是我的插件初始化的方式(我遗漏了全局变量和函数):
$.treeVisualizer = function(xml, options) {
var args = $.extend({}, $.treeVisualizer.defaults, options);
/* At least one of the arguments (default true) have to be true */
if (args.normalView || args.fsView) {
initVars(args);
loadXML(xml);
} else {
console.error("Cannot initialize Tree Visualizer: either the container " +
"does not exist, or you have set both normal and fullscreen view to " +
"false, which does not make sense.");
}
/* Event handlers -- only after we've initiated the variables to globals */
$(document).ready(function() {
// Show fs-tree-visualizer tree
$(".tv-show-fs").click(function(e) {
// Show corresponding fullscreen version
FS.show();
// Execute some functions
sizeTreeFS();
e.preventDefault();
});
// Zooming
zoomOpts.find("button").click(function() {
var $this = $(this);
// Do something
});
anyTree.on("click", "a", function(e) {
// Do something, and execute function: has to
// target the right tooltip
tooltipPosition();
e.preventDefault();
});
});
}
Run Code Online (Sandbox Code Playgroud)
这是放置事件处理程序的正确位置吗?
那个XML可视化工具看起来不错.我有几个指示你.
首先,使用$ .fn.componentName而不是$ .componentName创建jquery-component/widget/plugin.
$.fn.treeVisualizer
Run Code Online (Sandbox Code Playgroud)
其次,我建议将所有全局值移动到选项中,或将局部变量移动到组件中.您提供的代码段应该有效.每个实例的每个全局值都必须是一个选项.
$.fn.myComponent(options){
var defaults = {
option1: true,
option2: 5
};
options = $.extend({}, defaults, options);//defaults and options are being merged into {}
var constantValue = 15; //values that won't change, you can just move locally from global
}
Run Code Online (Sandbox Code Playgroud)
第三,对于你的全局函数,我建议将它们与组件一起放在一个自调用函数中,这样组件就可以访问函数,并且它们不是全局函数.
(function initComponent(){
$.fn.myComponent(){
someFunction();
}
function someFunction(){
//do something
}
})();
//immediately invoke function/ self-invoking function
Run Code Online (Sandbox Code Playgroud)
或者您可以将函数放在组件范围内.
$.fn.myComponent = function(){
someFunction();
function someFunction(){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
第四,我建议使用类而不是id.您确实可以通过跟踪实例的数量确保id是唯一的来解决这个问题,但只需使用类(fe,xml-id-1).或者您也可以使用data-id/data-xml-id属性.不要担心在不同的组件中查询具有相同类的元素,我将在下一个指针中找到它.
$jqueryElement.addClass('xml-id-'+id);
$('.xml-id-'+id);//you can query it by class-name like this
Run Code Online (Sandbox Code Playgroud)
或者如果你想利用数据属性(我推荐使用数据属性,因为html更容易阅读,并且有更多的意义imo)
$jqueryElement.attr('data-xml-id', id); //fe <div data-xml-id="1"></div>
$('[data-xml-id="'+id+'"]'); //you can query it like this
Run Code Online (Sandbox Code Playgroud)
最后,每个查询和事件都需要与您的组件相关,因此您只需搜索元素并在组件实例中添加事件.这可确保您不会意外地在组件的另一个实例上执行操作.
$.fn.myComponent=function(){
$('[data-xml-id="1"]'); //this queries the whole DOM, don't do this!
var $el = this.find('[data-xml-id="1"]'); //this only looks for matching elements within the current instance of the component
$el.click(function(){// also add events to elements you searched within your components
//do something
);
}
Run Code Online (Sandbox Code Playgroud)
然后最终初始化你的组件.
$('#tree1').treeVisualizer(xml,
{
fullscreen: true
}
);
$('#tree2').treeVisualizer(xml);
Run Code Online (Sandbox Code Playgroud)
评论中的额外问题:
find方法与全局查询方法的作用相同,区别在于它只在jQueryObject的DOM中搜索.
获取当前匹配元素集中每个元素的后代,由选择器,jQuery对象或元素过滤.来源:jQuery文档
例:
var footer = $('footer');
footer.find('div');// searches for div's inside the footer
Run Code Online (Sandbox Code Playgroud)
插件内部是this指您初始化插件的jQueryObject.
$.fn.myComponent = function(){
console.log(this);// refers to $el
}
var $el = $('#id');
$el.myComponent();
Run Code Online (Sandbox Code Playgroud)
在事件回调中,这指的是您附加事件处理程序的本机元素.您必须将其包装在jQuery对象中以对其执行jQuery操作.
$('button').click(function(){
console.log(this); //prints out the button that was clicked
$(this).css('background','#000'); //wrap native button element in jQuery object and perform jQuery methods on it
});
Run Code Online (Sandbox Code Playgroud)
每当您不确定其中的位置时this,只需将其记录到控制台即可.通过这些信息,您可以看到this.find('.tree-structure')在组件内部使用时,您确实只会在初始化组件的jQuery对象中搜索具有"tree-structure"类的元素.
| 归档时间: |
|
| 查看次数: |
534 次 |
| 最近记录: |