mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 13:32:54 +08:00
fix(icon): prevent ssr rendering
This commit is contained in:
@ -19,7 +19,7 @@ export class Icon {
|
|||||||
/**
|
/**
|
||||||
* @input {string} Specifies the label to use for accessibility. Defaults to the icon name.
|
* @input {string} Specifies the label to use for accessibility. Defaults to the icon name.
|
||||||
*/
|
*/
|
||||||
@State() ariaLabel: string = '';
|
@Prop() ariaLabel: string = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @input {string} Specifies which icon to use. The appropriate icon will be used based on the mode.
|
* @input {string} Specifies which icon to use. The appropriate icon will be used based on the mode.
|
||||||
@ -38,20 +38,13 @@ export class Icon {
|
|||||||
@Prop() md: string = '';
|
@Prop() md: string = '';
|
||||||
|
|
||||||
|
|
||||||
@State() svgContent: string = null;
|
@Prop({ context: 'isServer'}) private isServer: boolean;
|
||||||
|
|
||||||
|
|
||||||
getSvgUrl() {
|
@State() private svgContent: string = null;
|
||||||
const iconName = this.iconName;
|
|
||||||
if (iconName !== null) {
|
|
||||||
return `${publicPath}svg/${iconName}.svg`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
get iconName() {
|
private get iconName() {
|
||||||
// if no name was passed set iconName to null
|
// if no name was passed set iconName to null
|
||||||
if (!this.name) {
|
if (!this.name) {
|
||||||
return null;
|
return null;
|
||||||
@ -117,73 +110,18 @@ export class Icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static loadSvgContent(svgUrl: string, callback: {(loadedSvgContent: string): void}) {
|
render() {
|
||||||
// static since all IonIcons use this same function and pointing at global/shared data
|
if (this.isServer) {
|
||||||
// passed in callback will have instance info
|
return <div class="icon-inner">{/* ssr */}</div>;
|
||||||
|
|
||||||
// add to the list of callbacks to fiure when this url is finished loading
|
|
||||||
IonIcon.loadCallbacks[svgUrl] = IonIcon.loadCallbacks[svgUrl] || [];
|
|
||||||
IonIcon.loadCallbacks[svgUrl].push(callback);
|
|
||||||
|
|
||||||
if (IonIcon.activeRequests[svgUrl]) {
|
|
||||||
// already requesting this url, don't bother again kicking off another
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add this url to our list of active requests
|
const svgUrl = getSvgUrl(this.iconName);
|
||||||
IonIcon.activeRequests[svgUrl] = true;
|
|
||||||
|
|
||||||
// kick off the request for the external svg file
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.addEventListener('load', function() {
|
|
||||||
// awesome, we've finished loading the svg file
|
|
||||||
|
|
||||||
// remove this url from the active requests
|
|
||||||
delete IonIcon.activeRequests[svgUrl];
|
|
||||||
|
|
||||||
// this response is the content of the svg file we're looking for
|
|
||||||
let svgContent = this.responseText;
|
|
||||||
|
|
||||||
if (this.status >= 400) {
|
|
||||||
// umm, not awesome, something is up
|
|
||||||
console.error('Icon could not be loaded:', svgUrl);
|
|
||||||
svgContent = `<!--error loading svg-->`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cache the svg content in the global IonIcon constant
|
|
||||||
IonIcon.svgContents[svgUrl] = svgContent;
|
|
||||||
|
|
||||||
// find any callbacks waiting on this url
|
|
||||||
const svgLoadCallbacks = IonIcon.loadCallbacks[svgUrl];
|
|
||||||
if (svgLoadCallbacks) {
|
|
||||||
// loop through all the callbacks that are waiting on the svg content
|
|
||||||
for (var i = 0; i < svgLoadCallbacks.length; i++) {
|
|
||||||
// fire off this callback which was provided by an instance
|
|
||||||
svgLoadCallbacks[i](svgContent);
|
|
||||||
}
|
|
||||||
delete IonIcon.loadCallbacks[svgUrl];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
xhr.addEventListener('error', () => {
|
|
||||||
// umm, idk
|
|
||||||
console.error('Icon could not be loaded:', svgUrl);
|
|
||||||
});
|
|
||||||
|
|
||||||
// let's do this!
|
|
||||||
xhr.open('GET', svgUrl, true);
|
|
||||||
xhr.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const svgUrl = this.getSvgUrl();
|
|
||||||
if (!svgUrl) {
|
if (!svgUrl) {
|
||||||
// we don't have good data
|
// we don't have good data
|
||||||
return <div class="icon-inner">{/* invalid svg */}</div>;
|
return <div class="icon-inner">{/* invalid svg */}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const svgContent = IonIcon.svgContents[svgUrl];
|
const svgContent = svgContents[svgUrl];
|
||||||
if (svgContent === this.svgContent) {
|
if (svgContent === this.svgContent) {
|
||||||
// we've already loaded up this svg at one point
|
// we've already loaded up this svg at one point
|
||||||
// and the svg content we've loaded and assigned checks out
|
// and the svg content we've loaded and assigned checks out
|
||||||
@ -193,7 +131,7 @@ export class Icon {
|
|||||||
|
|
||||||
// haven't loaded this svg yet
|
// haven't loaded this svg yet
|
||||||
// start the request
|
// start the request
|
||||||
Icon.loadSvgContent(svgUrl, loadedSvgContent => {
|
loadSvgContent(svgUrl, loadedSvgContent => {
|
||||||
// we're finished loading the svg content!
|
// we're finished loading the svg content!
|
||||||
// set to this.svgContent so we do another render
|
// set to this.svgContent so we do another render
|
||||||
this.svgContent = loadedSvgContent;
|
this.svgContent = loadedSvgContent;
|
||||||
@ -206,15 +144,73 @@ export class Icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const IonIcon: GlobalIonIcon = {
|
function getSvgUrl(iconName: string) {
|
||||||
activeRequests: {},
|
if (iconName !== null) {
|
||||||
loadCallbacks: [] as any,
|
return `${publicPath}svg/${iconName}.svg`;
|
||||||
svgContents: {}
|
}
|
||||||
};
|
return null;
|
||||||
|
|
||||||
|
|
||||||
interface GlobalIonIcon {
|
|
||||||
activeRequests: {[url: string]: boolean};
|
|
||||||
loadCallbacks: {[url: string]: {(loadedSvgContent: string): void}[]};
|
|
||||||
svgContents: {[url: string]: string};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function loadSvgContent(svgUrl: string, callback: {(loadedSvgContent: string): void}) {
|
||||||
|
// static since all IonIcons use this same function and pointing at global/shared data
|
||||||
|
// passed in callback will have instance info
|
||||||
|
|
||||||
|
// add to the list of callbacks to fiure when this url is finished loading
|
||||||
|
loadCallbacks[svgUrl] = loadCallbacks[svgUrl] || [];
|
||||||
|
loadCallbacks[svgUrl].push(callback);
|
||||||
|
|
||||||
|
if (activeRequests[svgUrl]) {
|
||||||
|
// already requesting this url, don't bother again kicking off another
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add this url to our list of active requests
|
||||||
|
activeRequests[svgUrl] = true;
|
||||||
|
|
||||||
|
// kick off the request for the external svg file
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.addEventListener('load', function() {
|
||||||
|
// awesome, we've finished loading the svg file
|
||||||
|
|
||||||
|
// remove this url from the active requests
|
||||||
|
delete activeRequests[svgUrl];
|
||||||
|
|
||||||
|
// this response is the content of the svg file we're looking for
|
||||||
|
let svgContent = this.responseText;
|
||||||
|
|
||||||
|
if (this.status >= 400) {
|
||||||
|
// umm, not awesome, something is up
|
||||||
|
console.error('Icon could not be loaded:', svgUrl);
|
||||||
|
svgContent = `<!--error loading svg-->`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the svg content in the global IonIcon constant
|
||||||
|
svgContents[svgUrl] = svgContent;
|
||||||
|
|
||||||
|
// find any callbacks waiting on this url
|
||||||
|
const svgLoadCallbacks = loadCallbacks[svgUrl];
|
||||||
|
if (svgLoadCallbacks) {
|
||||||
|
// loop through all the callbacks that are waiting on the svg content
|
||||||
|
svgLoadCallbacks.forEach(cb => {
|
||||||
|
// fire off this callback which was provided by an instance
|
||||||
|
cb(svgContent);
|
||||||
|
});
|
||||||
|
delete loadCallbacks[svgUrl];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.addEventListener('error', () => {
|
||||||
|
// umm, idk
|
||||||
|
console.error('Icon could not be loaded:', svgUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
// let's do this!
|
||||||
|
xhr.open('GET', svgUrl, true);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const activeRequests: {[url: string]: boolean} = {};
|
||||||
|
const loadCallbacks: {[url: string]: {(loadedSvgContent: string): void}[]} = [] as any;
|
||||||
|
const svgContents: {[url: string]: string} = {};
|
||||||
|
Reference in New Issue
Block a user