Setup and use a component in uibuilder with Vue3 and vue3 sfc loader - TotallyInformation/node-red-contrib-uibuilder GitHub Wiki
Many thanks to Fabio Marzocca for this contribution.
This page is the Vue v3 equivalent of using http-vue-loader with Vue v2.
Setup and use a component in uibuilder, with Vue3
and vue3-sfc-loader
.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Node-RED uibuilder</title>
<meta name="description" content="Node-RED uibuilder ">
<link type="text/css" rel="stylesheet" href="./index.css" media="all">
</head>
<body>
<div id="my-app">
<my-component :greeting="myGreeting" :who="myWho"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue3-sfc-loader/dist/vue3-sfc-loader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-router.global.js"></script>
<script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
<script src="./uibuilderfe.min.js">/* REQUIRED: remove 'min.' to use dev version */</script>
<script src="./index.js"></script>
</body>
</html>
index.js
/* eslint-disable strict */
/* jshint browser: true, esversion: 6, asi: true */
/* globals uibuilder */
// @ts-nocheck
/** Minimalist code for uibuilder and Node-RED */
'use strict'
const { createApp, ref } = Vue
const options = {
moduleCache: {
vue: Vue
},
async getFile(url) {
const res = await fetch(url);
if ( !res.ok )
throw Object.assign(new Error(res.statusText + ' ' + url), { res });
return {
getContentData: asBinary => asBinary ? res.arrayBuffer() : res.text(),
}
},
addStyle(textContent) {
const style = Object.assign(document.createElement('style'), { textContent });
const ref = document.head.getElementsByTagName('style')[0] || null;
document.head.insertBefore(style, ref);
},
}
const { loadModule } = window['vue3-sfc-loader'];
const app = Vue.createApp({
data() {
return {
myGreeting: 'Hi there',
myWho: 'oh wise one!',
}
}, // --- End of data --- //
components: {
'my-component': Vue.defineAsyncComponent( () => loadModule('./myComponent.vue', options) )
},
})
app.mount('#my-app')
myComponent.vue
<template>
<div>
<div class="hello">
{{ greeting }} {{ who }}
</div>
<slot>
Default slot content, replace with your own text between the component tags.
See the <a href="https://vuejs.org/guide/components/slots.html" target="_blank">VueJS documentation for
slots</a> for more information.
</slot>
<div class="example">{{ msg }}</div>
</div>
</template>
<script>
export default {
props: {
greeting: String,
who: String
},
data() {
return {
msg: 'This is a message!',
color: 'red',
}
}
}
</script>
<style scoped>
.hello {
background-color: #ffe;
font-size: 2rem;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
margin: 25px;
}
.example {
margin-top: 5em;
color: v-bind('color');
text-align:center;
}
</style>