Can i import single file component using Vue and Vue Router CDN? - vue.js

I'm currently using Vue and Vue Router CDN. I want to import a single file component (user.html) to my index.html with Vue router. But when I click on "Go to user" the data didn't display. I read a few guides about Vue router but they used NPM or CIL instead of Vue CDN.
Index.html
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- use router-link component for navigation. -->
<!-- specify the link by passing the `to` prop. -->
<!-- `<router-link>` will be rendered as an `<a>` tag by default -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
<router-link to='/User.html'>Go to User</router-link>
</p>
<!-- route outlet -->
<!-- component matched by the route will render here -->
<router-view></router-view>
</div>
<script>
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const User = { template: '#test'}
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
{
path:'/User.html', component: User
}
]
const router = new VueRouter({
routes
})
const app = new Vue({
router
}).$mount('#app')
</script>
User.html
<template id = "test">
fsjdfjdfldskjflkd
</template>

I think there's been a misunderstanding. As far as I can tell you're trying to load User.html in the way you would load a .vue file, but that doesn't work unless you're using Webpack to build your project since the .vue filetype is something that the vue-loader project is responsible for parsing.
Vue Router CDN means you're not building with Webpack, so loading a component like you're doing is impossible. You can configure Vue Router to serve a User.html file, but that file can't be a template component since in CDN mode Vue Router has no idea what files are on your server, nor can it simply retreive them.
So you need to do one of the following three options:
Option 1: Start using Webpack for your project
This is what I recommend you doing. You'll find that your project will perform better and will be easier to develop using it.
Option 2: Use the proper template syntax for CDN
This is for example:
var mytemplate = `<div>
<h1>This is my template</h1>
</div>`
Vue.component('mycomp1', {
template: mytemplate
});
Vue.component('mycomp2', {
template: `
<div>
Hello, {{ name }}!
</div>
`,
props: ['name'],
});
You can't load other files as templates when you're not building using Webpack. Webpack puts them into your single page application for you, Vue Router has no idea what's inside User.html nor can Vue use it as a template. Vue Router can be told to redirect to a fully functional User.html website page, but not to just use it as a template.
Option 3: Use Ajax requests to fetch the template file
This is something I STRONGLY URGE YOU NOT TO DO, but for the sake of completeness, you can use the CDN version if you fetch the contents of User.html file using an Ajax request and create a component from that.
I really, really recommend that you stop using the CDN version and instead go for a Webpack based solution, give in to the dark side! Or make it even simpler and use Nuxt.js instead since it's easier for beginners to use.

Related

Vue Js not displaying

