How to import vuejs component dependencies in a MPA? - javascript

In a single page app, I can do this to include a component inside a component.
$ npm install sagalbot/vue-select
<template>
<div id="myApp">
<v-select :value.sync="selected" :options="options"></v-select>
</div>
</template>
<script>
import vSelect from "vue-select"
export default {
components: {vSelect},
data() {
return {
selected: null,
options: ['foo','bar','baz']
}
}
}
</script>
How can I do this in a MPA, where I have bunch of js files or sometimes inline javascript in different pages?
I am not using any build system.

I would highly recommend using vue-cli, but if for some reason that is not possible, then I believe,though I have never tried it, you would basically need to add all your components and code into a single long js file, or include them in the right order in your html documents.
Certain component libraries can work this way, like vuetify. You simply include the whole vuetify.js file after vue.js and then you can use all the components available.
I think it would be quite a lot of work to do anything of much size, but if it is something really small you could add components in the following manner, one after another.
var componentTemplate =
`
// Template code..
`;
Vue.component('my-cool-component', {
template: componentTemplate,
data: function() {
return {
//
}
}
});

Related

How to convert component string as real component in vue

Hi i have a requirement for plugin store where i need to load component from core into plugins and inside plugin i need to convert that string into real component so that i can use it.
Note: better approach is most welcome in the view of plugin store inside core
my pseudo logic
get component from specified path through http
convert loaded string into real vue component and store it in a variable
render it in dom
let componentAsString =
`<template>
<div>
<h class="red">{{title}}</h>
<!--<A></A> -->
</div>
</template>
<script>
//import A from './components/A'
export default {
name: 'App',
data(){
return {
title:'Hello World'
}
},
/*components: {
A
}*/
}
</script>
<style lang="scss" scoped>
.red{color:red;}
</style>`;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
</div>
You have chosen very difficult approach to solve the requirement. Main problem is the content of the string - it is essentially a Vue SFC (.vue file). In order to turn this SFC into a Vue component usable in the browser a lot must be done. You must use Webpack (or Rollup or any other bundler), use vue-loader inside to parse the SFC and use different Webpack loaders to process each section of SFC (Babel to transpile the <scipt> block, sass-loader and sass compiler to turn <style lang="scss"> into CSS)
There are tools for doing most of this (with limitations) in the browser like for example vue3-sfc-loader but the cost is huge - vue3-sfc-loader weights around 1.4MB of minified javascript (add Vue itself or potential CSS preprocessor on top of that) and I bet performance of such solution will not be great either
Much easier approach is to use this standard tooling at build time
Just create your components as you normally do - in .vue files
Use your components as Async Components and build a "dictionary" of available components. Those components will be build at build time into separate js files and loaded into a browser on demand (when used)
// ComponentStore.js
export default {
component1: () => import('./components/component1'),
component2: () => import('./components/component2'),
}
Note: process of creating this dictionary can be automated too (inspiration)
Use the component as dynamic component
// DynamicComponent.vue
<template>
<component :is="comp" />
</template>
<script>
import ComponentStore from "ComponentStore.js"
export default {
props: ['componentName'],
computed: {
comp() {
return ComponentStore[this.componentName]
}
}
}
</script>

component structure in Vue

First: I'm using Vue since last night, so the answer is probably obvious.
I find components with that layout:
<template>
<Slider v-model="value"/>
</template>
<script>
import Slider from '#vueform/slider'
export default {
components: { Slider },
}
</script>
<style src="#vueform/slider/themes/default.css" />
but at the same time, I also find components that are structured like a JS object:
app.component('button-counter', {
data() {
return {
count: 0
}
},
template: `
<button #click="count++">
You clicked me {{ count }} times.
</button>`
})
Is there a practical difference? is one preferred? is one more Vue2 vs. Vue3?
The following syntax called SFC single file component :
<template>
...
</template>
<script>
...
</script>
<style src="#vueform/slider/themes/default.css" />
which requires a bundler like webpack or vue cli to be transpiled, the second syntax (your example is based on vue 3) is used to define global component which could work if you're using Vue via CDN,
the first syntax is preferred when you setup a medium/large projects.

VueJs 3 - Use bundled sfc combined with Client Side Rendering

