Header and footer component in Vue.js - vue.js

I am learning Vue.js, I am not using cli for Vue.js installation, I just downloaded Vue.js file and trying to learn it.
My issue is to externalize components like header.vue and footer.vue and add them to main component.
I used Vue.component('MyHeader', require('./components/Header.vue')); to load component but I was getting error like "Uncaught ReferenceError: require is not defined".
To resolve this error I downloaded require.js file from here but I am still unable to load component files.
Folder Structure
index.html
<!DOCTYPE html>
<html>
<head>
<title>this is example of header and footer</title>
</head>
<body>
<div id='root'>
<testcomponent></testcomponent>
<MyHeader></MyHeader>
<div>I am Content</div>
<MyFooter></MyFooter>
</div>
<!-- we need this two files for vue js -->
<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript" src="require.js"></script>
<!-- End of we need this two files for vue js -->
<script type="text/javascript" src="indexController.js"></script>
</body>
</html>
indexController.js
//rout file for vue js
Vue.component("testcomponent",{
template:'<p>I am Test Component</p>'
});
Vue.component('MyHeader', require('./components/Header.vue'));
Vue.component('MyFooter', require('./components/Footer.vue'));
//import MyHeader from './components/Header.vue'
//import MyFooter from './components/Footer.vue'
var app = new Vue({
el: "#root",
components: {
MyHeader,
MyFooter
},
data: {
},
methods:{
}
});
Header.vue
<template>
<h1>I am Header</h1>
</template>
Footer.vue
<template>
<h1>I am Footer</h1>
</template>

Single file component (.vue)
You need vue-loader to convert .vue files to normal js format.
If you will read the documentation at https://v2.vuejs.org/v2/guide/single-file-components.html, you basically need to use webpack or browserify to use .vue files extensions.

As it says in the comments, you need a build tool to use .vue files. But you can get all the goodness of components, except scoped css, by using plain .js files.
Put your templates in .js template strings, then call your components the old way, with <script src="urlOfFile.js">, or call them with requirejs, but they need to be plain .js files, not .vue.

CommonJS using require (not to be confused with require.js which is using AMD):
Instead of Header.vue create Header.js which you then can require just like you do:
module.exports = {
template: `<template>
<h1>I am Header</h1>
</template>`
}
ES6 export / import
If you want to use ES6 import instead of require, this would be the content of Header.js:
export default {
template: `<template>
<h1>I am Header</h1>
</template>`
}
To work with .vue component files and structuring, you need vue-webpack-loader and a build stack involving something like webpack or browserify.
See
https://v2.vuejs.org/v2/guide/single-file-components.html#For-Users-New-to-Module-Build-Systems-in-JavaScript

If you are just starting with Vue and all the JS magic I would look into the vue cli install approach link. It should install webpack and all the things needed for single page components then you can work backward to deconstruct the pieces of that setup.
You can also look at the examples in the vue GitHub repos. link
That example is using vuex along with single file components but it is solid.

Related

Add Vue 3 to CMS generated HTML

i got a site with a cms here, which generates html the common way. Now i try to add Vue 3. CSS and JS is created by webpack.
The CMS generates a source like this:
<html>
<head>
<script src="/dist/app.js"></script>
<link rel="stylesheet" type="text/css" href="/dist/app.css">
</head>
<body>
<div id="app">
<h1>Hello {{name}}</h1>
<MyComponent />
<div>Awesome Copyright</div>
</div>
</body>
</html>
Is it possible to mount vue 3 to #app, but keep the source as structure/content for the page and use vue 3 inside? Like setting {{name}} to a value from vue and MyComponent from a vue file? And all JS is compiled by webpack?
I did not figure out how to solve this. Something like SSR seems not to be a practicable solution and switching to a headless constellation with the cms as api is not either.
After reading and understanding the documentation, i answer myself.
https://v3.vuejs.org/guide/installation.html#with-a-bundler
See section "In-browser template compilation".
Step 1: Alias vue within webpack
resolve: {
alias: {
vue: "vue/dist/vue.esm-bundler.js"
}
}
Step 2: Run Vue ;-)
createApp({
data() {
return {
name: 'John Doe'
}
},
}).mount('#app')
The definition of template is not necessary. It takes the content from #app.
You can do this
createApp({
data() { return {} },
template: document.querySelector('#app').innerHTML
}).mount('#app')

How to make Vue 3 application without CLI / Webpack / Node