This is my very beginning with Vue with Symfony. Problem is nothing is displayed in my page, I was expecting Hello to be print. I did all my configurations. I have created folder vue
Inside vue I have following 2 files.
App.vue
<template>
<div id="app">
<h1>Hello</h1>
</div>
</template>
index.js
import Vue from "vue";
import App from "./App";
new Vue({
components: { App },
template: "<App/>"
}).$mount("#app");
I have in my webpack.config.js
.addEntry('app', './assets/vue/index.js')
I did anything wrong here ?
You are mounting the Vue instance to something existing in the DOM with id app. But the component inside App.vue also contains a div with id app. Try to mount to anything else on the page that Symfony creates (you can't mount on body or html). I'm sure that page does not contain anything with id app.

How to use VUE router with native HTML elements as components?

I am in this situation:
old project, npm/vue compiler not available
using vue in vanilla JS flavour
using router, that needs components
don't want to use smelly injected strings, that are really bad for code readability
How can I use pieces of html as components for vanilla JS vue?
I found a totally undocumented solution for making vanilla JS components with native HTML:
1 Pure HTML (no smelly injected strings):
<div id="components" style="display:none"><!--hide component code-->
<div id="component-category-index"><!--component 1 source code-->
CATEGORY INDEX COMPONENT
</div>
<div id="component-article-show"><!--component 2 source code-->
ARTICLE SHOW COMPONENT
</div>
</div>
2 vanilla JS Vue initialization:
const vue=new Vue({
el: '#vue-app',
....your vue blabla.....
router:new VueRouter({
routes :[
{ path: '/article', component: { template: document.getElementById('component-article-show').outerHTML } },
{ path: '/categories', component: { template: document.getElementById('component-category-index').outerHTML } }
]
})
})
pros:
use vanilla JS vue with full components functionalities
keep vue "style-component-logic" separated but on the same file, without
hard breaking that clean and simple pattern
cons:
all HTML of the page must be on the same file, so this solution is OK for smaller SPA or single pages with VUE.

How to embed LinkedIn Profile in VueJs Component

I am using VueJS to build a website and I got to the point where I want to include my embedded profile into a page/Component in Vue. It seems to work only if I refresh the page. When I navigate from other pages to this page it is not displayed.
In my public/index.html I included LinkedIn Library Script
<script type="text/javascript" src="https://platform.linkedin.com/badges/js/profile.js" async defer></script>
In my component:
<template>
<!-- some other code -->
<div class="col-md-4 col-sm-12 text-sm-center">
<div class="LI-profile-badge" data-version="v1" data-size="medium" data-locale="en_US" data-type="vertical" data-theme="dark" data-vanity="nicolae-orlov">
</div>
</div>
</template>
I saw some info that I need to reload the component to force it to re-render but I am not sure how. Any help is much appreciated.
If you want to add a script tag only on a specific component, you can use PostScribe to render a script after load.
After installing (npm i postscribe --save) and importing (import postscribe from 'postscribe'), you can add your script tag in the mounted lifecycle hook:
mounted() {
postscribe('#linkedin', '<script src="https://platform.linkedin.com/badges/js/profile.js"><\/script>')
}
where #linkedin refers to the ID of your profile badge element (add an ID if necessary)
Your linkedin badge should now be embedded in your Vue component.
You can add the javascript by injecting script into head and then adding the html into the respective component. This is how you can inject javascript directly into head from the component.
<script>
export default {
head(){
return{
script : [
{
src:
'https://platform.linkedin.com/badges/js/profile.js',
type:
'text/javascript'
}
],
}
}
}
</script>

What is the purpose of 'main.js' and 'App.vue' in a Vue.js application?

I don't understand the exact purpose of each file.
Suppose I want to add authentication code. Where should I place it, in main.js or App.vue?
I believe you might be missing on some of the basics behind the structure of Vue.js and where and/or how to put in functionality like authentication. It might be worth going through their introduction again to solidify your knowledge.
To answer more directly, when you run a Vue.js application you need to have a basic HTML page (like index.html) as an entry point and the initialisation for your Vue.js application loaded in a <script> in that page.
When you write a Vue.js application you can choose to do it in pure JavaScript, in TypeScript or in the .vue component format which combines the HTML, CSS and JavaScript you need to define components.
The vue format is not run directly. It has to be transpiled into plain JavaScript by the Vue-CLI/builder and packed using a packager like Webpack first and then loaded by your entry point. Luckily, the Vue.js CLI handles nearly all of this process so you can get on with building.
File App.vue
This is typically the root of your application defined in Vue.js Component file format. It's usually something that defines the template for your page:
<template>
<div id="app">
<SideBar />
<router-view v-if="loaded" />
</div>
</template>
<script>
import SideBar from "./pages/SideBar";
export default {
components: { SideBar },
computed: {
loaded() {
return this.$store.state.loadState == "loaded";
}
}
};
</script>
File main.js
This is usually the JavaScript file that will initialise this root component into a element on your page. It is also responsible for setting up plugins and third-party components you may want to use in your app:
import Vue from "vue";
import { store } from "./store/store";
import router from "./router";
import App from "./App.vue";
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
File index.html
The index page provides your entry point in HTML providing an element for Vue.js to load into and imports file main.js to initialise your application.
<!-- The HTML element that hosts the App.vue component -->
<div id="app"></div>
<!-- Built files will be auto injected -->
<script type="text/javascript" src="main.js"></script>
On another note, a decent place to put your authentication logic is in the router where you can add navigation guards to restrict access to pages based on the current authentication state and send your users to a login page:
// GOOD
router.beforeEach((to, from, next) => {
if (!isAuthenticated) next('/login')
else next()
})
I don't think you specifically need an index.html in your project. Provided your main.js has an import that references you main Vue page, e.g.:
import App from "./App.vue";
and then renders it.
new Vue({
...
render: (h) => h(App),
...
The .vue file is a special Vue.js CLI project feature allowing you to write Vue.js apps or Vue.js components in more convenient way. You write your app/component in the .vue file and Vue.js CLI transforms it into code that works in a browser.
The main.js in Vue.js CLI project is starting the instance of the app. The index.html file in Vue.js CLI project is handled automatically (it's located in the 'public' folder).
The right place to start with Vue.js CLI is: Instant Prototyping

How to Access Vue-Loader Components in an HTML File

I would like to use the modular style and file format of Vue Loader (i.e., where I have a template section, script section and style section in each .vue file).
What I can't figure out how to do (or if it is even possible to do) is use my custom templates in an html file.
For instance, in the App.vue file I can use the following code:
<template>
<div id="app">
<message>Hello there</message>
</div>
</template>
This will work to display a custom message component on the home page.
What I would like to do instead is use my custom components in html files. For instance, in the index.html file to use the following code:
<div id="app">
<message>Hello there</message>
</div>
Any idea how I can do this? Thanks.
NOTE: I am new to Vue Loader and semi-new to Vue (so I apologize in advance if the answer to this question is obvious).
There are many ways you can compile a single file component and then use that component in a web page.
Use vue-cli
Vue released a command line interface tool called vue-cli that can initialize projects and build components with zero configuration. One option to build a component that you can use in your page is to use vue build.
vue build MyComponent.vue --prod --lib MyComponent
This will compile a script that exposes MyComponent. If you include that script in your page and then add it globally,
Vue.component(MyComponent)
That component will be available to you in any of your Vues.
Make a plugin
Here is a sample of a very basic framework for making a plugin.
myPluginDefinition.js
window.MyPlugin= {};
MyPlugin.install = function (Vue) {
Vue.component('my-component', require('./my-component.vue'));
}
webpack.config.js
module.exports = {
entry: "./myPluginDefinition.js",
output: {
path: __dirname+'/dist',
filename: "MyPlugin.js"
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader',
}
]
}
};
This will build a file called MyPlugin.js that will contain each of the single file components that you include in the install function. Include the script on your page and then call
Vue.use(MyPlugin)
and you will have all of your components.
Use a custom webpack configuration
There are many ways you could configure webpack to build your single file components. You could build them all into a single file or build them separately. I suggest if you want to use one of these options you ask a separate question.
Actually you can do this easily by:
register your component :
Vue.component('message', {
template: '<div>A custom component!</div>'
});
then comment the render function in your Vue instance like so:
new Vue({
el: '#app',
// render: h => h(App)
})
after that you will be able to render your message Tag like this:
<div id="app">
<message></message>
</div>
Edit :
if you don't want to use this way you can define it in your view instance:
new Vue({
el: '#app',
// render: h => h(App)
components: {
message: {
template: `
<h1>Hello World</h1>
`
}
}
})
Import desired component definition object and pass it to options.components
<template>
<some-component></some-component>
</template>
<style>...</style>
<script>
import SomeComponent from 'path/to/some-component.vue';
export default {
components: {
// ES2015 shorthand for SomeComponent: SomeComponent
SomeComponent
}
}
</script>
That leverages local component registration
Both the default export and SomeComponent are component definition objects.