Greetings
Hello fellow Vuers!
So I've got the following situation:
I use ASP.Net Core 3.1 as my server and I would like to use the Vue SFC setup including Typescript support and bind the resulting components into my .cshtml.
Example Usage
Example.vue
<template>
<label :for="name">{{ content }}</label>
<input :id="name" :placeholder="content"/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
someCode
}),
</script>
<style scoped>
/*some styling*/
</style>
Index.cshtml.cs
public class IndexModel: PageModel{
public string Name { get; set; }
public string Content { get; set; }
}
Index.cshtml
#page
#model Namespace.To.IndexModel
<example :name="#Model.Name" :content="#Model.Content" />
The Question
Is there a way to bundle the Single File Components and then use the Components as needed inside of a .(cs)html?
Preferably I'd like to have each component inside of it's own .js file to load them on demand, but it's not a must have.
Thanks in advance
It is possible. But to clarify, it seems like you want to use the components individually. That means that what you're calling a SFC/component, will need to be treated as its own Vue app.
Assuming that's the case, instead of making the components bundled separately you'll need to create a vue app for each one, and individually export them.
You will need to decide how/when to mount them. I've relied on a more manual way of mounting, which requires a line of js to link the DOM element with the widget and pass the attributes. Alternatively you can rely on the DOM tag only. Admittedly, the js way is a bit more verbose, but less prone to edge cases.
Here is the example for the js way
components/example/index.js:
import Example from './Example.vue';
export const mountExample = (el, props) =>
Vue.createApp(el, props);
Then will wrap the component in a function that allows you to pass the DOM element to use and the props.
You would need
<script src="vue.js"/><!-- if it's not bundled in there -->
<script src="example.js"/>
<div id="example" />
<script>
mountExample('#example', {name:"#Model.Name", content="#Model.Content});
</script>
The other way (without the js instantiation) would be to wrap it in a function (IIFE) that looks for <example> tags, parses the content and then mounts the app with the provided parameters. It's quite a bit more work than the other example, but shouldn't be terribly complex.
So for the Example example, I'd organize it something like this: example
/components/example/
|-- Example.vue
|-- index.js
and then use webpack chaining via vue.config.js to do multiple of these
module.exports = {
// tweak internal webpack configuration.
// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
chainWebpack: config => {
// remove the standard entry point
config.entryPoints.delete('app')
// then add your own
config.entry('example')
.add('./src/components/example/index.js')
.end()
.entry('menu')
.add('./src/components/menu/index.js')
.end()
}
}
A caveat; I've used rollup to generate these and I haven't tested this, but webpack should work too
resources for the webpack config:
https://cli.vuejs.org/guide/webpack.html#simple-configuration
https://github.com/neutrinojs/webpack-chain

Using Vue Components in Angular

I have a project that is built in Vue and I want to reuse the components from the Vue application in an Angular application so I don't have to go and rebuild every single component from scratch.
I saw this tutorial on medium: How to use Vue 2.0 components in an angular application, but that tutorial is for AngularJS.
I'm wondering if anyone has done this before, if it's worth it and if anyone knows of any tutorials or reference material.
Wrap your Vue components as native Web Components.
Since Angular supports using custom Web Components, you'll be able to use the Vue components (wrapped as Web Components).
To Angular it doesn't make a difference if the custom Web Components were generated by Vue or not (for all Angular knows, they could be native HTML elements).
Demo
Runnable DEMO here.
The demo is an Angular 5 app. The Vue custom component is defined in index.html. Notice how in app/app.component.html it is used directly in the template, as if it were a native element.
Step by step below.
In Vue
Use vue-custom-element to wrap your Vue components as Web Components:
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-custom-element#3.0.0/dist/vue-custom-element.js"></script>
<script>
const MyVueWebComp = {
props: ['msg'],
template:`
<div style="border: 3px dashed green; padding: 5px">
I am my-vue-web-comp.<br>
Value of "msg" prop: {{ msg }}<br>
<input v-model="text"><button #click="addText">Click me</button>
<div v-for="t in texts">
Text: {{ t }}
</div>
</div>
`,
data() {
return {
text: '',
texts: []
};
},
methods: {
addText() {
this.texts.push(this.text);
this.text = '';
}
}
};
Vue.customElement('my-vue-web-comp', MyVueWebComp);
</script>
That will create a <my-vue-web-comp> web component that can be used directly in the DOM, without the need to have a working Vue instance.
The above is just a demo runnable directly in the browser. If you have .vue files and a vue-cli app, you'll need to do npm install vue-custom-element --save and then create a .js file like:
import Vue from 'vue';
import vueCustomElement from 'vue-custom-element';
import MyElement from './MyElement.vue';
Vue.use(vueCustomElement);
Vue.customElement('my-element', MyElement);
And then this, when bundled, will generate a .js file that can be imported directly as a single <script> tag, instead of the whole code and script tags above.
For more details, check vue-custom-element's docs.
In Angular
Now, in the Angular app, after importing the Web Components (being them Vue-generated or not), configure them to be used by Angular by adding schemas: [CUSTOM_ELEMENTS_SCHEMA] in your #NgModule:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
//...
#NgModule({
// ...
schemas: [
CUSTOM_ELEMENTS_SCHEMA // added this
]
})
export class AppModule {
Now use the Web Components (generated from Vue or not) directly in Angular templates. E.g. the component defined in the code above could be used like:
<my-vue-web-comp [msg]="name"></my-vue-web-comp>
In fact, the runnable demo shows an example of that usage.
Limitations
You may need polyfills for older browser support. Please check vue-custom-element's docs for more details.

Importing javascript file for use within vue component

I am working on a project that requires using a js plugin. Now that we're using vue and we have a component to handle the plugin based logic, I need to import the js plugin file within the vue component in order to initialize the plugin.
Previously, this was handled within the markup as follows:
<script src="//api.myplugincom/widget/mykey.js
"></script>
This is what I tried, but I am getting a compile time error:
MyComponent.vue
import Vue from 'vue';
import * from '//api.myplugincom/widget/mykey.js';
export default {
data: {
My question is, what is the proper way to import this javascript file so I can use it within my vue component?
...
Include an external JavaScript file
Try including your (external) JavaScript into the mounted hook of your Vue component.
<script>
export default {
mounted() {
const plugin = document.createElement("script");
plugin.setAttribute(
"src",
"//api.myplugincom/widget/mykey.js"
);
plugin.async = true;
document.head.appendChild(plugin);
}
};
</script>
Reference: How to include a tag on a Vue component
Import a local JavaScript file
In the case that you would like to import a local JavaScript in your Vue component, you can import it this way:
MyComponent.vue
<script>
import * as mykey from '../assets/js/mykey.js'
export default {
data() {
return {
message: `Hello ${mykey.MY_CONST}!` // Hello Vue.js!
}
}
}
</script>
Suppose your project structure looks like:
src
- assets
- js
- mykey.js
- components
MyComponent.vue
And you can export variables or functions in mykey.js:
export let myVariable = {};
export const MY_CONST = 'Vue.js';
export function myFoo(a, b) {
return a + b;
}
Note: checked with Vue.js version 2.6.10
try to download this script
import * from '{path}/mykey.js'.
or import script
<script src="//api.myplugincom/widget/mykey.js"></script>
in <head>, use global variable in your component.
For scripts you bring in the browser way (i.e., with tags), they generally make some variable available globally.
For these, you don't have to import anything. They'll just be available.
If you are using something like Webstorm (or any of the related JetBrains IDEs), you can add /* global globalValueHere */ to let it know that "hey, this isn't defined in my file, but it exists." It isn't required, but it'll make the "undefined" squiggly lines go away.
For example:
/* global Vue */
is what I use when I am pulling Vue down from a CDN (instead of using it directly).
Beyond that, you just use it as you normally would.
I wanted to embed a script on my component and tried everything mentioned above, but the script contains document.write. Then I found a short article on Medium about using postscribe which was an easy fix and resolved the matter.
npm i postscribe --save
Then I was able to go from there. I disabled the useless escape from eslint and used #gist as the template's single root element id:
import postscribe from 'postscribe';
export default {
name: "MyTemplate",
mounted: function() {
postscribe(
"#gist",
/* eslint-disable-next-line */
`<script src='...'><\/script>`
);
},
The article is here for reference:
https://medium.com/#gaute.meek/how-to-add-a-script-tag-in-a-vue-component-34f57b2fe9bd
For anyone including an external JS file and having trouble accessing the jQuery prototype method(s) inside of the loaded script.
Sample projects I saw in vanilla JS, React and Angular were simply using:
$("#someId").somePlugin(options)
or
window.$("#someId").somePlugin(options)
But when I try either of those in my VueJS component I receive:
Error: _webpack_provided_window_dot$(...).somePluginis not a function
I examined the window object after the resources had loaded I was able to find the jQuery prototype method in the window.self read-only property that returns the window itself:
window.self.$("#someId").somePlugin(options)
Many examples show how to load the external JS file in VueJS but not actually using the jQuery prototype methods within the component.

Categories

Resources