如何在入队脚本注入html之前延迟页面元素的显示

时间:2016-11-25 作者:CoderScissorhands

我正在排队一些javascript,这些javascript将SVG注入到我页面的DOM中(称为SVGInjector); 它非常有效,除了一件事:有一个不受欢迎的;“闪烁”/在我的屏幕上移动元素,在加载时放置注入的元素。显然,这个眨眼有一个名字,是我在几个月后问这个问题时发现的,它被称为非样式内容的眨眼(或FOUC),甚至还有它自己的名字Wiki.

这种转变的原因似乎很清楚:页面的其他元素显然是在注入SVG的js运行之前绘制的,然后,一旦插入,页面就会改变以适应添加的SVG。我昨天在回答我自己的问题时提到了这一点:https://wordpress.stackexchange.com/a/247315/105196

如何防止因延迟注入而导致元件移动

一些线索,也许这里有一些关于在加载整个页面之前运行js的信息,https://stackoverflow.com/questions/2920129/can-i-run-javascript-before-the-whole-page-is-loaded, 但一般来说,它是关于web编码的,而不是特定于WordPress的。我对WP和排队不太了解,不知道如何适应这些解决方案。

代码是如何将js排入函数队列的。php:

function mytheme_enqueue_front_page_scripts() {
    if( is_front_page() )
    {
        wp_enqueue_script( \'injectSVG\', get_stylesheet_directory_uri() . \'/js/svg-injector.min.js\', array( \'jquery\' ), null, true );
        wp_enqueue_script( \'custom\', get_stylesheet_directory_uri() . \'/js/custom.js\', array( \'jquery\' ), null, true );

    }
}

add_action( \'wp_enqueue_scripts\', \'mytheme_enqueue_front_page_scripts\' );
问题可能出在SVGinjector脚本本身,它可能有特定的指令等待其他元素被绘制出来。如果您认为原因可能是:

SVGInjector js脚本(作为“injectSVG”排队)

!function(t,e){"use strict";function r(t){t=t.split(" ");for(var e={},r=t.length,n=[];r--;)e.hasOwnProperty(t[r])||(e[t[r]]=1,n.unshift(t[r]));return n.join(" ")}var n="file:"===t.location.protocol,i=e.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),o=Array.prototype.forEach||function(t,e){if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;var r,n=this.length>>>0;for(r=0;n>r;++r)r in this&&t.call(e,this[r],r,this)},a={},l=0,s=[],u=[],c={},f=function(t){return t.cloneNode(!0)},p=function(t,e){u[t]=u[t]||[],u[t].push(e)},d=function(t){for(var e=0,r=u[t].length;r>e;e++)!function(e){setTimeout(function(){u[t][e](f(a[t]))},0)}(e)},v=function(e,r){if(void 0!==a[e])a[e]instanceof SVGSVGElement?r(f(a[e])):p(e,r);else{if(!t.XMLHttpRequest)return r("Browser does not support XMLHttpRequest"),!1;a[e]={},p(e,r);var i=new XMLHttpRequest;i.onreadystatechange=function(){if(4===i.readyState){if(404===i.status||null===i.responseXML)return r("Unable to load SVG file: "+e),n&&r("Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver."),r(),!1;if(!(200===i.status||n&&0===i.status))return r("There was a problem injecting the SVG: "+i.status+" "+i.statusText),!1;if(i.responseXML instanceof Document)a[e]=i.responseXML.documentElement;else if(DOMParser&&DOMParser instanceof Function){var t;try{var o=new DOMParser;t=o.parseFromString(i.responseText,"text/xml")}catch(l){t=void 0}if(!t||t.getElementsByTagName("parsererror").length)return r("Unable to parse SVG file: "+e),!1;a[e]=t.documentElement}d(e)}},i.open("GET",e),i.overrideMimeType&&i.overrideMimeType("text/xml"),i.send()}},h=function(e,n,a,u){var f=e.getAttribute("data-src")||e.getAttribute("src");if(!/\\.svg/i.test(f))return void u("Attempted to inject a file with a non-svg extension: "+f);if(!i){var p=e.getAttribute("data-fallback")||e.getAttribute("data-png");return void(p?(e.setAttribute("src",p),u(null)):a?(e.setAttribute("src",a+"/"+f.split("/").pop().replace(".svg",".png")),u(null)):u("This browser does not support SVG and no PNG fallback was defined."))}-1===s.indexOf(e)&&(s.push(e),e.setAttribute("src",""),v(f,function(i){if("undefined"==typeof i||"string"==typeof i)return u(i),!1;var a=e.getAttribute("id");a&&i.setAttribute("id",a);var p=e.getAttribute("title");p&&i.setAttribute("title",p);var d=[].concat(i.getAttribute("class")||[],"injected-svg",e.getAttribute("class")||[]).join(" ");i.setAttribute("class",r(d));var v=e.getAttribute("style");v&&i.setAttribute("style",v);var h=[].filter.call(e.attributes,function(t){return/^data-\\w[\\w\\-]*$/.test(t.name)});o.call(h,function(t){t.name&&t.value&&i.setAttribute(t.name,t.value)});var g,m,b,y,A,w={clipPath:["clip-path"],"color-profile":["color-profile"],cursor:["cursor"],filter:["filter"],linearGradient:["fill","stroke"],marker:["marker","marker-start","marker-mid","marker-end"],mask:["mask"],pattern:["fill","stroke"],radialGradient:["fill","stroke"]};Object.keys(w).forEach(function(t){g=t,b=w[t],m=i.querySelectorAll("defs "+g+"[id]");for(var e=0,r=m.length;r>e;e++){y=m[e].id,A=y+"-"+l;var n;o.call(b,function(t){n=i.querySelectorAll("["+t+\'*="\'+y+\'"]\');for(var e=0,r=n.length;r>e;e++)n[e].setAttribute(t,"url(#"+A+")")}),m[e].id=A}}),i.removeAttribute("xmlns:a");for(var x,S,k=i.querySelectorAll("script"),j=[],G=0,T=k.length;T>G;G++)S=k[G].getAttribute("type"),S&&"application/ecmascript"!==S&&"application/javascript"!==S||(x=k[G].innerText||k[G].textContent,j.push(x),i.removeChild(k[G]));if(j.length>0&&("always"===n||"once"===n&&!c[f])){for(var M=0,V=j.length;V>M;M++)new Function(j[M])(t);c[f]=!0}var E=i.querySelectorAll("style");o.call(E,function(t){t.textContent+=""}),e.parentNode.replaceChild(i,e),delete s[s.indexOf(e)],e=null,l++,u(i)}))},g=function(t,e,r){e=e||{};var n=e.evalScripts||"always",i=e.pngFallback||!1,a=e.each;if(void 0!==t.length){var l=0;o.call(t,function(e){h(e,n,i,function(e){a&&"function"==typeof a&&a(e),r&&t.length===++l&&r(l)})})}else t?h(t,n,i,function(e){a&&"function"==typeof a&&a(e),r&&r(1),t=null}):r&&r(0)};"object"==typeof module&&"object"==typeof module.exports?module.exports=exports=g:"function"==typeof define&&define.amd?define(function(){return g}):"object"==typeof t&&(t.SVGInjector=g)}(window,document);
这是我自定义的代码。调用脚本的js文件。我已尝试将其直接放置在文件和document ready中,但在这两种情况下仍会发生闪烁/移位:

SVGInjector js调用(在排队的“自定义”js文件中)

// For testing in IE8
if (!window.console){ console = {log: function() {}}; };

// Elements to inject
var mySVGsToInject = document.querySelectorAll(\'img.inject-me\');

// Options
var injectorOptions = {
evalScripts: \'once\',
pngFallback: \'assets/png\',
each: function (svg) {
    // Callback after each SVG is injected
    if (svg) console.log(\'SVG injected: \' + svg.getAttribute(\'id\'));
  }
};

 // Trigger the injection
  SVGInjector(mySVGsToInject, injectorOptions, function (totalSVGsInjected) {
 // Callback after all SVGs are injected
 console.log(\'We injected \' + totalSVGsInjected + \' SVG(s)!\');
});
谢谢!

3 个回复
SO网友:socki03

因此,注入的问题是javascript只会在加载所有内容后运行,这意味着,它需要再次向服务器发出所有图像请求。不幸的是,您可能无法在发出请求之前发出请求,因为它们是前端请求,而不是后端加载请求。。。

因此,您有几个选择,要么尝试淡入,要么确保图像开始时有足够的空间,或者两者都有。

我不确定你是否想让我详细说明,这就是为什么我没有回答这个问题。

SO网友:Hybrid Web Dev

您是否考虑过使用延迟加载/ajax方法加载元素?您可以将其与css和JS结合使用,以生成所需的结果。例如,加载隐藏的元素,然后使用onload事件(或任何其他绑定)。另一种方法是在实际加载图像之前,使用一个简单的预加载脚本预加载图像(发出Dom请求)。类似这样:

$(image_object_or_element_here).each(function(){ //preloader

      $(\'<img/>\')[0].src = image_source_here;

    });
这就是说,在等待加载脚本时阻止整个DOM加载通常是一种糟糕的做法/糟糕的性能和糟糕的UI。此外,请考虑这样的情况,即最终会出现脚本错误,从而阻止脚本运行。用户不会看到任何内容,也不会知道他们为什么没有获得内容。

SO网友:Mark Kaplun

真正的解决方案是不使用库,而是使用短代码或小部件将SVG插入到内容中。

SVGInjector是基于AJAX的,因此,无论您将其核心JS放置在何处以及如何放置,都需要到服务器进行另一次往返才能获取SVG本身,这意味着可能总是在已经绘制了页面的某些部分并且需要回流之后才绘制SVG。

减轻回流影响(或者换句话说,避免人们注意到回流)的一种方法是在页面上为将成为插入目标的元素预先分配足够的空间。例如,如果您知道SVG将生成一个40x40图像,那么只需要一个40x40div 在HTML中,您希望插入,并在那里插入SVG。这种策略可以很好地处理图像,但SVG比YMMV复杂得多。