How to import functions from different js file in a Vue+webpack+vue-loader project
Asked Answered
E

4

67

I have App.vue which has a template:

    <template>
     <div id="app">
         <login v-if="isTokenAvailable()"></login>
     </div>
    </template>

I've declared the isTokenAvailable method in the normal way for Vue inside methods. It uses a function that I wrote in a separate js file:

<script>
    import * as mylib from './mylib';

    export default {
      ....
        methods:{
            isTokenAvailable: () => {
                return mylib.myfunc();
            }
        }
    }
</script>

mylib starts like this:

    import models from './model/models'
    import axois from 'axios'

    export default function() {
        // functions and constants
    }

When I run the project, I get this below warning:

    export 'myfunc' (imported as 'mylib') was not found in './mylib'

I gather I'm not importing or declaring a javascript module correctly... but there seem to be so many ways to do it, added with the complexity of the scoping in Vue, I'm not sure what is the right way to do it?

Why this isn't a dupe of: How do I include a JavaScript file in another JavaScript file?

That one doesn't seem to fix the problem, specifically in the context of vuejs.

I have tried this:

<script>
    const mylib = require('./mylib');
    ...
</script>

With the function modified to: exports.myfunc = function()

Should I have some other dependency for this to work? Because I get a different error:

    [Vue warn]: Error in render function:
    TypeError: mylib.myfunc is not a function
Eudemonism answered 25/4, 2017 at 10:43 Comment(7)
Possible duplicate of How do I include a JavaScript file in another JavaScript file?Inulin
@DanielCooke I understand the above is similar, but it's not the same issue - this is in the context of Vue, and I have used export as in that answer and it still doesn't workEudemonism
You need to read up on Modules in Javascript to solve your problem. You will need to understand what module loaderr you are using. Are you using webpack? SystemJS? You could try const 'myfunc' = require('mylib'); the node.js import syntax.Inulin
@DanielCooke thanks, I'm using webpack. I have tried const ... but then I get a different error in the console: mylib.myfunc is not a functionEudemonism
"mylib.myfunc();" this means that you should return object, but u export functionShavonda
@KirillMatrosov sorry I don't understand - can you put into an answer with some more explanation pls?Eudemonism
I think it is related to a missing source map for the file: html5rocks.com/en/tutorials/developertools/sourcemapsKelter
D
100

Say I want to import data into a component from src/mylib.js:

var test = {
  foo () { console.log('foo') },
  bar () { console.log('bar') },
  baz () { console.log('baz') }
}

export default test

In my .Vue file I simply imported test from src/mylib.js:

<script> 
  import test from '@/mylib'

  console.log(test.foo())
  ...
</script>
Daudet answered 13/3, 2018 at 20:43 Comment(2)
This is perfect! Incase anyone is curios to why I wanted to go by this method, I needed a separate batch file to run functions in, now I can easily pass data to mylib and run the desired function with a return statement! Fabulous work.Leucite
Is this supposed to work with vanilla js? I get Unexpected identifier for the import partHardspun
E
39

After a few hours of messing around I eventually got something that works, partially answered in a similar issue here: How do I include a JavaScript file in another JavaScript file?

BUT there was an import that was screwing the rest of it up:

Use require in .vue files

<script>
  var mylib = require('./mylib');
  export default {
  ....

Exports in mylib

 exports.myfunc = () => {....}

Avoid import

The actual issue in my case (which I didn't think was relevant!) was that mylib.js was itself using other dependencies. The resulting error seems to have nothing to do with this, and there was no transpiling error from webpack but anyway I had:

import models from './model/models'
import axios from 'axios'

This works so long as I'm not using mylib in a .vue component. However as soon as I use mylib there, the error described in this issue arises.

I changed to:

let models = require('./model/models');
let axios = require('axios');

And all works as expected.

Eudemonism answered 25/4, 2017 at 13:55 Comment(3)
WHYYYYYYY??? This is ridiculous. If I'm using a transpiler such as Babble or Webpack, then whyyy can't we use import statements?? I want to pull my hair out...or abandon VueJS, not sure which.Protestantism
Thanks for this, I was working on this for 2 hours... your answer saved the day!Iconium
For me this throws require is not defined.Custumal
M
10

I like the answer of Anacrust, though, by the fact "console.log" is executed twice, I would like to do a small update for src/mylib.js:

let test = {
  foo () { return 'foo' },
  bar () { return 'bar' },
  baz () { return 'baz' }
}

export default test

All other code remains the same...

Mcgaha answered 13/10, 2018 at 8:1 Comment(0)
K
8

I was trying to organize my vue app code, and came across this question , since I have a lot of logic in my component and can not use other sub-coponents , it makes sense to use many functions in a separate js file and call them in the vue file, so here is my attempt

1)The Component (.vue file)

//MyComponent.vue file
<template>
  <div>
  <div>Hello {{name}}</div>
  <button @click="function_A">Read Name</button>
  <button @click="function_B">Write Name</button>
  <button @click="function_C">Reset</button>
  <div>{{message}}</div>
  </div>
 </template>


<script>
import Mylib from "./Mylib"; // <-- import
export default {
  name: "MyComponent",
  data() {
    return {
      name: "Bob",
      message: "click on the buttons"
    };
  },
  methods: {
    function_A() {
      Mylib.myfuncA(this); // <---read data
    },
    function_B() {
      Mylib.myfuncB(this); // <---write data
    },
    function_C() {
      Mylib.myfuncC(this); // <---write data
    }
  }
};
</script>

2)The External js file

//Mylib.js
let exports = {};

// this (vue instance) is passed as that , so we
// can read and write data from and to it as we please :)
exports.myfuncA = (that) => {
  that.message =
  "you hit ''myfuncA'' function that is located in Mylib.js  and data.name = " +
    that.name;
};

exports.myfuncB = (that) => {
  that.message =
  "you hit ''myfuncB'' function that is located in Mylib.js and now I will change the name to Nassim";
  that.name = "Nassim"; // <-- change name to Nassim
};

exports.myfuncC = (that) => {
  that.message =
  "you hit ''myfuncC'' function that is located in Mylib.js and now I will change the name back to Bob";
  that.name = "Bob"; // <-- change name to Bob
};

export default exports;

enter image description here 3)see it in action : https://codesandbox.io/s/distracted-pare-vuw7i?file=/src/components/MyComponent.vue


edit

after getting more experience with Vue , I found out that you could use mixins too to split your code into different files and make it easier to code and maintain see https://v2.vuejs.org/v2/guide/mixins.html

Konstanze answered 15/8, 2020 at 22:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.