Skip to content

Commit edd871a

Browse files
wip(docs): add "Load SVG dynamically (using watch())" example
1 parent 7060367 commit edd871a

File tree

1 file changed

+107
-2
lines changed

1 file changed

+107
-2
lines changed

docs/examples.md

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* [Nested components](#nested-components)
1515
* [Use SFC Custom Blocks for i18n](#use-sfc-custom-blocks-for-i18n)
1616
* [Use Options.getResource() and process the files (nearly) like webpack does](#use-optionsgetresource-and-process-the-files-nearly-like-webpack-does)
17+
* [Load SVG dynamically (using `watch()`)](#load-svg-dynamically-using-watch)
1718
* [Load SVG dynamically (using `async setup()` and `<Suspense>`)](#load-svg-dynamically-using-async-setup-and-suspense)
1819
* [Use remote components](#use-remote-components)
1920
<!--/toc-->
@@ -520,7 +521,7 @@ _see at [vuejs/rfcs](https://github.com/vuejs/rfcs/pull/231)_
520521
</html>
521522
```
522523
<!--example:target:import_style-->
523-
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A++%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%40next%2Fdist%2Fvue.runtime.global.prod.js%22%3E%3C%2Fscript%3E%0A++%3Cscript+src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvue3-sfc-loader%400.8.3%2Fdist%2Fvue3-sfc-loader.js%22%3E%3C%2Fscript%3E%0A%0A++%3Cscript%3E%0A%0A++++%2F*+%3C!--+*%2F%0A++++const+config+%3D+%7B%0A++++++files%3A+%7B%0A++++++++'%2Fstyle.css'%3A+%60%0A++++++++++++.styled+%7B+color%3A+red+%7D%0A++++++++%60%2C%0A++++++++'%2Fmain.vue'%3A+%60%0A++++++++++++%3Ctemplate%3E%0A++++++++++++++%3Cspan+class%3D%22styled%22%3Ehello%3C%2Fspan%3E+world%0A++++++++++++%3C%2Ftemplate%3E%0A++++++++++++%3Cscript%3E%0A++++++++++++++import+'.%2Fstyle.css'%0A++++++++++++++export+default+%7B%0A++++++++++++++%7D%0A++++++++++++%3C%2Fscript%3E%0A++++++++%60%2C%0A++++++%7D%0A++++%7D%3B%0A++++%2F*+--%3E+*%2F%0A%0A++++const+options+%3D+%7B%0A++++++moduleCache%3A+%7B+vue%3A+Vue+%7D%2C%0A++++++getFile%3A+url+%3D%3E+config.files%5Burl%5D%2C%0A++++++addStyle(textContent)+%7B%0A%0A++++++++const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A++++++++const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A++++++++document.head.insertBefore(style%2C+ref)%3B%0A++++++%7D%2C%0A++++++handleModule%3A+async+function+(type%2C+getContentData%2C+path%2C+options)+%7B+%0A++++++++switch+(type)+%7B+%0A++++++++++++case+'.css'%3A%0A++++++++++++++options.addStyle(await+getContentData(false))%3B%0A++++++++++++++return+null%3B%0A++++++++%7D+%0A++++++%7D%2C%0A++++%7D%0A%0A++++Vue.createApp(Vue.defineAsyncComponent(()+%3D%3E+window%5B'vue3-sfc-loader'%5D.loadModule('%2Fmain.vue'%2C+options))).mount(document.body)%3B%0A%0A++%3C%2Fscript%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:import_style-->
524+
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A++%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%40next%2Fdist%2Fvue.runtime.global.prod.js%22%3E%3C%2Fscript%3E%0A++%3Cscript+src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvue3-sfc-loader%400.8.3%2Fdist%2Fvue3-sfc-loader.js%22%3E%3C%2Fscript%3E%0A++%3Cscript%3E%0A%0A++++%2F*+%3C!--+*%2F%0A++++const+config+%3D+%7B%0A++++++files%3A+%7B%0A++++++++'%2Fstyle.css'%3A+%60%0A++++++++++.styled+%7B+color%3A+red+%7D%0A++++++++%60%2C%0A++++++++'%2Fmain.vue'%3A+%60%0A++++++++++%3Ctemplate%3E%0A++++++++++++%3Cspan+class%3D%22styled%22%3Ehello%3C%2Fspan%3E+world%0A++++++++++%3C%2Ftemplate%3E%0A++++++++++%3Cscript%3E%0A++++++++++++import+'.%2Fstyle.css'%0A++++++++++++export+default+%7B%0A++++++++++++%7D%0A++++++++++%3C%2Fscript%3E%0A++++++++%60%2C%0A++++++%7D%0A++++%7D%3B%0A++++%2F*+--%3E+*%2F%0A%0A++++const+options+%3D+%7B%0A++++++moduleCache%3A+%7B+vue%3A+Vue+%7D%2C%0A++++++getFile%3A+url+%3D%3E+config.files%5Burl%5D%2C%0A++++++addStyle(textContent)+%7B%0A%0A++++++++const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A++++++++const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A++++++++document.head.insertBefore(style%2C+ref)%3B%0A++++++%7D%2C%0A++++++handleModule%3A+async+function+(type%2C+getContentData%2C+path%2C+options)+%7B+%0A++++++++switch+(type)+%7B+%0A++++++++++case+'.css'%3A%0A++++++++++++options.addStyle(await+getContentData(false))%3B%0A++++++++++++return+null%3B%0A++++++++%7D+%0A++++++%7D%2C%0A++++%7D%0A%0A++++Vue.createApp(Vue.defineAsyncComponent(()+%3D%3E+window%5B'vue3-sfc-loader'%5D.loadModule('%2Fmain.vue'%2C+options))).mount(document.body)%3B%0A%0A++%3C%2Fscript%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:import_style-->
524525
[:top:](#readme)
525526

526527

@@ -958,6 +959,110 @@ In the following example we use a trick to preserve reactivity through the `Vue.
958959
[:top:](#readme)
959960

960961

962+
## Load SVG dynamically (using `watch()`)
963+
964+
<!--example:source:load_svg_watch-->
965+
```html
966+
<!DOCTYPE html>
967+
<html>
968+
<body>
969+
<script src="https://unpkg.com/vue@next/dist/vue.runtime.global.prod.js"></script>
970+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue3-sfc-loader.js"></script>
971+
<script>
972+
973+
/* <!-- */
974+
const config = {
975+
files: {
976+
'/circle0.svg': `<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50" /></svg>`,
977+
'/circle1.svg': `<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" /></svg>`,
978+
'/main.vue': `
979+
<template>
980+
<mycomponent
981+
:name="'circle' + index % 2"
982+
/>
983+
</template>
984+
<script>
985+
import mycomponent from './myComponent.vue'
986+
import { ref } from 'vue'
987+
988+
export default {
989+
components: {
990+
mycomponent
991+
},
992+
setup() {
993+
994+
const index = ref(0);
995+
setInterval(() => index.value++, 1000);
996+
return {
997+
index,
998+
}
999+
},
1000+
}
1001+
</script>
1002+
`,
1003+
'/myComponent.vue': `
1004+
<template>
1005+
<span v-html="svg" />
1006+
</template>
1007+
<script>
1008+
1009+
import { ref, watch } from 'vue'
1010+
1011+
function asyncToRef(callback) {
1012+
1013+
const val = ref();
1014+
watch(() => callback(), promise => promise.then(value => val.value = value), { immediate: true }); // TBD handle catch()...
1015+
return val;
1016+
}
1017+
1018+
export default {
1019+
props: {
1020+
name: String
1021+
},
1022+
setup(props) {
1023+
return {
1024+
svg: asyncToRef(() => import('./' + props.name + '.svg')),
1025+
}
1026+
}
1027+
}
1028+
1029+
</script>
1030+
`
1031+
}
1032+
};
1033+
/* --> */
1034+
1035+
const options = {
1036+
moduleCache: { vue: Vue },
1037+
getFile: url => config.files[url],
1038+
addStyle(textContent) {
1039+
1040+
const style = Object.assign(document.createElement('style'), { textContent });
1041+
const ref = document.head.getElementsByTagName('style')[0] || null;
1042+
document.head.insertBefore(style, ref);
1043+
},
1044+
handleModule: async function (type, getContentData, path, options) {
1045+
switch (type) {
1046+
case '.svg':
1047+
return getContentData(false);
1048+
}
1049+
},
1050+
}
1051+
1052+
Vue.createApp(Vue.defineAsyncComponent(() => window['vue3-sfc-loader'].loadModule('/main.vue', options))).mount(document.body);
1053+
1054+
</script>
1055+
1056+
</body>
1057+
</html>
1058+
```
1059+
<!--example:target:load_svg_watch-->
1060+
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%40next%2Fdist%2Fvue.runtime.global.prod.js%22%3E%3C%2Fscript%3E%0A%3Cscript+src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvue3-sfc-loader%400.8.3%2Fdist%2Fvue3-sfc-loader.js%22%3E%3C%2Fscript%3E%0A%3Cscript%3E%0A%0A++%2F*+%3C!--+*%2F%0A++const+config+%3D+%7B%0A++++files%3A+%7B%0A++++++'%2Fcircle0.svg'%3A+%60%3Csvg+viewBox%3D%220+0+100+100%22+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle+cx%3D%2250%22+cy%3D%2250%22+r%3D%2250%22+%2F%3E%3C%2Fsvg%3E%60%2C%0A++++++'%2Fcircle1.svg'%3A+%60%3Csvg+viewBox%3D%220+0+100+100%22+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle+cx%3D%2250%22+cy%3D%2250%22+r%3D%2240%22+%2F%3E%3C%2Fsvg%3E%60%2C%0A++++++'%2Fmain.vue'%3A+%60%0A++++++++%3Ctemplate%3E%0A++++++++++%3Cmycomponent%0A++++++++++++%3Aname%3D%22'circle'+%2B+index+%25+2%22%0A++++++++++%2F%3E%0A++++++++%3C%2Ftemplate%3E%0A++++++++%3Cscript%3E%0A++++++++++import+mycomponent+from+'.%2FmyComponent.vue'%0A++++++++++import+%7B+ref+%7D+from+'vue'%0A%0A++++++++++export+default+%7B%0A++++++++++++components%3A+%7B%0A++++++++++++++mycomponent%0A++++++++++++%7D%2C%0A++++++++++++setup()+%7B%0A++++++++++++++%0A++++++++++++++const+index+%3D+ref(0)%3B%0A++++++++++++++setInterval(()+%3D%3E+index.value%2B%2B%2C+1000)%3B%0A++++++++++++++return+%7B%0A++++++++++++++++index%2C%0A++++++++++++++%7D%0A++++++++++++%7D%2C%0A++++++++++%7D%0A++++++++%3C%2Fscript%3E%0A++++++%60%2C%0A++++++'%2FmyComponent.vue'%3A+%60%0A++++++++%3Ctemplate%3E%0A++++++++++%3Cspan+v-html%3D%22svg%22+%2F%3E%0A++++++++%3C%2Ftemplate%3E%0A++++++++%3Cscript%3E%0A%0A++++++++++import+%7B+ref%2C+watch+%7D+from+'vue'%0A%0A++++++++++function+asyncToRef(callback)+%7B%0A%0A++++++++++++const+val+%3D+ref()%3B%0A++++++++++++watch(()+%3D%3E+callback()%2C+promise+%3D%3E+promise.then(value+%3D%3E+val.value+%3D+value)%2C+%7B+immediate%3A+true+%7D)%3B++%2F%2F+TBD+handle+catch()...%0A++++++++++++return+val%3B%0A++++++++++%7D%0A%0A++++++++++export+default+%7B%0A++++++++++++props%3A+%7B%0A++++++++++++++name%3A+String%0A++++++++++++%7D%2C%0A++++++++++++setup(props)+%7B%0A++++++++++++++return+%7B%0A++++++++++++++++svg%3A+asyncToRef(()+%3D%3E+import('.%2F'+%2B+props.name+%2B+'.svg'))%2C%0A++++++++++++++%7D%0A++++++++++++%7D%0A++++++++++%7D%0A%0A++++++++%3C%2Fscript%3E%0A++++++%60%0A++++%7D%0A++%7D%3B%0A++%2F*+--%3E+*%2F%0A%0A++const+options+%3D+%7B%0A++++moduleCache%3A+%7B+vue%3A+Vue+%7D%2C%0A++++getFile%3A+url+%3D%3E+config.files%5Burl%5D%2C%0A++++addStyle(textContent)+%7B%0A%0A++++++const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A++++++const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A++++++document.head.insertBefore(style%2C+ref)%3B%0A++++%7D%2C%0A++++handleModule%3A+async+function+(type%2C+getContentData%2C+path%2C+options)+%7B+%0A++++++switch+(type)+%7B+%0A++++++++case+'.svg'%3A%0A++++++++++return+getContentData(false)%3B%0A++++++%7D+%0A++++%7D%2C%0A++%7D%0A%0A++Vue.createApp(Vue.defineAsyncComponent(()+%3D%3E+window%5B'vue3-sfc-loader'%5D.loadModule('%2Fmain.vue'%2C+options))).mount(document.body)%3B%0A%0A%3C%2Fscript%3E%0A%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:load_svg_watch-->
1061+
1062+
[:top:](#readme)
1063+
1064+
1065+
9611066
## Load SVG dynamically (using `async setup()` and `<Suspense>`)
9621067

9631068
<!--example:source:load_svg_async_setup-->
@@ -1036,7 +1141,7 @@ In the following example we use a trick to preserve reactivity through the `Vue.
10361141
</html>
10371142
```
10381143
<!--example:target:load_svg_async_setup-->
1039-
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%40next%2Fdist%2Fvue.runtime.global.prod.js%22%3E%3C%2Fscript%3E%0A%3Cscript+src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvue3-sfc-loader%400.8.3%2Fdist%2Fvue3-sfc-loader.js%22%3E%3C%2Fscript%3E%0A%3Cscript%3E%0A%0A++%2F*+%3C!--+*%2F%0A++const+config+%3D+%7B%0A++++files%3A+%7B%0A++++++'%2Fcircle.svg'%3A+%60%3Csvg+viewBox%3D%220+0+100+100%22+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle+cx%3D%2250%22+cy%3D%2250%22+r%3D%2250%22+%2F%3E%3C%2Fsvg%3E%60%2C%0A++++++'%2Fmain.vue'%3A+%60%0A++++++++%3Ctemplate%3E%0A++++++++++%3CSuspense%3E%0A++++++++++++%3Cmycomponent%0A++++++++++++++%3Aname%3D%22'circle'%22%0A++++++++++++%2F%3E%0A++++++++++%3C%2FSuspense%3E%0A++++++++%3C%2Ftemplate%3E%0A++++++++%3Cscript%3E%0A++++++++++import+mycomponent+from+'.%2FmyComponent.vue'%0A++++++++++export+default+%7B%0A++++++++++++components%3A+%7B%0A++++++++++++++mycomponent%0A++++++++++++%7D%2C%0A++++++++++%7D%0A++++++++%3C%2Fscript%3E%0A++++++%60%2C%0A++++++'%2FmyComponent.vue'%3A+%60%0A++++++++%3Ctemplate%3E%0A++++++++++%3Cspan+v-html%3D%22svg%22%2F%3E%0A++++++++%3C%2Ftemplate%3E%0A++++++++%3Cscript%3E%0A%0A++++++++++import+%7B+ref+%7D+from+'vue'%0A%0A++++++++++export+default+%7B%0A++++++++++++props%3A+%7B%0A++++++++++++++name%3A+String%0A++++++++++++%7D%2C%0A++++++++++++async+setup(props)+%7B%0A++++++++++++++return+%7B%0A++++++++++++++++svg%3A+await+import('.%2F'+%2B+props.name+%2B+'.svg')%2C%0A++++++++++++++%7D%0A++++++++++++%7D%0A++++++++++%7D%0A%0A++++++++%3C%2Fscript%3E++++++++%0A++++++%60%0A++++%7D%0A++%7D%3B%0A++%2F*+--%3E+*%2F%0A%0A++const+options+%3D+%7B%0A++++moduleCache%3A+%7B+vue%3A+Vue+%7D%2C%0A++++getFile%3A+url+%3D%3E+config.files%5Burl%5D%2C%0A++++addStyle(textContent)+%7B%0A%0A++++++const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A++++++const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A++++++document.head.insertBefore(style%2C+ref)%3B%0A++++%7D%2C%0A++++handleModule%3A+async+function+(type%2C+getContentData%2C+path%2C+options)+%7B+%0A++++++switch+(type)+%7B+%0A++++++++case+'.svg'%3A%0A++++++++++return+getContentData(false)%3B%0A++++++%7D+%0A++++%7D%2C%0A++%7D%0A%0A++Vue.createApp(Vue.defineAsyncComponent(()+%3D%3E+window%5B'vue3-sfc-loader'%5D.loadModule('%2Fmain.vue'%2C+options))).mount(document.body)%3B%0A%0A%3C%2Fscript%3E%0A%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:load_svg_async_setup-->
1144+
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%40next%2Fdist%2Fvue.runtime.global.prod.js%22%3E%3C%2Fscript%3E%0A%3Cscript+src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvue3-sfc-loader%400.8.3%2Fdist%2Fvue3-sfc-loader.js%22%3E%3C%2Fscript%3E%0A%3Cscript%3E%0A%0A++%2F*+%3C!--+*%2F%0A++const+config+%3D+%7B%0A++++files%3A+%7B%0A++++++'%2Fcircle.svg'%3A+%60%3Csvg+viewBox%3D%220+0+100+100%22+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle+cx%3D%2250%22+cy%3D%2250%22+r%3D%2250%22+%2F%3E%3C%2Fsvg%3E%60%2C%0A++++++'%2Fmain.vue'%3A+%60%0A++++++++%3Ctemplate%3E%0A++++++++++%3CSuspense%3E%0A++++++++++++%3Cmycomponent%0A++++++++++++++%3Aname%3D%22'circle'%22%0A++++++++++++%2F%3E%0A++++++++++%3C%2FSuspense%3E%0A++++++++%3C%2Ftemplate%3E%0A++++++++%3Cscript%3E%0A++++++++++import+mycomponent+from+'.%2FmyComponent.vue'%0A++++++++++export+default+%7B%0A++++++++++++components%3A+%7B%0A++++++++++++++mycomponent%0A++++++++++++%7D%2C%0A++++++++++%7D%0A++++++++%3C%2Fscript%3E%0A++++++%60%2C%0A++++++'%2FmyComponent.vue'%3A+%60%0A++++++++%3Ctemplate%3E%0A++++++++++%3Cspan+v-html%3D%22svg%22%2F%3E%0A++++++++%3C%2Ftemplate%3E%0A++++++++%3Cscript%3E%0A++++++++++export+default+%7B%0A++++++++++++props%3A+%7B%0A++++++++++++++name%3A+String%0A++++++++++++%7D%2C%0A++++++++++++async+setup(props)+%7B%0A++++++++++++++return+%7B%0A++++++++++++++++svg%3A+await+import('.%2F'+%2B+props.name+%2B+'.svg')%2C%0A++++++++++++++%7D%0A++++++++++++%7D%0A++++++++++%7D%0A++++++++%3C%2Fscript%3E++++++++%0A++++++%60%0A++++%7D%0A++%7D%3B%0A++%2F*+--%3E+*%2F%0A%0A++const+options+%3D+%7B%0A++++moduleCache%3A+%7B+vue%3A+Vue+%7D%2C%0A++++getFile%3A+url+%3D%3E+config.files%5Burl%5D%2C%0A++++addStyle(textContent)+%7B%0A%0A++++++const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A++++++const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A++++++document.head.insertBefore(style%2C+ref)%3B%0A++++%7D%2C%0A++++handleModule%3A+async+function+(type%2C+getContentData%2C+path%2C+options)+%7B+%0A++++++switch+(type)+%7B+%0A++++++++case+'.svg'%3A%0A++++++++++return+getContentData(false)%3B%0A++++++%7D+%0A++++%7D%2C%0A++%7D%0A%0A++Vue.createApp(Vue.defineAsyncComponent(()+%3D%3E+window%5B'vue3-sfc-loader'%5D.loadModule('%2Fmain.vue'%2C+options))).mount(document.body)%3B%0A%0A%3C%2Fscript%3E%0A%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:load_svg_async_setup-->
10401145

10411146
[:top:](#readme)
10421147

0 commit comments

Comments
 (0)