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.
|
||||
*/
|
||||
@State() ariaLabel: string = '';
|
||||
@Prop() ariaLabel: string = '';
|
||||
|
||||
/**
|
||||
* @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 = '';
|
||||
|
||||
|
||||
@State() svgContent: string = null;
|
||||
@Prop({ context: 'isServer'}) private isServer: boolean;
|
||||
|
||||
|
||||
getSvgUrl() {
|
||||
const iconName = this.iconName;
|
||||
if (iconName !== null) {
|
||||
return `${publicPath}svg/${iconName}.svg`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@State() private svgContent: string = null;
|
||||
|
||||
|
||||
get iconName() {
|
||||
private get iconName() {
|
||||
// if no name was passed set iconName to null
|
||||
if (!this.name) {
|
||||
return null;
|
||||
@ -117,21 +110,63 @@ export class Icon {
|
||||
}
|
||||
|
||||
|
||||
static loadSvgContent(svgUrl: string, callback: {(loadedSvgContent: string): void}) {
|
||||
render() {
|
||||
if (this.isServer) {
|
||||
return <div class="icon-inner">{/* ssr */}</div>;
|
||||
}
|
||||
|
||||
const svgUrl = getSvgUrl(this.iconName);
|
||||
if (!svgUrl) {
|
||||
// we don't have good data
|
||||
return <div class="icon-inner">{/* invalid svg */}</div>;
|
||||
}
|
||||
|
||||
const svgContent = svgContents[svgUrl];
|
||||
if (svgContent === this.svgContent) {
|
||||
// we've already loaded up this svg at one point
|
||||
// and the svg content we've loaded and assigned checks out
|
||||
// render this svg!!
|
||||
return <div class="icon-inner" innerHTML={svgContent}></div>;
|
||||
}
|
||||
|
||||
// haven't loaded this svg yet
|
||||
// start the request
|
||||
loadSvgContent(svgUrl, loadedSvgContent => {
|
||||
// we're finished loading the svg content!
|
||||
// set to this.svgContent so we do another render
|
||||
this.svgContent = loadedSvgContent;
|
||||
});
|
||||
|
||||
// actively requesting the svg, so let's just render a div for now
|
||||
return <div class="icon-inner">{/* loading svg */}</div>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getSvgUrl(iconName: string) {
|
||||
if (iconName !== null) {
|
||||
return `${publicPath}svg/${iconName}.svg`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
IonIcon.loadCallbacks[svgUrl] = IonIcon.loadCallbacks[svgUrl] || [];
|
||||
IonIcon.loadCallbacks[svgUrl].push(callback);
|
||||
loadCallbacks[svgUrl] = loadCallbacks[svgUrl] || [];
|
||||
loadCallbacks[svgUrl].push(callback);
|
||||
|
||||
if (IonIcon.activeRequests[svgUrl]) {
|
||||
if (activeRequests[svgUrl]) {
|
||||
// already requesting this url, don't bother again kicking off another
|
||||
return;
|
||||
}
|
||||
|
||||
// add this url to our list of active requests
|
||||
IonIcon.activeRequests[svgUrl] = true;
|
||||
activeRequests[svgUrl] = true;
|
||||
|
||||
// kick off the request for the external svg file
|
||||
const xhr = new XMLHttpRequest();
|
||||
@ -139,7 +174,7 @@ export class Icon {
|
||||
// awesome, we've finished loading the svg file
|
||||
|
||||
// remove this url from the active requests
|
||||
delete IonIcon.activeRequests[svgUrl];
|
||||
delete activeRequests[svgUrl];
|
||||
|
||||
// this response is the content of the svg file we're looking for
|
||||
let svgContent = this.responseText;
|
||||
@ -151,17 +186,17 @@ export class Icon {
|
||||
}
|
||||
|
||||
// cache the svg content in the global IonIcon constant
|
||||
IonIcon.svgContents[svgUrl] = svgContent;
|
||||
svgContents[svgUrl] = svgContent;
|
||||
|
||||
// find any callbacks waiting on this url
|
||||
const svgLoadCallbacks = IonIcon.loadCallbacks[svgUrl];
|
||||
const svgLoadCallbacks = loadCallbacks[svgUrl];
|
||||
if (svgLoadCallbacks) {
|
||||
// loop through all the callbacks that are waiting on the svg content
|
||||
for (var i = 0; i < svgLoadCallbacks.length; i++) {
|
||||
svgLoadCallbacks.forEach(cb => {
|
||||
// fire off this callback which was provided by an instance
|
||||
svgLoadCallbacks[i](svgContent);
|
||||
}
|
||||
delete IonIcon.loadCallbacks[svgUrl];
|
||||
cb(svgContent);
|
||||
});
|
||||
delete loadCallbacks[svgUrl];
|
||||
}
|
||||
});
|
||||
|
||||
@ -176,45 +211,6 @@ export class Icon {
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const svgUrl = this.getSvgUrl();
|
||||
if (!svgUrl) {
|
||||
// we don't have good data
|
||||
return <div class="icon-inner">{/* invalid svg */}</div>;
|
||||
}
|
||||
|
||||
const svgContent = IonIcon.svgContents[svgUrl];
|
||||
if (svgContent === this.svgContent) {
|
||||
// we've already loaded up this svg at one point
|
||||
// and the svg content we've loaded and assigned checks out
|
||||
// render this svg!!
|
||||
return <div class="icon-inner" innerHTML={svgContent}></div>;
|
||||
}
|
||||
|
||||
// haven't loaded this svg yet
|
||||
// start the request
|
||||
Icon.loadSvgContent(svgUrl, loadedSvgContent => {
|
||||
// we're finished loading the svg content!
|
||||
// set to this.svgContent so we do another render
|
||||
this.svgContent = loadedSvgContent;
|
||||
});
|
||||
|
||||
// actively requesting the svg, so let's just render a div for now
|
||||
return <div class="icon-inner">{/* loading svg */}</div>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const IonIcon: GlobalIonIcon = {
|
||||
activeRequests: {},
|
||||
loadCallbacks: [] as any,
|
||||
svgContents: {}
|
||||
};
|
||||
|
||||
|
||||
interface GlobalIonIcon {
|
||||
activeRequests: {[url: string]: boolean};
|
||||
loadCallbacks: {[url: string]: {(loadedSvgContent: string): void}[]};
|
||||
svgContents: {[url: string]: string};
|
||||
}
|
||||
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