How to access "this" context (Vue/Nuxt instance) in a VanillaJS file? - javascript

I have a function inside a .js file in a nuxt 2 project.
Basically I need to use a nuxt module property from nuxt.config like this this.nuxt.options. inside a function in a normal .js file.
For example:
aNormalJsFile.js
if (this.nuxt.options.module.triggers.isActive) {
// do something
}
But now I can't because it doesn't know what is Nuxt of course. I'm getting this error:
Cannot read properties of undefined (reading 'nuxt')

If you want to inject a Vue/Nuxt instance inside of a .js file (vanilla JS), you can follow this helper function approach
/src/utils/printCoolNumber.js
export const printIt = (VueInstance) => console.log(VueInstance.coolNumber)
// ☝🏻 basically does console.log(this.coolNumber) as in a .vue file
Any .vue file
<script>
import { printIt } from "#/utils/printCoolNumber";
export default {
data() {
return {
coolNumber: 12,
};
},
mounted() {
printIt(this) // πŸ‘ˆπŸ» Vue instance ("this") passed here, it prints 12 in the console
},
};
</script>
I wouldn't say that this is the best approach in the long run (using Composables is usually still better) but it is great for small helper functions where you don't need too much Vue-specific methods.

Related

Nuxtjs custom module

I'm quite new to Nuxtjs so I made a test project which purpose is merely the (of course) testing of Nuxtjs functionalities.
Currently I'm trying to create a simple custom module: afaik a module is basically a wrapper around a vou/js library/plugin, something like a high-level integration used to expose configurations on how the underlying library/plugin is imported and used in the Nuxt application.
So I'm trying with a simple module that declare some plain js classes that I'll use in my application, e.g. Order and Product, and that's what I came out with:
Directory structure
pages
the-page.vue
modules
classes
index.js
order.js
/modules/classes/index.js
const path = require('path')
export default function (moduleOptions) {
const { nuxt } = this
// add the debug plugin
this.addPlugin({
src: path.resolve(__dirname, 'order.js'),
})
}
/modules/classes/order.js
class Order {
constructor(id) {
this.id = id;
console.log('created order #' + this.id);
}
}
export {Order};
/nuxt.config.js
export default {
// ...
buildModules: [
// ...
'~/modules/classes'
],
// ...
}
/pages/the-page.vue
<script>
export default {
name: 'ThePage',
data () {
return {
}
},
methods: {
createOrder () {
const order = new Order(123)
}
}
}
</script>
The error
My defined class are still not imported in my pages:
/app/pages/the-page.vue
18:13 error 'order' is assigned a value but never used no-unused-vars
18:25 error 'Order' is not defined no-undef
Considerations
Probably I'm missing something about modules usage and/or implementation, but every tutorial I found starts with too complex scenarios, and since I'm at the beginning with Nuxtjs I need something easier to implement.
Ok, I found out that I was mistaken how NuxtJs modules are intended to work and was traying to do somenthing they are not intended for.
Nuxt modules cannot import js classes in every component of the application as I wanted to do, they just "add a property" to the main application instance that is made accessible through this.$<something>, like e.g. you can already do in simple Vue with the Vue Router or the Vuex store plugins that give access to the this.$router and this.$store properties.
NuxtJs modules just wrap simple plugins and expose configuration options to made.

How to use functions exported using scalajs in reactjs components?

I have tried exporting some functions to the main.js file in scalajs using #JSExportTopLevel annotation, as explained in the Export Scala.js APIs to JavaScript scalajs documentation and building the main.js as explained here.
This results in main.js from which I am able to make use the functions exported in the scalajs code.
Now I want to use these exported functions in my reactjs components. For this I tried following steps:
Copy the main.js file in the public folder
Include the javascript file in the index.html, like so:
<script type="text/javascript" src="./main.js"></script>
Now, if I load the app in the browser and try to use these functions in the browser console, it works fine:
console.log(foo());
But I am not the utilise these functions in reactjs components:
import React from 'react';
const RuleEditor = () => {
console.log(foo());
return (
<>
</>
);
};
export default RuleEditor;
I always get the following compilation error:
foo is not defined no-undef
I do understand that reactjs is not able to recognise the function as I haven't really specified where to get that function from but I am not really sure how to achieve it. I have gone to couple of other stackoverflow posts where some suggestions where to look for it in window object but I didn't find those functions there.
Please suggest a proper way to make use of functions exported from scalajs in reactjs components. TIA.
Exporting objects/classes/functions as top level exports put them in Javascript global scope.
class Foo(val x: Int) {
#JSExport
def square(): Int = x*x // note the (), omitting them has a different behavior
#JSExport("foobar")
def add(y: Int): Int = x+y
}
You can utilise these functions in the scripts embedded in html or in scalajs as shown here.
But if you need to use these functions in a nodejs app, you need to export these functions from a module. We need to add the following in the build.sbt. Read more here.
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) }
Now, we can make use of the exported functions in a nodejs app by importing them like so:
import { square, add } from './main'
If you wish to export these functions from a module named other than main, provide module id for each exported function like so:
class Foo(val x: Int) {
#JSExport("square", "my-math")
def square(): Int = x*x // note the (), omitting them has a different behavior
#JSExport("foobar", "my-math")
def add(y: Int): Int = x+y
}
and use it like so:
import { square, add } from './my-math'

