vue - moving child component code to another file - vue.js

I have a subcomponent within a file, and I want to extract it out of the file and into another file.
I'm just using vue (not cli) and php, and I don't have access to ES6, so I can't use those import statements.
const form = {
...
components:{
subForm:{
/* lots of code */
}
}
}

If you are using require.js you can just import it from the new file
const subForm = require('path/to/new/file);
const form = {
components { subForm };
}
If not, you can create the component in a new file and registered in the global Vue instance.
Vue.component('subForm', {
/* lots of code */
});
This will work assuming that you import the file into your HTML using a bundler or something like gulp. And that Vue is globally included in the DOM either through a script tag linking to a CDN or through whatever you are using to bundle the application.

Related

Nuxt avoid import of client-side script for server-side rendering

In my nuxt.js application, I have a script that imports an NPM package which is only compatible with browser contexts (it references document, location, window, etc.)
Is there a way to exclude this from SSR?
import thing from "#vendor/thing"; // causes `document not defined` error
export default showThing(){
if (process.client) {
thing();
}
}
I can use the method with process.client but this file is still imported in my components.
You could import it dynamically rather than in every context.
As explained in my answer here: https://stackoverflow.com/a/67825061/8816585
In your example, that would be something like this
export default showThing(){
if (process.client) {
const thing = await import('#vendor/thing')
thing()
}
}

Use global Vue 3 plugins in Storybook stories?

How can I use a Vue 3 plugin in Storybook stories?
For example, I use FormKit to create form elements in my components.
FormKit is rigged globally in my main.ts like so:
import { plugin, defaultConfig } from '#formkit/vue'
const app = createApp(App)
app.use(plugin, defaultConfig)
but this file isn't used by Storybook... so how can I do the same for Storybook?
I was able to find documentation here:
https://github.com/storybookjs/storybook/tree/47f753f5e8d084b4d544cf1ec76077a9382aa6b2/app/vue3
I learned that you are able to access the app created by Storybook in .storybook/preview.js by importing it from #storybook/vue3.
Example is copied from above link:
// .storybook/preview.js
import { app } from '#storybook/vue3';
app.use(MyPlugin);
app.component('my-component', MyComponent);
app.mixin({
/* My mixin */
});

Import Vue components from folder programmatically not hard coded (I'm actually using Nuxt but I'll call it Vue)

I have a number of SVG cards as components in Vue; I probably have 50 or more. I could import them one by one just after the script tag:
<script>
import MyVueComponent1 from "~/components/MyVueComponent1.vue";
import MyVueComponent2 from "~/components/MyVueComponent2.vue";
import MyVueComponent3 from "~/components/MyVueComponent3.vue";
...
import MyVueComponent50 from "~/components/MyVueComponent50.vue";
But I've been reading that I can do this programmatically. I just haven't found any one example that makes it crystal clear to me. I able to register the components dynamically but I'm not certain how to import an entire folder of components.
I was able to register the components dynamically using this code in the created hook:
created() {
const requireComponent = require.context(
// Look for files in the current directory
"../components",
// Do not look in subdirectories
false,
// Only include "S" prefixed .vue files
/S[\w-]+\.vue$/
);
// For each matching file name...
requireComponent.keys().forEach((fileName) => {
// Get the component config
const componentConfig = requireComponent(fileName);
// Get the PascalCase version of the component name
fileName = fileName.replace("./", "");
fileName = fileName.replace(".vue", "");
const componentName = fileName;
this.generatedComponentList.push(componentName);
// Globally register the component
Vue.component(componentName, componentConfig.default || componentConfig);
});
},
And I'm using the generatedComponentList of component names to display the cards:
<div
v-for="componentName in generatedComponentList"
:key="componentName"
>
<component :is="componentName" :id="componentName"></component>
</div>
But I'd love to get rid of all the import lines under the script tag and have cleaner and more dynamic code. That way if I add a new component card to the folder, it will simply be "picked up" and displayed without having to add the "import" line, or register the component etc. Hopefully I've clearly articulated what I'm looking to achieve.
Nuxt auto-imports the components you use from the ~/components directory, so you don't need to import or register them explicitly.
This feature is enabled in nuxt.config.js with the components config:
// nuxt.config.js
export default {
components: true
}
Thanks tony19 suggesting I look at the nuxt.config.js file, your answer definitely put me on the right track; also thanks to whoever suggested 1 might be the right answer.
Here's the solution that worked for me:
Based on tony19's suggestion I looked at my nuxt.config.js file; specifically the component section. I already had this line in my code to automatically import any components in my components folder:
components: true,
But the components I wanted to import were nested within another folder within the components folder.
After reading this 2 from the nuxt.org docs, I replaced my previous code with this:
//components: true,
components: [
// Equivalent to { path: '~/components' }
'~/components',
{ path: '~/components/myTargetComponents', extensions: ['vue'] }
],
Then, I was able to remove all of my import lines:
<script>
import MyVueComponent1 from "~/components/MyVueComponent1.vue";
import MyVueComponent2 from "~/components/MyVueComponent2.vue";
import MyVueComponent3 from "~/components/MyVueComponent3.vue";
...
import MyVueComponent50 from "~/components/MyVueComponent50.vue";
In my index.vue file I don't have anything listed in the components section anymore...just this as a reminder to myself:
,
components: {
//see nuxt.config.js file ...component section
},
Just to be clear, in my index.vue file, I don't import any components using this format, "import MyVueComponent1 from "~/components/MyVueComponent1.vue"; AND I don't have anything listed in the components section. Also just to clarify, the components I'm wanting to import ARE in a sub folder of the components folder (~/components/myTargetComponents). I realize now that I didn't clearly articulate that in my original post.
As a related piece of this...
As you can see from my original post, I'm using a block of code in the created hook to populate a list of the component names:
this.generatedComponentList.push(componentName);
And then using this list to iterate through the component cards:
<div
v-for="componentName in generatedComponentList"
:key="componentName"
>
<component :is="componentName" :id="componentName"></component>
</div>
But I'm wondering if there's a list of these components already generated by nuxt.config.js file. Any suggestions? And again, thanks everyone for the help, I greatly appreciate it.

register dynamic components for vue app in seperate module file

I would like to make a js module file that imports vue component and register there.
and then inherit this component and use it for the app's main component.
I've found similar cases but the thing is, I don't use vue cli.
custom.js
import customMain from '/custom/components/main/main.js';
window.Vue.defineComponent('custom-main', customMain);
and in the app.js
import Main from '/global/components/main/main.js';
var App = createApp({
...
components: {
'global-main': Main,
},
template: `<component :is='mainComponent'></component>`,
computed: {
mainComponent() {
if(this.settings.customComponent){
return 'custom-main';
}else{
return 'global-main';
}
}
is this doable? what should I do to make this work?
is there other alternative way to load components dynamically?
The best approach for this case is defining a plugin named registerComponents in the plugins folder : plugins/registerComponents.js
import customMain from '/custom/components/main/main.js';
export default {
install: (app, options) => {
app.component('custom-main', customMain);
}
}
in App.js use the plugin:
import registerComponents from './plugins/registerComponents'
var App = createApp({....})
App.use(registerComponents)

document is not defined in a Vue component imported to Nuxt when extract_css: false

I have built a Vue component using #vue/cli and tried importing it to Nuxt applications as a dependency. The component is built using --target lib and it compiles to .umd.js source.
When I use vue.config.js with the following setup:
module.exports = {
css: { extract: false }
}
the component styles are included in the bundle and results in throwing the error document is not defined in the following line of bundle file
...
var styleElement = document.querySelector('style[' + ssrIdKe`
...
The component works completely fine if I set the extract value to true, but obviously that requires a manual import of the bundled CSS file ( which I want to avoid )
Is there any solution to get a custom component included inside Nuxt project with styles bundled?
This is due to the server-side rendering. If you need to specify that you want to import a resource only on the client-side, you need to use the process.client variable.
Try this:
if (process.client) {
var styleElement = document.querySelector('style[' + ssrIdKe`
}