vue.jsvuejs3

JavaScript function re-use in different Vue templates


I am using the Vue3 options API within a static HTML page (well, actually its dynamically generated .NET MVC, but that is irrelevant to my question). I had originally had this working with Vue2x, but after updating to Vue3, my original method doesn't seem to work anymore.

I have some plain JavaScript code that can be used to format a person's date of birth in a few different ways. I want to be able to reuse this code across several different pages/apps. Here is a few lines of my "DataFormatting.js" file:

// DataFormatting.js

function formatDob(dob) {
    if (dob) {
        dob = new Date(dob);
        if (isValidDate(dob)) {
            var options = { month: 'short', day: 'numeric', year: 'numeric' };
            return dob.toLocaleDateString("default", options);
        }
    }
    return "";
}

function formatDobWithAge(dob) {
    if (dob) {
        dob = new Date(dob);
        if (isValidDate(dob)) {
            var age = getAge(dob, new Date());
            var options = { month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' };
            return dob.toLocaleDateString("default", options) + " (" + age + " yo)";
        }
    }
    return "";
}

// other formatting functions omitted

function isValidDate(d) {
    return d instanceof Date && !isNaN(d);
}

Now I want to be able to reuse this file/library across multiple different pages (or Vue app instances).

I used to be able to just simply include this file with a <script> tag like so:

<script src="~/js/DataFormatting.js"></script>

And then, from the template, I could reference my JavaScript library functions like so:

<tr v-for="person in people">
    <td>{{ formatDobWithAge(person.DateOfBirth) }}</td>
</tr>

Using Vue3, this is what my setup looks like:

<script src="~/lib/vue/dist/vue.global.js"></script>
<script>
    const { createApp } = Vue

    createApp({
        data() {
            return {
                people: @Html.Raw(JsonSerializer.Serialize(Model.People))
            }
        },
        mounted() {
        },
        computed: {
        },
        watch: {
        },
        methods: {
        }
    }).mount('#app');
</script>

Why can I not reference this extra JavaScript library anymore? What do I need to do so that I can reference a set of JS functions for formatting purposes? Do I need to get away from a plain JS file and move it to something more Vue (component?) friendly?


Solution

  • You can easily convert DataFormatting.js into a module, the moment you make something in a file exportable it qualifies as a module.

    Ensure your file is in the scope of your src directory and import your functions wherever you need them in the specific .vue files or other JS files that need to leverage those functions.

    // DateFormatting.js
    
    export function formatDob(dob) { ... }
    
    export function formatDobWithAge(dob) { ... }
    
    function isValidDate(d) { ... }
    
    
    // example.vue
    <script>
      import { formatDob, formatDobWithAge } from 'DateFormatting.js'
    
      ... {
    
        data() { ... }
        methods: { formatDob, formatDobWithAge }
    
     ...
    
    </script>
    

    P.S. To expand on understanding ES Modules, You can do the same with ES module version of lodash or any ES supporting lib for that matter, The lodash-es lib can be leveraged in the template with the least effort by registering only what you use in methods.

    https://www.npmjs.com/package/lodash-es