2

大家好,我知道我的问题与其他问题相似,但我的问题不同。请仔细听我说。

简单地说,我只是想知道是否一次又一次地调用一个函数,如何在我的插件代码中设置一个条件,如果不调用该特定部分则不运行。

我在 jQuery 中编写了一个插件类型的短代码。这是特定于我的项目。它适用于我将传入参数的集合widthheight特定元素。window loadwindow resize。_ 我是 jquery 的初学者,所以对对象不太熟悉。

这是代码

//creating some universal variable
var _W, _H, _header, _lH, _lW, _lH1, _lH2, _lH3;

(function($){
    adjust = function(options) {

    var defaults = { 
        headerClass: '',
        containerClass : '',
        Hlevel1:{space:0, divClass :'', prevDivClass : ''},
        Hlevel2:{space:0, divClass :'', prevDivClass : ''},
        Hlevel3:'',
        Wlevel1 : {space:0, divClass : '', prevDivClass : ''},
        Wlevel2 : {space:0, divClass : '', prevDivClass : ''}

    };
    var opts = $.extend(defaults, options);

    function performAdjust(){
            _W = $(window).width(); //retrieve current window width
            _H = $(window).height(); //retrieve current window height
            _headH = $(opts.headerClass).outerHeight(true);//retrieve current header height


            // take left height after header height subtract to window height
            _lH = _H - _headH

            //make a variable for level one height
            _lH1 = _lH - (opts.Hlevel1.space + $(opts.Hlevel1.prevDivClass).outerHeight(true))

            //make a variable for level two height
            _lH2 = _lH1 - (opts.Hlevel2.space + $(opts.Hlevel2.prevDivClass).outerHeight(true));



            //applying height on main container
            $(opts.containerClass).css({height:_lH});


            //applying height on level 1 div
            $(opts.Hlevel1.divClass).css({height:_lH1 });


            //applying height on level 2 div
            $(opts.Hlevel2.divClass).css({height:_lH2 });


            //take left width after level one element

            // if(typeof opts.Wlevel1.divClass === 'undefined'){
            //  console.log('insert in if');
            // }


            var prdiv_lw1 = $(opts.Wlevel1.prevDivClass).outerWidth(true);

            _lW1 = _W - (prdiv_lw1+ opts.Wlevel1.space);

            //applying Width on level 1 div
            $(opts.Wlevel1.divClass).css({width:_lW1 });


            //take left width after level one element
            _lW2 = _lW1 - ($(opts.Wlevel2.prevDivClass).outerWidth(true)+ opts.Wlevel2.space);
            //applying Width on level 2 div
            $(opts.Wlevel2.divClass).css({width:_lW2 });        

        };
        $(function() {
            performAdjust();
        });
        $(window).resize(function() {
            performAdjust();
        });

    }
})(jQuery);

如何初始化它

// initialize adjust function for manage route
    $(document).ready(function (){
        adjust({
            headerClass : '.header',
            containerClass :'.container, .navContainer',
            Hlevel1: {space:0, divClass : '.viewport', prevDivClass : '#leftBreadcrumb'},

            Wlevel1 :{space:0, divClass : '.contentContainer', prevDivClass : '.navContainer'},
            Wlevel2 :{space:0, divClass : '.header-midsec', prevDivClass : '.navContainer'}
        })
    });

当页面通过ajax请求再次初始化

$(document).ready(function (){
  adjust({
    Hlevel1: {space:100, divClass : '.viewport1', prevDivClass : '.routeHead '},
  })
});

问题

当我为其他元素再次初始化它时,它将覆盖所有属性。我第一次为主页结构初始化它。下次我的页面来自 ajax 请求,所以在该结构下,一些元素需要动态width, height调整,我必须再次初始化它,但它会覆盖所有属性。

如果我再次调用此函数并且不传递未使用的对象和参数,那么我想提出一个条件,那么它将不会运行。

我怎样才能做到这一点,请告诉我

提前感谢,对不起我的英语

只是我只想知道是否一次又一次地调用一个函数,如何在我的插件中设置一个条件,如果我不调用该特定部分则不运行。

我尝试过的另一件事typeof,但我不明白如何处理它。

4

2 回答 2

2

如果我理解正确,您实际上想要实现的是,第一次使用传递的选项字段覆盖默认值,但在再次执行时覆盖最后使用的值。