I am trying to make Vue 3 application but without CLI and Webpack.
There is no official documentation yet. On CDN are many versions (vue.cjs.js, vue.cjs.prod.js, vue.esm-browser.js, vue.esm-bundler.js, vue.global.js, vue.runtime.global.js...).
Which one to pick? And how to mount application, old way does not work. There are many online examples how works new Composition API but none how to start project without CLI / Webpack.
Link to Vue 3 CDN:
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
In body:
<div id="app">
</div>
<script type="module">
import app from './app.js'
const {createApp} = Vue;
createApp(app).mount('#app');
</script>
In app.js is simple component:
export default {
name: 'Test',
setup() {
const title = "Hello";
return {
title
};
},
template: `
<div>
<h1>{{title}}</h1>
</div>
`,
};
Instead of one component, app.js can be a container for other components.
I made simple Vue 3 QuickStart template so anyone can see how this works.
Template is in SPA-like style and contains 4 sample pages, 4 components, routing and store. It uses only Vue.js from CDN, everything else is hand made ;)
Note: This is not library, it's just demo code so anyone can see how to mount Vue 3 application and use Composition API in simple scenario.
Online demo: http://vue3quickstart.rf.gd/
GitHub: https://github.com/SaleCar/Vue3-QuickStart
Found in docs: https://vuejs.org/guide/quick-start.html#without-build-tools
Without Build Tools
To get started with Vue without a build step, simply copy the following code into an HTML file and open it in your browser:
<script src="https://unpkg.com/vue#3"></script>
<div id="app">{{ message }}</div>
<script>
Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
The above example uses the global build of Vue where all APIs are exposed under the global Vue variable.
While the global build works, we will be primarily using ES modules syntax throughout the rest of the documentation for consistency. In order to use Vue over native ES modules, use the following HTML instead:
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue#3/dist/vue.esm-browser.js"
}
}
</script>
<div id="app">{{ message }}</div>
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
Notice how we can import directly from 'vue' in our code - this is made possible by the <script type="importmap"> block, leveraging a native browser feature called Import Maps. Import maps are currently only available in Chromium-based browsers, so we recommend using Chrome or Edge during the learning process. If your preferred browser does not support import maps yet, you can polyfill it with es-module-shims.
You can add entries for other dependencies to the import map - just make sure they point to the ES modules version of the library you intend to use.
Not for production
The import-maps-based setup is meant for learning only - if you intend to use Vue without build tools in production, make sure to check out the Production Deployment Guide.
In addition, as Evan You recommended, Vite(https://madewithvuejs.com/vite) is a good alternative to #vue/cli and webpack. It's still CLI like but more lightweight I think. Fast and supports SFC.

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

Vue.js Declarative rendering not working after webpacking

Below is my index.html file
<!doctype html>
<html><head>
<body>
<h1>ES</h1>
<div id="app">
{{ message }}
</div>
<script src="dist/main.js" type="text/javascript"></script></head>
</body>
</html>
I am trying to use basic vue.js declarative rendering. My index.js input for webpack with zero configuration is below
import Vue from 'vue';
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
The value of message is not shown in the page . Is this something to do with my webpack configuration. Do I need to use Babel transpiler to get this to work?
See Explanation of Different Builds in the doc.
The default file for these bundlers (pkg.module) is the Runtime only
ES Module build (vue.runtime.esm.js).
Vue build with runtime only doesn't include HTML template compiler, which you need in your case. (Runtime only build is 30% smaller in size)
As the doc mentioned, to import full build of Vue, you may use
import Vue from 'vue/dist/vue.esm.js';
Btw, I highly recommend you to use vue-cli instead of configuring the Vue project yourself.

how to use a .vue file in a html?

I created a hello.vue file, now how to use this in a html file? I already setup a webpack,
<template>
<p>Hello</p>
<p>{{message}}</p>
</template>
<script>
module.exports = {
data: {
message: 'hello'
}
}
</script>
<style>
p {
font-size: 14px
}
</style>
How do you want to use it?
Taking demonstation from official example: vue-hackernews-2.0. This is a component, so you import the component in another vue file like this:
import Comment from '../components/Comment.vue'
and you add in the list of components in that vue instance:
components: { Spinner, Comment },
Than you can use it in HTML like this:
<comment v-for="id in item.kids" :key="id" :id="id"></comment>
You just have to include your bundled .js file in your HTML file and include mounter div - so Vue could know where to execute the app.
Your index file could looks something like this (showing only body section)
...
<body>
<div id="app"></div>
<script src="bundle.js">
</body>
...
Your main Vue file could looks like this:
import Vue from 'vue'
import Hello from 'hello.vue'
const app = new Vue({
render: (h) => h(Hello)
}).$mount('#app')
And in this way you can store all other components into the hello.vue.
This is probably way that you should use when you are building SPA.