Использует ли jQuery правильную манипуляцию DOM с добавлением и созданием элементов?

0

Поэтому я столкнулся с этой проблемой:
Изображение 174551

Теперь нужно отметить, что размеры печатаются с использованием идентичного кода:

$graphContainer.append("<br/>dimensions: ");
var width = $graphContainer[0].offsetWidth, height = $graphContainer[0].offsetHeight;       
$graphContainer.append(width + 'x' + height);

И красный DIV это $graphContainer сам. Функции называются так:

        s.load();
        setTimeout(function() {
            s.load()
        }, 350);

s является объектом я строю. (Если я использовал 300 мс, то оба вышли как 800x30, поэтому его между 300-350 мс).

Теперь порядок DOM корректен, и элементы были добавлены в DOM, используя jQuery перед вызовом этой функции. (Немного сложная логика, надеюсь, вы можете принять мое слово, не глядя на код дыры).

Я думаю, что я действительно знаю, что здесь происходит, если вы используете innerHTML для добавления контента, то для его полной доступности в DOM потребуется некоторое время, и это может привести к появлению подобных фантомов. Теперь график, о котором я говорю, находится в миллисекундах, но для меня это настолько плохо, что у вас нет политики, чтобы никогда не использовать innerHTML для добавления или создания элементов.

Дело в том, что все элементы DOM, используемые в объектах и сделанные DOM-манипуляции, были выполнены с использованием кода jQuery типа $('<div>') для создания элементов и $container.append($child) для добавления дочерних элементов.

Мне всегда казалось, что jQuery сделал правильные манипуляции с DOM.
Разве это не так, и они широко используют innerHTML? Или я что-то упускаю, и это может быть что-то еще, что задержка в 300 мс - это долго, чтобы это было проблемой innerHTML?

В настоящее время я использую jQuery 1.9.1

На всякий случай это код, который получает этот результат (это подключаемый модуль jQuery):

if (typeof jQuery != 'function') {
    throw "The CommoditiesPeersIndices is a jQuery plugin i.e. jQuery needs to be defined first";
}

(function ($) {
    /*
        Built with jQuery 1.9.1 in mind.
        Creates the [CommoditiesPeersIndices] Object
    */


var CommoditiesPeersIndices = function(Settings) {
/*
    Binds all of the tools objects into a single object and manages them
*/
    var 
        CLASS_NAME = 'CommoditiesPeersIndices' //the CSS root Class name that will be applied to all the objects
    ;

    this.$root = $('<div>'); //the root of the object

    var This = this
        ,DefaultSettings = {
            //$container : null //the jQuery object into with the tool will be built
            parentClassName : '' //the parent class name name of the parent object that will be appended to this object
        }
    ;

    var s; //temp variale for the test small graph

    function _init() {
        //makes sure that the Settings object has all of the settings
        mergeSettings(Settings, DefaultSettings);
        CLASS_NAME = Settings.parentClassName + CLASS_NAME;

        s = new SmallGraphObject({
            parentClassName : CLASS_NAME + '-'
        });
        This.$root.append(s.$root);
    }

    this.load = function() {


        s.load();
        setTimeout(function() {
            s.load()
        }, 350);


    };

    function mergeSettings(targetObject, sourceObj) {
    /*
        Used to merge the DefaultSettings with the Settings object. Basically the targetObject will get all of the sourceObjects values that are missing from the target object or are not of the same type as the sourceObject value.
    */
        var name, targetType;
        if(typeof targetObject == 'object' && targetObject  != null) {
            //merges the user Settings object with the Default SettingsObject i.e. DefaultSettings
            for(name in sourceObj) {
                targetType = typeof targetObject[name];
                switch(targetType) {
                    case 'object':
                        if(targetType == null) {
                            targetObject[name] = Utility.copyObject(sourceObj[name]);
                        } else {
                            mergeSettings(targetObject[name], sourceObj[name])
                        }
                        break;
                    default:
                        if(typeof sourceObj[name] != typeof targetObject[name]) {
                            targetObject[name] = sourceObj[name];
                        }
                        break;
                }
            }
        } else {
            targetObject = Utility.copyObject(sourceObj);
        }
    }   

    _init();
};var SmallGraphObject = function(Settings) {
/*
    The single small graph object on the page, holds the graph + the enlarge button
*/
    var 
        CLASS_NAME = 'SmallGraph'
    ;

    this.$root = $('<div>'); 

    var This = this
        ,DefaultSettings = {
            instrumentID : 1031004 //the instrument ID of the instrument who data will be displayed.
            ,parentClassName : '' //the parent class name name of the parent object that will be appended to this object
            ,startDate : new Date()
            ,decimalPlaces : 2 //the number of decimal places the series will show
        }
        ,$graphContainer = $('<div>') //the highchart container
        ,$header = $('<div>') //the header that holds the name and the enlarge button

        ,$container = $('<div>') //the container object of the [SmallGraph] to with you can place CSS
    ;

    function _init() {
        //makes sure that the Settings object has all of the settings
        mergeSettings(Settings, DefaultSettings);

        CLASS_NAME = Settings.parentClassName + CLASS_NAME;

        $container.addClass(CLASS_NAME + 'Container')
            .append($header.addClass(CLASS_NAME + '-Header'))
            .append($graphContainer.addClass(CLASS_NAME + '-Graph'))
        ;
        This.$root.addClass(CLASS_NAME).append($container);

        $header.text('Heading');
    }

    this.load = function() {
    /*
        Loads the series data from the server.
    */

        $graphContainer.append("<br/>dimensions: ");
        var width = $graphContainer[0].offsetWidth, height = $graphContainer[0].offsetHeight;       
        $graphContainer.append(width + 'x' + height);
    };

    function mergeSettings(targetObject, sourceObj) {
    /*
        Used to merge the DefaultSettings with the Settings object. Basically the targetObject will get all of the sourceObjects values that are missing from the target object or are not of the same type as the sourceObject value.
    */
        var name, targetType;
        if(typeof targetObject == 'object' && targetObject  != null) {
            //merges the user Settings object with the Default SettingsObject i.e. DefaultSettings
            for(name in sourceObj) {
                targetType = typeof targetObject[name];
                switch(targetType) {
                    case 'object':
                        if(targetType == null) {
                            targetObject[name] = Utility.copyObject(sourceObj[name]);
                        } else {
                            mergeSettings(targetObject[name], sourceObj[name])
                        }
                        break;
                    default:
                        if(typeof sourceObj[name] != typeof targetObject[name]) {
                            targetObject[name] = sourceObj[name];
                        }
                        break;
                }
            }
        } else {
            targetObject = Utility.copyObject(sourceObj);
        }
    }

    _init();
};

    $.fn.CommoditiesPeersIndices = function() {
    /*
        Creates a new instance of [CommoditiesPeersIndices]
    */    
        var Main = new CommoditiesPeersIndices({
                parentClassName : 'Tools-'
            })
            ,$head = $('head')    
        ;

        $head.append('<link rel="stylesheet" type="text/css" href="http://localhost:60226/Content/jQueryComponent.css" />');
        $head.append('<link rel="stylesheet" type="text/css" href="http://localhost:60226/Config/Company/test/test.css" />');

        this.append(Main.$root);
        Main.load();

        return this;
    };

}(jQuery));