您想要做的只是将defaults变量移出函数范围之外的闭包范围adjust。这样,新的传入options字段将覆盖以前使用的对象,而不是每次都覆盖相同的硬编码默认值。

基本上,你改变:

adjust = function(options) {
    var defaults = { 
        headerClass: '',
        containerClass : ''
    };
    var opts = $.extend(defaults, options);

到:

var defaults = { 
        headerClass: '',
        containerClass : ''            
    };

adjust = function(options) {
    var opts = $.extend(defaults, options);

JSFiddle 示例:http: //jsfiddle.net/MvxAj/1/

为了便于阅读,我删除了这些XlevelY字段。您可能还需要考虑使用更动态的方法,其中这些字段不是硬编码的,以在添加另一个级别时最大限度地减少代码更改,但情况不同:)

于 2013-10-29T09:06:20.113 回答
1

可能的解决方案

我对您需要什么的猜测只是对设置的特定值进行一些条件检查,但是您的代码阅读起来相当笨拙,因此确定需要定义什么来触发什么动作有点困难。

代码中的主要常量似乎是您为每个目标元素定义了一个特定的选择器,因此您可以用 if 包装影响特定选择器的每个语句:

if ( opts.containerClass ) {
  $(opts.containerClass).css({height:_lH});
}

您实际上不需要这样做typeof,因为如果您的选择器是空格,它们将不会很有用......并且空格被语句计falseif

但是,如果您有任何相互依赖以更改大小的元素,则这不会考虑在内,您的代码逻辑和 css 必须了解元素之间的依赖关系,并相应地应用您的 if 语句。

进一步的问题

默认对象也增加了一个问题,因为如果您将一组默认值合并到您正在测试属性是否存在的对象中,默认对象中的属性将始终显示为设置。你真的有三种方法可以解决这个问题。

  1. 在合并默认值之前创建一个测试对象,然后从该测试对象运行所有 if 语句。
  2. 仅在第一次调用代码时使用默认对象,随后的调用仅依赖于您传入的内容。
  3. 当您稍后调用代码时,即在 ajax 之后,为您不希望更改的项目传递错误值。

因此,作为 1 的示例,将此代码放在默认值合并之前。

var test = {};
if ( options.containerClass ) {
  test.containerClass = true;
}
var opts = $.extend({}, defaults, options);

但是,如果您不需要使用默认值,则使用默认值似乎有点愚蠢,并且在 ajax 之后调用时可能就是这种情况;这将我们引向第 2 点:

if ( !adjust.alreadyCalled ) {
  var opts = $.extend(defaults, options);
  adjust.alreadyCalled = true;
}
else {
  opts = options;
}

有些人可能会抱怨上面的想法是对的,因为它会adjust以一种意想不到的方式从根本上改变你的方法的行为。这就是为什么我建议第 3 点——如果你愿意的话,覆盖你不想要的项目。

$(document).ready(function(){
  adjust({
    containerClass: false,
    Hlevel1: {
     'space': 100, 
     'divClass': '.viewport1', 
     'prevDivClass': '.routeHead '
    }
  })
});

这样做的缺点是,如果您扩展了此函数可以调整的项目,您将不得不修改所有调用以进行调整,以确保您想要覆盖的所有内容都已falsed删除。

更好的方法

与其解决您已有的问题,我建议(以及添加条件语句)是为调整添加辅助参数,例如:

adjust = function(options, includeDefaults) {

通过这种方式,您可以判断是否以及何时要使用默认值,显然,如果您启用默认值,那么所有调整都可能发生......如果您不启用默认值,那么您可以更具体地了解您想要的内容调整,因为您的条件检查不会被默认值混淆。

var opts;
if ( includeDefaults ) {
  opts = $.extend({}, defaults, options);
}
else {
  opts = options;
}

更新

@ikari(+1)刚刚提出了一个很好的观点,我没有注意到,您实际上没有$.extend正确使用默认值合并。你最好使用:

opts = $.extend({}, defaults, options);

这样,您可以创建一个新对象,首先结合默认值,然后再结合您传入的选项,而不是不断修改您的默认值对象。我已经完成并更新了上面的代码以反映此更改。

于 2013-10-29T09:00:06.203 回答