Skip to content

Setup and use a component in uibuilder with Vue3 and vue3 sfc loader

Fabio Marzocca edited this page Jul 16, 2022 · 3 revisions

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>
Clone this wiki locally