С помощью этого CSS:

.Tools-CommoditiesPeersIndices-SmallGraph {
    width: 300px;

}
.Tools-CommoditiesPeersIndices-SmallGraph-Graph {
    height: 150px;
    background: #f00;
}
  • 0
    Ваш вопрос, кажется, сводится к следующему: «Что находится в исходном коде jQuery?» В этом случае вы всегда можете просто убедиться сами .
  • 0
    Так в чем именно твоя проблема? Что вы создаете два одинаковых элемента, но в итоге они имеют разные измерения? Да, jQuery использует innerHTML там, где это имеет смысл.
Показать ещё 2 комментария
Теги:
dom

1 ответ

1
Лучший ответ

Существует некоторое объяснение механики jQuery в API. Это то, что говорят документы о передаче в узле в качестве параметра, например $('<div>'):

Если HTML более сложный, чем один тег без атрибутов, как в приведенном выше примере, фактическое создание элементов обрабатывается механизмом innerHTML браузера. В большинстве случаев jQuery создает новый элемент и устанавливает свойство innerHTML элемента в фрагмент HTML, который был передан. Когда параметр имеет один тег (с необязательным закрывающим тегом или быстрым закрытием) - $ ("") или $ (""), $ ("") или $ ("") - jQuery создает элемент с использованием встроенной функции JavaScript createElement().

Итак, если вы бросаете больше, чем только один тег, innerHTML запускается:

var foo = $("<div>");                   // this will use createElement
var bar = $("<div><p>hello</p></div>"); // innerHTML will be used here
var doh = $("<div class='hello'>");     // also innerHTML here...

У меня также возникли проблемы с созданием элементов jQuery, которые были слишком медленными (особенно в Internet Explorer), поэтому я пошел вперед и использовал собственные функции createElement и createTextNode, мой бог внезапно быстро, как черт!

  • 0
    github.com/jquery/jquery/blob/master/src/manipulation.js отличается в зависимости от того, какой метод используется для создания элемента и, как вы сказали, насколько сложен элемент. (buildFragment - это то, что используется, когда вы делаете $("sometextorhtml") )

Ещё вопросы

Сообщество Overcoder
Наверх
Меню