How to use Vue-plugin-load-script

I am trying to load a custom JS file into my vue and I recently came across vue-plugin-load-script and installed it. I configured it as below:
In my main.js I have
Vue.loadScript("file.js").then(() => {
console.log("SUCESS")
}).catch(() => {
console.log("FAILED")
})
however, the npm page does not show how to use your functions in your views. For instances, lets say the file.js had a function called calculateTime(), and I have a view called Home.vue. How would I call the calculateTime() function from my
<script>
export default {
methods : {
** Trying to put function here **
}
}
</script>
If you have you JS File local, you can import it, like:
import * as localA from "./../../theFile.js"; /*put your path to file.js*/
And after that you can use all methods from theFile.js by writting in a method from your vue Component
methodVue: function (...) {
localA.theMethod(param); /*the Method is declared in theFile.js*/
return;
}
And in your theFile.js your method that you want to use need to be written like that
export function theMethod(param) {
...
}
Do you have a specific reason to use this library? Looking at the function all it does is add a script tag to the DOM if it is not already there and resolve the promise when it loads GitHub link. You could just as well use import * from 'file.js' at the top of the vue file. Then use the functions from that file as usual. The bundler should be able to figure out if the file is imported in multiple places and add it only once.

Where to store common component methods in #NUXT.JS

Actually i want to know where to store common components methods in #NUXT.JS.
things which i have tried.
--> Storing common code in middleware (its use-less) because according to my knowledge middleware is only capable of handling request and response to server.
methods: {
// states methods.
SwitchManager: function (__dataContainer, __key, __value) {
// stand alone debugger for this module.
let debug = __debug('computed:_3levelSwitch')
// debug showing function loaded.
debug('(h1:sizeCheck) creating switch..')
// switch.
switch (__key) {
// fake allow set value to true of given key
default:
this[__dataContainer][__key][__value] = true
break
}
return this[__dataContainer][__key][__value]
},
SizeCheck: function (__size) {
// stand alone debugger for this module.
let debug = __debug('tags:p')
// debug showing function loaded.
debug('(p:sizeCheck) checking..')
// init switch.
this.SwitchManager('pill', 'size', __size)
},
StateCheck: function (__state) {
// stand alone debugger for this module.
let debug = __debug('tags:h1')
// debug showing function loaded.
debug('(h1:sizeCheck) checking..')
// init switch.
this.SwitchManager('pill', 'state', __state)
}
},
created () {
// h1 tag size check
this.SizeCheck(this.size)
this.StateCheck(this.state)
}
I go for mixins like with plain vue.js. Only difference - for global mixins - I include them as a plugin, but first:
Non global mixins
I would create an extra folder for my mixins. For example in a /mixins/testMixin.js
export default {
methods: {
aCommonMethod () {}
}
}
Then import in a layout, page or component and add it via the mixins object:
<script>
import commonMixin from '~/mixins/testMixin.js'
export default {
mixins: [commonMixin]
}
</script>
Global mixins
For example in a new file plugins/mixinCommonMethods.js:
import Vue from 'vue'
Vue.mixin({
methods: {
aCommonMethod () {}
}
})
Include that file then in nuxt.config.js
plugins: ['~/plugins/mixinCommonMethods']
After that you would have the method everywhere available and call it there with this.commonMethod(). But here an advice from the vue.js docs:
Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components. In most cases, you should only use it for custom option handling like demonstrated in the example above. It’s also a good idea to ship them as Plugins to avoid duplicate application.
Inject in $root & context
Another possibility would be to Inject in $root & context

ES6 modules: why a previously exported module is not known by "child" modules?

I am trying to put together a module based architecture for my Meteor/Node application.
I have a client/main.js importing a imports/module1/index.js.
The imports/module1/index.js imports a imports/module1/api/api.js after it imports a component imports/module1/component/component1.js.
To sum it up, the simplified tree would look like this
.client/main.js
|_imports/module1/index.js
|_imports/module1/api/api.js
|_imports/module1/component/component1.js
The api.js file looks like that:
export default {
myFunction1 (arg1, arg2) {
// function stuff
},
myFunction2 (arg1, arg2) {
// function stuff
},
}
I expected to be able to call myFunction1(ar1,arg2) inside the imports/module1/component/component1.js but it doesn't work. What am I missing?
Currently you don't import api.js in your component1.js file so component1 has no access to any functions defined in the api.
Scope of a file doesn't "leak" so each file is completely separate in this matter. import in the main.js file doesn't automatically make all the imported modules available to its child modules – this wouldn't make sense. You have to import something in order to be able to use it.

Categories