Here is a learning repository for learning VueJS.
- A place for learning VueJS
- VueJS
- Hello World With @vue/cli
- Vue Commands
- Vue Dev Tools
- Summary Of Basic Commands And Syntax
- Components
- Directive
- Events
- Data
- Watcher
- Computed
- Methods
- Props
- Types
- Component
- Filter
- BeforeCreate
- $ indicates a global variable
- Components
- Dynamic Attributes
- older notes below ....
- Props
- Refs
- Vuetify
- Vue Tutorial Walkthroughs
- Vue Tutorial 1: Traversy Media : Vue in 60 minutes
- Installing VUE
- Hello World
- Methods
- {{ only work when we expect text to be present, not HTML attributes }}
- v-bind
- href
- Directives : passing in attribute values
- Setting data values
- Components
- Analysing a Vue app
- Routing
- Vue basic code snippets
- Vue Client 3
- Vue Serve
- Building projects
- Saved preferences
- vue ui
- Applying CSS Classes to VUE
- Vue Tutorial 2 : Connecting VUE to Firebase Database in 54 minutes
- Vue Backends
- Vue Tutorial 2 : Connecting VUE to Firebase Database in 54 minutes
- Vue with Firebase
- Rework From Scratch Of Vue Firebase App
- Add Views To Provide Navigation
- Add Bootstrap
- Vue Components And Props
- Components With Props
- Axios Getting API Data
- Vue With Firebase: 2019-09
- Vue With Firebase 2
- To Do Vue App
- Vue.prototye - adding to global scope variables
- Vuex Global Storage
- Vue With PHP : Laravel
- Vue With Authentication
These standalone VueJS files are good for learning individual components of Vue because the file stands alone and there are no complex dependencies to inject into the project. Good for learning.
These are built using the @vue/cli command line interface, and each one is a fully-fledged Vue project
# add variable
Vue.prototype.$appName = 'My App'
# log
new Vue({
beforeCreate: function(){
console.log(this.$appName)
}
})v-on:click="doThis" event
v-bind:href="myUrl" attribute
v-model="dataItem01" 2-way binding
Methods : executed every time DOM is repainted
Computed Properties : values cached and only updated when have to
Watch : asynchronous tasks : execute on return
Shortcuts
@ = v-on:
:href = v-bind:href
:style = v-bind:stylePlan is to have all Standalone Projects in separate folder.
Also to have one main ‘Vue’ app which can be deployed online.
Thirdly we can have a PUBLIC folder in which to place all of the static HTML files and to reference them directly.
To do : Build the vue-cli-3 app and have it running online with netlify; then build on this!
The Vue Handbook By Flavio Copes
Vue creates components with HTML/CSS/Javascript.
Vue works with NativeScript - see https://www.npmjs.com/package/nativescript-vue-template
Vue is small, fast and simple.
The size of Vue is only 24kb.
It’s an indie project not driven by an corporation
Vue is a progressive framework which means that it can happily coexist with other frameworks and can be added in via a simple script tag
React uses JSX
Vue uses a templating system
Vue can use any valid HTML file rather than the more complex JSX which React uses.
Vuex is the state management library which takes after Redux
vue-router handles routing
vuex handles state
Follow Gregg Pollack from vuemastery.com
Follow Evan You who was the creator of Vue.js
Anthony Gore is a teacher of VueJS whose goal is to help you become an expert in VueJS.
Basic Documentation at VueJS.org
Advanced Documentation at vuemastery.com
Vue CLI 3 at https://cli.vuejs.org/guide/
Angular was created by Google and released in 2010
Angular original is called AngularJS
Angular2 was released in 2016
Angular 2+ is called Angular.
Angular 7 is the latest version as of October 2018.
React is developed by Facebook and was released in 2013.
Facebook extensively uses React in Facebook, Instagram and WhatsApp. It’s used by Uber for example.
Vue is created by ex-Google employee Evan You in 2014.
Vue has done incredibly given that it does not have the backing of a large company, but just one individual!!!!
Vue has current stable
Vue has been chosen by Chinese giants AliBaba and Baidu as their framework of choice.
Vue is now in version 3 as of April 2019.
One significant change is in Vue CLI 3 which is used to generate and scaffold code quickly for a start-up project.
Plugins can be added at any point during the development lifecycle.
We can access the Vue library either online via a CDN or offline
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.common.dev.js"></script>
<script src="assets/js/vue.js"></script># install
yarn global add @vue/cli
# update
yarn global upgrade --latest @vue/cli
# create
vue create test-deploy-to-netlify-01
# navigate
cd test-deploy-to-netlify-01
# run
yarn serve
# deploy - push to GitHub
# deploy - connect Netlify to GitHub repo
# deploy - Netlify build command is `yarn run build`
# deploy - Netlify publish directory is `dist`Egghead-01
Firstly let’s create a standard div
<div id="card"><header>{{ title }}</header><div>{{ content }}</content></div>
Let’s declare a Vue instance
var card = new Vue({el:'card',data:{title:'Dinosaurs',content:'<strong>Dinosaurs</strong> appeared during the Triassic period'}})
# Access Babel Config
vue inspect
Vue prototypevue dev tools are available as a Chrome extension and be sure, in the settings, to also allow access to file URLs
Single File
new Vue() if part of other application in another framework
Vue.component() if part of another application in another framework
v-text v-once v-html v-bind:attribute="value" HTML attributes :attribute="value" v-model 2-way binding v-for="item in items" {{item}} v-on:click="doThis" @click="doThis" v-in:click="DoThis('data')" v-show="isVisible">Show This v-on:submit Form tag v-on:submit.prevent
@click="doThis($event)" .. function(event)... @click="doThis('field',$event" .. function(data,$event)
export default{ data(){ field:'value'} } accessed via this.field
data(){field:'value'},watch:{field:function(){//do this on change}} data(){field:'value'},watch:{field:function(new,old){ }}
Used to display complex calculations to the user as a {{field}} Computed properties are rendered once cached and not re-calculated
Re-calculated on re-render
Method vs Watch vs Computed Methods react to EVENTS eg CLICK Computed creates a data source Watch a data value change
Pass state parent to child export default{props:['first','second']} export default{props:{first:String,second:{type:String,required:true,default:'abc'}}
String,Number, Boolean,Array,Object,Date,Function,Symbol
ComponentName field='value' ComponentName :field=dataItem (dataItem held in data{})
{{name|filter01}} filters:{filter01:function(name){return name?name:'there'}} will return 'there' if 'name' is null
Can action something before your app is created
new Vue({
beforeCreate:function(){
console.log('about to make this Vue app');
},
router,
data() {
return {
IncomingData: 'some data right here'
}
},
render: h => h(App)
}).$mount("#app");Components : re-usable blocks of code
<component-content></component-content>
Vue.component('component-content',{
data: function(){ return { data01:'x' } },
template: '<div>{{x}}</div>
});We can see that the src attribute reads from the data structure using :src=product.src
<template>
<div>
<h1>Phil's Shop</h1>
<div v-if="!paidFor">
<p>Item for sale</p>
<p>Price is £ {{product.price}}</p>
<p>{{product.description}}</p>
<img width="200" :src="product.src" />
</div>
<div ref="paypal"></div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String
},
data() {
return {
loaded: false,
paidFor: false,
product: {
price: 200,
description: "a product",
src: "https://picsum.photos/400/300?random=1"
}
};
}
};
</script>rendering data with expression syntax {{ ... }}
conditional rendering with v-if, v-else-if and v-else
Notice that the app is rendering live and we can prove this by opening up the Chrome Dev Tools and choose the Console and change app.message to an alternative value
events with @mouseover
other events
enabling and disabling features with :disabled
Props cannot have numbers in the name ie ThisProp is good but ThisProp01 is not valid
Refs allow us to name a component so that we can reference it
<input ref="myRef" />
this.$refs["myRef"].focus();
this.$refs.myRef
this.$refs.myRef.value
this.$refs.myRef.baseURI
In an array, for example
<ul v-for="item in collection" :key="index" ref="listofitems">
<li>{{item}}</li>
</ul>
console.log(this.$refs) produces an array with index 0,1,2 etcVuetify adds Google Material Design to the Vue website
vue create myapp
cd myapp
vue add vuetify
<template>
<v-app>
<v-card width="400" class="mx-auto mt-5">
<v-card-title class="pb-0">
<h1>Login</h1>
</v-card-title>
<v-card-text>
<v-form>
<v-text-field
label="Username"
prepend-icon="mdi-account-circle"
/>
<v-text-field
:type="showPassword ? 'text' : 'password'"
label="Password"
prepend-icon="mdi-lock"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append="showPassword = !showPassword"
/>
</v-form>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-btn color="success">Register</v-btn>
<v-btn color="info">Login</v-btn>
</v-card-actions>
</v-card>
</v-app>
</template>
<script>
export default {
name: 'App',
data () {
return {
showPassword: false
}
}
}
</script>v-html
v-on:click
v-model : Binding data fields
v-if and v-else
v-on:keyup
Adding items to an array
v-for loop using an index
Remoing items from an array
v-model : binding data on screen to fields in data
Checking for values to be not null
To make the html display properly we can change the syntax to
<h2 v-html="content"</h2>
app element now contains the items
app.titleapp.content
Add an array to data
dinosaurs:[{name:"raptor"},{name:"triceratops"}]
<ul><li v-for="dinosaur in dinosaurs">{{dinosaur.name}}</li></ul>
See v-for-01.html for a working example
We can bind a button click to a method
<button v-on:click="doThis">Click Here</button>
v-on:keyup.enter=“methodName”
We can call a method with the enter key as well as clicking on a button
<form v-on:keyup.enter="methodName">
<button v-on:click="addItemToList">Add Item To List</button>
<form v-on:keypress.enter="addItem"><input id="itemForm" /><button v-on:click="addItem">Add Dinosaur</button></form>
addItem(){event.preventDefault()var input = document.getElementById('itemForm')if(input.value!==''){let dataItem = {value:input.value}this.dinosaurs.push({name:dataItem.value})//input.value=''}}
We can have two ways to call v-for
- v-for=“item in items”
- v-for=“(item,index) in items”
we can now pass the index through to use it
Let’s add a delete button by adding the index to the v-for
<li v-for="(dinosaur,index in dinosaurs"><button v-on:click="deleteItem(index)">X</button>{{dinosaur.name}}</li>
deleteItem(index){this.dinosaurs.splice(index,1)}
We can bind data fields using v-model
For example in our input form we can use
<form v-on:keypress.enter="addItem">Name:<input v-model="dinosaurName" id="dinosaurName" />Weight:<input v-model="dinosaurWeight" type="number" id="dinosaurWeight"/> kg<button v-on:click="addItem">Add Dinosaur</button></form>
with each dinosaur displaying as a list item
<ul><li v-for="(dinosaur,index in dinosaurs"><button v-on:click="deleteItem(index)">X</button><h4>{{dinosaur.name}}</h4><p>The {{dinosaur.name}} weighs {{dinosaur.weight}} kg</p><a href="">https://en.wikidpedia.org/wiki/{{dinosaur.name}}</a></li></ul>
where our Vue data item can now hold
dinosaurs:[{name:"raptor",weight:20},{name:"triceratops",weight:200}],dinosaurName:'',dinosaurWeight:'',
so we can now add an item using
addItem(){event.preventDefault()let dinosaurName = document.getElementById('dinosaurName').valuelet dinosaurWeight = document.getElementById('dinosaurWeight').valueif(dinosaurName !== ''){let newDinosaur = {name:dinosaurName,weight:dinosaurWeight}this.dinosaurs.push(newDinosaur)this.dinosaurName=''this.dinosaurWeight=''}}
We can filter our lists and either display, hide or change the content.
We do this by creating a filters block in our Vue instance and accessing the named filter as a | pipe after our display item on screen eg <h4>{{dinosaur.name | capitalize}}</h4>
For example we can ensure the first letter is capitalised
filters:{capitalize(value){if(!value)returnvalue=value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}}
We can now apply the filter with
<li v-for="(dinosaur,index in dinosaurs"><button v-on:click="deleteItem(index)">X</button><h4>{{dinosaur.name | capitalize}}</h4><p>The {{dinosaur.name}} weighs {{dinosaur.weight}} kg</p><a href="">https://en.wikidpedia.org/wiki/{{dinosaur.name}}</a></li>
Which will now capitalize the first letter of every heading
Just check for
if(!value){// value is blank}
To create a filter for lower-case only we can do
filter:{undercase(value){if(!value) return ''value = value.toString()return value.toLowerCase()}}
so we can ensure the url is lower case
<a href="">https://en.wikidpedia.org/wiki/{{dinosaur.name|undercase}}</a>
Filters can be combined, or piped, so the output of one is fed into the input of another
For example we can change the URL code to read, when we create a new filter
filters:{url(value){if(!value) return ''value=value.toString()return "https://en.wikidpedia.org/wiki/" + value},}
<a href="">{{ dinosaur.name | undercase | url }}</a>
So now the title appears in Uppercase for first letter, and the URL appears in all lower case regardless of the input.
Computed Properties
Watching
v-bind:class - Dynamically Updating CSS
Enabling/Disabling Screen Items
Inline CSS
v-if/else
v-show
These notes are taken from VueJS on Egghead Video 4
We can compute properties from other properties
Let’s create computed-properties-01
In our Vue instance create, alongside data and methods and filters, one called ‘computed’
data:{},methods:{},filters:{},computed:{totalDinosaurs(){}}
We can add in detail such as :
dinosaurs: [{ name: "Raptor", weight: 20, quantity:1 },{ name: "triceratops", weight: 200, quantity:2 }],
So when we push a new dinosaur we can add the quantity
if (dinosaurName !== "") {let newDinosaur = {name: dinosaurName,weight: dinosaurWeight,quantity:1,};this.dinosaurs.push(newDinosaur);
So we can add computed properties
addQuantity(index){this.dinosaurs[index].quantity++},removeQuantity(index){this.dinosaurs[index].quantity--},
And now build this into our HTML
<ul><li v-for="(dinosaur,index in dinosaurs"><button v-on:click="deleteItem(index)">X</button><h4><button v-on:click="removeQuantity(index)">-</button>{{ dinosaur.quantity }}<button v-on:click="addQuantity(index)">+</button>{{ dinosaur.name | capitalize }}</h4><p>The {{ dinosaur.name }} weighs {{ dinosaur.weight }} kg</p><a href="">{{ dinosaur.name | undercase | url }}</a></li></ul>
See computed-properties-01.html for a working example
We can add, alongside data: and methods: and other blocks, a new block called watch.
This can be aware of changing values on our page.
We must name our watched property to be the name of another data property or computed property etc which already exists. } } }, computed:{ totalDinosaurs(){ return this.dinosaurs.length } }, ```
which can make our HTML appear or disappear
<h3 id="populationWarning">Population Limit Exceeded!!!</h3>
With CSS we can apply or not apply CSS Styles using the following syntax
v-bind:class="{style:styleIsApplied}"
We can change multiple classes using this syntax
<div v-bind:class="{ customStyle1:isStyle1Applied, customStyle2:isStyle2Applied}"
or this syntax
<button class="styleMe" v-bind:class="[{large:isLarge},{rounded:isRounded}]"
As an example, we can bind HTML form input data and use it to set CSS class styles where the custom styles are applied depending if the values are true or false.
Let’s create a simple set of elements with styling data which can be input.
<h1>{{title}}</h1><button class="styleMe" v-bind:class="{large:isLarge}">Style Me</button><br /><br /><input v-model="fontColor" /><label> Font Color</label><br /><input v-model="backgroundColor" /> Background Color<br /><input type="checkbox" v-model="isLarge" /> Large <br /><input type="checkbox" v-model="isRounded" /> Rounded <br /><input type="checkbox" v-model="isDisabled" /> Disabled <br /><input type="range" v-model="range" min="0" max="100" value="0"/><br />
We have used v-model to bind the values to items found in the data: object in our Vue instance
data:{title:"Binding to HTML form data",fontColor:'#cccccc',backgroundColor:'#cccccc',isLarge:false,isDisabled:false,isRounded:false,}
We have bound the class ‘Large’ to whether or not the ‘isLarge’ tick box is ticked or not
<style>.styleMe{width:10vw;}.large{width:20vw;}</style>
So the default width is 10% but when ‘large’ is ticked the width becomes 20% of the screen width.
We can v-bind:disabled to an item
<buttonclass="styleMe"v-bind:disabled="isDisabled">Style Me</button><br /><br /><input type="checkbox" v-model="isDisabled" /> Disabled <br />
To set inline styles we can use computed properties
<button v-bind:style="computedStyle">
computed:{computedStyle(){return{'margin-left':this.buttonMarginLeft + '%',background:this.backgroundColor,color:this.fontColor,}}}
So for example this would work
<buttonclass="styleMe"v-bind:class="[{large:isLarge},{rounded:isRounded}]"v-bind:style="styles"v-bind:disabled="isDisabled">Style Me</button><br /><br /><input v-model="fontColor" /><label> Font Color</label><br /><input v-model="backgroundColor" /> Background Color<br /><input type="checkbox" v-model="isLarge" /> Large <br /><input type="checkbox" v-model="isRounded" /> Rounded <br /><input type="checkbox" v-model="isDisabled" /> Disabled <br /><input type="range" v-model="buttonMarginLeft" min="0" max="100" /><br />
data:{title:"Binding to HTML form data",fontColor:'#cccccc',backgroundColor:'#cccccc',isLarge:false,isDisabled:false,isRounded:false,buttonMarginLeft:0,},computed:{styles(){return {'margin-left':this.buttonMarginLeft + '%',background:this.backgroundColor,color:this.fontColor,}}},
Again see html-form-01.html for a working example of this
This finishes Egghead Vue video 6
We can use if..else statements to render content
We can for example conditionally display a list
<ul v-if="dinosaurs.length>0">
We can use v-else to instruct what to do if the previous v-if is false
<h3 v-else>Please add a new dinosaur</h3>
See v-if-else-01.html for a working example
V-show can display items on a page similar to v-if and v-else
<div v-show="quantity<5">
We could show/hide buttons for example
<ul v-if="dinosaurs.length>0"><h2>List of {{dinosaurs.length}} dinosaurs</h2><li v-for="(dinosaur,index) in dinosaurs"><button v-show="dinosaur.quantity<=5" v-on:click="increaseQuantity(index)">+</button>{{dinosaur.quantity}}<button v-show="dinosaur.quantity>1" v-on:click="decreaseQuantity(index)">-</button>{{dinosaur.name}}<button v-on:click="removeDinosaur(index)">X</button></li></ul>
See v-show-01.html for a working example
v-on:submit
Vue With Checkboxes
Vue With Radio Buttons
Vue With Drop-Down Boxes (HTML Select )
We can call a method on submitting a form
<form v-on:submit="validateFields">
We can call event.PreventDefault() method using the following syntax
<form v-on:submit.prevent="validateFields">
v-model:checked
We can create a binding for an input checkbox
<div id="app"><input type="checkbox" id="checkbox" v-model="isChecked" />This checkbox is {{ isChecked ? 'checked' : 'unchecked' }}<div v-show="isChecked">Checked</div></div><script>var app = new Vue({el:'#app',data:{isChecked:false,}})</script>
see checked-01.html
We can bind the value of a radio button (which gets submitted in the form) with
<input type="radio" v-bind:value="dinosaur.name" />
and also if we want to know which radio button has been clicked we can use v-model=“selectedItem”
See full example at radio-buttons-01.html
<h3>Basic v-for list of dinosaurs</h3><ul><li v-for="dinosaur in dinosaurs">{{dinosaur.name}}</li></ul><h3>Now creating the same list as radio buttons</h3><ul><li v-for="dinosaur in dinosaurs"><input type="radio" v-bind:value="dinosaur.name" v-model="selectedDinosaur"/>{{dinosaur.name}}</li></ul><h5>Your selected dinosaur is {{selectedDinosaur}}</h5></div><script>var app = new Vue({el:'#app',data:{title:"Working With Checkboxes In Vue",dinosaurs:[{name:'Velociraptor'},{name:'tyrannosaurus'}],selectedDinosaur:'',}})
We can also use multi-select checkboxes which are used on many standard forms
The HTML element is called select and each item is an option
Let’s create a basic drop-down box
<select><option v-for="dinosaur in dinosaurs" v-bind:value="dinosaur.name">{{dinosaur.name}}</option></select>
In order to output which item has been selected we can use v-model
<div id="app"><select v-model="selectedDinosaur"><option v-for="dinosaur in dinosaurs" v-bind:value="dinosaur.name">{{dinosaur.name}}</option></select><h4>Your selected dinosaur is {{selectedDinosaur}}</h4></div><script>var app = new Vue({el:'#app',data:{dinosaurs:[{name:"velociraptor"},{name:"stegasaursus"},{name:"triceratops"}],selectedDinosaur:'',}})</script>
We can add multi-select by creating an array of selectedDinosaurs
<div id="app"><h2>Selecting Multiple Dinosaurs</h2><select v-model="selectedDinosaurs" multiple><option v-for="dinosaur in dinosaurs" v-bind:value="dinosaur.name">{{dinosaur.name}}</option></select><h4>Your selected dinosaurs are {{selectedDinosaurs.toString()}}</h4></div><script>var app = new Vue({el:'#app',data:{dinosaurs:[{name:"velociraptor"},{name:"stegasaursus"},{name:"triceratops"}],selectedDinosaur:'',selectedDinosaurs:[],}})</script>
See select-box-01.html for a working example
Components are used to break bigger apps up. Can separate into .vue files if needed
Creating A Component
Using A Component
Reusing Components
Component Local And Global Data
Using Components With The x-template syntax
Vue.component( ‘my-component’, {template:‘This is my component text’} )
We can also declare it as a literal object
var component01 = {template:'<p>{{field01}}</p>',data:function(){return {field01:'some data'}}}
We can now declare a parent Vue element and use this component
<div id="app">
<my-component></my-component>
</div>
<script>
var app = new Vue({
el:'#app'
})
</script>
See component-01.html as a worked example
And component-02.html also
Components can be used multiple times
<div id="app">{{globalData}}<my-component-01></my-component-01><my-component-01></my-component-01></div>
We can have data common across all components
<div id="app">{{globalData}}<component01 /><component01 /></div>
new Vue({el:'#app',data(){return {globalData:"some global data"}}})Vue.component('componenet01',template:'<p>{{localData}}</p>',data(){return {localData:'some local data'}})
We can also create components using the following
<script type="text/x-template" id="component01"><div><button v-on:click="quantity++">{{quantity}}</button>{{name}}</div></script>
and use them by creating a ‘components’ section inside our Vue instance
components:{
'component01':{
template:"#component01",
props:["name","quantity"],
}
},
props are the data items which will be fed into the component
Note that we can also add methods and even data although the data has to be returned as a function.
See component-05.html for a worked example of this.
We can trigger an event in the child component and use it to call a method in the parent component.
We can use the following syntax to emit an event in the child component and listen for it in the parent component
new Vue({el:"#app",data:{},methods:{},components:{'component-01':{template:"component-01",props:[],data(){},methods:{increment(){this.quantity+=1this.emit('increment',1)}}}},})
so we can use this to emit an event in the child component and update the parent component.
See component-06-pass-data.html for a worked example of this
Let’s now add a second template
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script><script src="assets/js/vue.js"></script><title>Vue Components</title></head><body><div id="app"><h1>{{title}}</h1><ul><hr /><li v-for="dinosaur in dinosaurs"><component01v-bind:name="dinosaur.name"v-bind:quantity="dinosaur.quantity"></component01><component02v-bind:name="dinosaur.name"v-bind:diet="dinosaur.diet"></component02><hr /></li></ul></div><script type="text/x-template" id="component01"><div>Component01--<button v-on:click="increment">{{quantity}}</button> {{name}}</div></script><script type="text/x-template" id="component02"><div>Component02--{{name}} eats {{diet}}</div></script><script>new Vue({el:"#app",data:{title:"Using 2 components",dinosaurs:[{name:"Tyrannosaurus",quantity:2,diet:"dinosaurs"},{name:"Stegosaurus",quantity:3,diet:"meat"}],total:0,},created:{},components:{'component01':{template:"#component01",props:["name","quantity"],methods:{increment(){this.quantity++},},},'component02':{template:"#component02",props:["name","diet"],},},})</script></body></html>
We can now toggle between our two templates
After creating our two templates we can set a property currentView
The Vue client is used to quickly scaffold different types of Vue projects from scratch. The latest iteration is Vue Client version 3.
vue-cli startup preferences can be saved for future use, to easily build custom projects from a set template over and over again. The file that is used here is in ~ /.vuerc
Vue CLI 3 also includes Webpack dev server with hot reloading!!!
Create a new project with
vue create project-name
or
vue ui
Go into the folder created and run npm run serve
You can also try installing and running a project with pnpm.
pnpm install cache-loader webpack vue-loader url-loader vue-style-loader postcss-loader css-loader
pnpm run serve
Once vue serve has been installed, to run a single vue file just type
vue serve myfile.vue
You will find that once you go to http://localhost:8080 the file will show. Also saving any changes to the file will instantly appear on the screen.
Plugins can be added to an existing project
vue add router
vue add vuex
vue add @vue/cli-plugin-eslint
vue add apollo
We can build for modern browsers using
vue-cli-service build --modern
API keys can be stored as environment variables
Create an .env file and add this to .gitignore so it’s not pushed to GitHub.
# development or productionNODE_ENV=developmentVUE_APP_TITLE=App TitleVUE_APP_API_Key_01=123456
When we build our Vue project the variable VUE_APP_API_Key_01 will return the appropriate value
in main.js
import Vue from 'vue'import App from './App.vue'Vue.config.productionTip = falseconsole.log(process)console.log(process.env)console.log(process.env.VUE_APP_API_Key_01)new Vue({render: function (h) { return h(App) },}).$mount('#app')/*ObjectBASE_URL: "/"NODE_ENV: "development"VUE_APP_API_Key_01: "123456"VUE_APP_TITLE: "App Title"123456*/
https://www.youtube.com/watch?v=z6hQqgvGI4Y
- Install VUE CDN NPM Vue-Cli Bower
- Npm install -g vue-cli
- Vue init webpack vue-01
- Cd vue-01
- Npm install
- Npm run dev
- Note that to get our route ‘/’ the default route we need to go to src/router/index.js file
- Later on at the end : npm install vue-resource –save (this enables database read)
- Data is read from https://jsonplaceholder.typicode.com - this also has ‘fetch’ instructions
- Exact url is https://jsonplaceholder.typicode.com/users
- Adding in element for styling : npm install element-ui –save
CDN
NPM
Vue-Cli
Bower
Building the Vue Lab
Npm install -g vue-cli
Vue init webpack vue-01
Cd vue-01
Npm install
Npm run dev
Note that to get our route ‘/’ the default route we need to go to src/router/index.js file
Later on at the end : npm install vue-resource –save (this enables database read)
Data is read from https://jsonplaceholder.typicode.com - this also has ‘fetch’ instructions
Exact url is https://jsonplaceholder.typicode.com/users
Adding in element for styling : npm install element-ui –save
npm i npm && vue init webpack hello-world && cd hello-world && npm install && npm run dev
npm i npm && vue init webpack hello-world-03 && cd hello-world-03 && npm install && npm run dev
<!DOCTYPE html><html><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Page Title</title><meta name="viewport" content="width=device-width, initial-scale=1"><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script></head><body><div id="app">hello</div></body><script>new Vue({el: "#app"})</script></html>
<script src="../assets/js/vue.js"></script><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
We can now also run a method
<div id="app"><p>{{sayHello()}}</div>
new Vue({el: '#app',data:{data01: 'some text'},methods:{sayHello:function(){// returns a stringreturn 'saying hello'.}}});
We can access, say for example data01 by the following code
data:{data01: 'some text'},methods:{sayHello:function(){return this.data01}}
v-bind can be used to bind data to an html element attributes
We can go to the href of a link by using the following
<a v-bind:href="link">Click here</a>
data:{link:'http://mysite.com'}
Directives are instructions placed in our code
v-bind is a directive
v-bind:attriute="value"
If we are in a method and wish to change the value of a data field we can do the following
<p>{{DoThis()}}</p>
data:{title:'some title'},methods:{DoThis:function(){this.title='and here is a new title'return this.title}}
<html><head><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script></head><body><div id="app">{{field}}<my-component></my-component><my-component></my-component></div></body><script>Vue.component('my-component',{template:'<p>hello from component</p>'})new Vue({el:'#app',data:function(){return{field:'hello world'}}})</script></html>
<html><head><script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script></head><body><div id="app">{{field01}}<component-01></component-01></div></body><script>Vue.component('component-01',{template:'<p>from component</p>'})new Vue({el:'#app',data:function(){return{field01:'some data here from data function'}}})</script></html>
<html><head><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script></head><body><div id="app">{{globalData}}<my-component-01></my-component-01><my-component-01></my-component-01></div><div id="app2"><my-component-01></my-component-01></div></body><script>Vue.component('my-component-01',{template:'<p><br />hello<br />{{field01}}<br />{{field02}}<button @click="changeMe">ChangeMe</button></p>',data:function(){return {field02: 'some more data here',field01: 'some data here'}},methods:{changeMe:function(){this.field01='Data has now been changed'}}})new Vue({el:'#app',data:function(){return {globalData:'this is common to all instances'}}})new Vue({el:'#app2'})</script></html>
<html><head><script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script></head><body><div id="app"><hr />App<component01></component01></div><div id="app2"><hr />App2<component01></component01></div></body><script>// create component as variablevar component01 = {template:'<p>{{field01}}</p>',data:function(){return {field01:'some data'}}}new Vue({el:'#app',components:{component01}})new Vue({el:'#app2',components:{'component01': component01}})</script></html>
index.html
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>component-05-sub</title></head><body><div id="app"></div><script src="/dist/build.js"></script></body></html>
main.js
import Vue from 'vue'import App from './App.vue'import Home from './Home.vue'Vue.component('component-home',Home)new Vue({el: '#app',render: h => h(App),})
App.vue page linking to a Home component
<template><div id="app"><img src="./assets/logo.png"><h1>{{ msg }}</h1><component-home></component-home></div></template><script>export default {name: 'app',data () {return {msg: 'Welcome to Your Vue.js App'}}}</script>
Home.vue
<template><div>Home Component<p>{{field01}}</p></div></template><script>export default {data: function(){return{field01:'test data'}}}</script>
To introduce routing check out Router-01
main.js
import Vue from 'vue'import BootstrapVue from "bootstrap-vue"import App from './App.vue'import "bootstrap/dist/css/bootstrap.min.css"import "bootstrap-vue/dist/bootstrap-vue.css"import Header from './components/Header.vue'import Footer from './components/Footer.vue'import Page1 from './components/Page1.vue'import Page2 from './components/Page2.vue'import VueRouter from 'vue-router'import { routes } from './routes'Vue.use(VueRouter)Vue.use(BootstrapVue)Vue.component('header-component',Header)Vue.component('footer-component',Footer)Vue.component('page1-component',Page1)Vue.component('page2-component',Page2)const router = new VueRouter({routes,mode : 'history'})new Vue({el: '#app',router,render: h => h(App)})
and routes.js
import Header from './components/Header.vue'import Footer from './components/Footer.vue'import Page1 from './components/Page1.vue'import Page2 from './components/Page2.vue'export const routes = [{path:'',component:null},{path:'/page1',component:Page1},{path:'/page2',component:Page2}]
with main component App.vue
<template><div id="app"><img src="./assets/logo.png"><h1>{{ msg }}</h1><h2>Essential Links</h2><header-component></header-component><h1> <router-view /> </h1><footer-component></footer-component></div></template><script>export default {name: 'app',data () {return {msg: 'Welcome to Your Vue.js App'}}}</script>
from which we can add 4 pages
Header.vue
<template><div><h2>Header</h2><a href="">Home</a> | <a href="/page1">Page1</a> | <a href="/page2">Page2</a></div></template>
Footer.vue
<template><div>Footer</div></template>
Page1.vue
<template><div>Page1</div></template>
Page2.vue
<template><div>Page2</div></template>
These are code snippets from my built code
vue-01.js
There are 2 vue files - App.vue and Phil.vue and these are both being imported here as well as the router
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import Phil from './Phil'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App, Phil },
template: '<App/>'
})
vue-01.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import test from '@/components/test'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'test',
component: test
}, {
path: '/helloworld',
name:'helloworld',
component: HelloWorld
}
]
})
which refers to 2 components
Version 1 and 2 were installed with
npm install -g vue-cli
Version 3 is installed with
npm install -g @vue/cli
Type vue to check you have this installed
vue --version
The version should show version 3 or above
We can build single Vue files using vue serve and vue build commands
npm install -g @vue/cli-service-global
We then create a single App.vue file
<template>
<h1>Hello</h1>
</template>
and run it with
vue serve
which will run the following files : main.js, index.js, App.vue,app.vue
or specify a name
vue serve myFile.vue
you can also build the component and not run it
vue build myFile.vue
This can run instant files
vue create hello-world
Yarn can be used instead of npm to install packages
Saved preferences will be saved in the ~/.vuerc file
Projects can be creates with a GUI
<div v-bind:class="{active:isActive}"></div><div v-bind:style="{color:activeColor}"></div>
Vue file
data{isActive:true,activeColor:'red'}
Vue Components
Components are used to break bigger apps up. Can separate into .vue files if needed
Create a component
Vue.component('my-component',{template:'This is my component text'})
<div id="app"><my-component></my-component></div>
https://www.youtube.com/watch?v=we4zuQIXmnw https://medium.com/codingthesmartway-com-blog/vue-js-2-firebase-e4b2479e35a8"
- Firebase.Google.com
- Databases : Real Time
- Npm install -g vue-cli
- Vue init webpack vue-01
- Cd vue-01
- Npm install
- Npm run dev
https://medium.com/js-dojo/7-vue-js-backends-compared-74812da014f4
https://www.youtube.com/watch?v=we4zuQIXmnw https://medium.com/codingthesmartway-com-blog/vue-js-2-firebase-e4b2479e35a8"
- Firebase.Google.com
- Databases : Real Time
- Npm install -g vue-cli
- Vue init webpack vue-01
- Cd vue-01
- Npm install
- Npm run dev
Vue 2 + Firebase: How to build a Vue app with Firebase authentication system in 15 minutes
vue create vue-with-firebase-01
choose Manual and choose Babel, Router and Linter
cd vue-with-firebase-01
yarn serveGoal will be to build three views
- Login
- Signup
- Home (requires a login)
<template>
<div class="login">
<h3>Sign In</h3>
<input placehoder="Email" />
<input type="password" placeholder="Password" />
<button type="submit">Submit</button>
<p>No account? Please <a href="/">register here</a></p>
</div>
</template>
<script>
export default {
name:'login',
data(){
return {};
},
methods:{}
}
</script>
<style scoped>
</style>Now look at vue-router to view the page
find src/router.js
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Login from './views/Login.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
},
{
path:'/login',name:'login',component:Login
}
]
})
App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/login">Login</router-link> |
<router-link to="/register">Register</router-link>
</div>
<router-view/>
</div>
</template>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
components/Component01.vue
<template>
<div>
<h3>This is component 01</h3>
<p>{{ title }}
</div>
</template>
<script>
export default {
name:'Component01',
props:{
title:String
}
}
</script>
views/Home.vue
<template>
<div class="home">
<h1>Home Page</h1>
<HelloWorld msg="Hello World Component"/>
<HelloWorld msg="Hello World Component"/>
<HelloWorld msg="Hello World Component"/>
<HelloWorld msg="Hello World Component"/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
import About from '@components/About.vue'
export default {
name: 'home',
components: {
HelloWorld
}
}
</script>
views/Login.vue
<template>
<div>
<input placeholder="Email" />
<input type="password" placeholder="Password" />
<button type="submit">Submit</button>
<p>No account? Click to <router-link to="Register">register</router-link></p>
</div>
</template>The login form looks very plain.
Let's add bootstrap
Using
npm install -g @vue/cli
vue create vue-firebase-app
cd vue-firebase-app
yarn serve \router.js
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
import View1 from "./views/View1.vue";
import View2 from "./views/View2.vue";
Vue.use(Router);
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [{
path: "/",
name: "home",
component: Home
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import( /* webpackChunkName: "about" */ "./views/About.vue")
},
{
path: "/view1",
name: "view1",
component: View1
},
{
path: "/view2",
name: "view2",
component: View2
}
]
});
// App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>|
<router-link to="/about">About</router-link>|
<router-link to="/view1">View1</router-link>|
<router-link to="/view2">View2</router-link>
</div>
<router-view />
</div>
</template>
\views\View1.vue and \views\View2.vue
<template>
<div>
<h1>View1</h1>
</div>
</template>yarn add vue bootstrap-vue bootstrap
// main.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import BootstrapVue from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.use(BootstrapVue);
Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount("#app");Vue components allow us to build a reusable model, swapping components in and out of pages.
See vue-2019-09-29-with-firebase for a working example of this
Overall structure
src
assets
components
Component1.vue
Component2.vue
views
View1.vue
View2.vue
App.vue
main.ts
router.ts
# router.ts
import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue'
import Register from './views/Register.vue'
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{ path: '/register', name: 'register', component: Register },
{ path: '/login', name: 'login', component: Login }
],
});
# main.ts
import Vue from 'vue';
import App from './App.vue';
import router from './router';
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App),
}).$mount('#app');
# App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>|
<router-link to="/register">Register</router-link>|
<router-link to="/login">Login</router-link>
</div>
<router-view />
</div>
</template>
# Home.vue
<template>
<div class="home">
<h1>Home.vue</h1>
<h2>
<PhilComponent />
</h2>
<h3>
<ComponentWithMessage msg="Displaying message sent through as props" />
</h3>
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
<ul style="list-style-type:none;">
<li>
<Component2WithMessage msg="Message 01" />
</li>
<li>
<Component2WithMessage msg="Message 02" />
</li>
<li>
<Component2WithMessage msg="Message 03" />
</li>
</ul>
<div>And here is a component with 2 messages in it</div>
<component-with-2-messages
message1="This is message 1"
message2="This is message 2"
:number1="someNumber"
:array1="someArray"
array2="hello hello hello, hello"
/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
import PhilComponent from "@/components/PhilComponent.vue";
import ComponentWithMessage from "@/components/ComponentWithMessage.vue";
import Component2WithMessage from "@/components/Component2WithMessage.vue";
import ComponentWith2Messages from "@/components/ComponentWith2Messages.vue";
@Component({
components: {
HelloWorld,
PhilComponent,
ComponentWithMessage,
Component2WithMessage,
ComponentWith2Messages
}
})
export default class Home extends Vue {
data() {
return {
someNumber: 1000,
someArray: ["one", "two", "three"]
};
}
}
</script>
This provides the lead in to components for example
# ComponentWith2Messages
<template>
<div>
<h5>This is a component with two messages</h5>
<ol>
<li>First Message : {{message1}}</li>
<li>Second Message : {{message2}}</li>
<li>First Number : {{number1}}</li>
</ol>
<ul>
<li v-for="item in array1" v-bind:key="item">An item {{item}}</li>
</ul>
<ul>
<li>{{array2}}</li>
</ul>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
@Component
export default class ComponentWith2Messages extends Vue {
@Prop() private message1!: string;
@Prop() private message2!: string;
@Prop() private number1!: number;
@Prop() private array1!: Array<String>;
@Prop() private array2!: Array<String>;
}
</script>Here we have 2 components with props being passed from the parent to the child component. Lab is vue-2019-10-05
# This is the View
<template>
<div id="master">
<hr />
<h1>Master Component</h1>
<HelloWorld msg="This is a HelloWorld component" />
<Component01 componentprop="Component01Prop" />
<Component02 />
This is a global computed property {{ count }}
<button @click="increment">Increment</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import "es6-promise/auto";
import Vuex from "vuex";
import HelloWorld from "@/components/HelloWorld.vue";
import Component01 from "@/components/Component01.vue";
import Component02 from "@/components/Component02.vue";
export default Vue.extend({
name: "ComponentMaster",
props: {
IncomingData: String
},
components: {
HelloWorld,
Component01,
Component02
},
methods: {
increment() {
console.log("about to increment");
this.$store.commit("increment");
console.log(this.$store.state.count);
localStorage.setItem("vuex-counter", this.$store.state.count.toString());
}
},
computed: Vuex.mapState(["count"])
});
</script>
# This is the component
<template>
<div class="component01">
<hr />
<p>This is <strong>component01</strong> with prop {{ componentprop }} <span><button @click="increment">Increment</button></span></p>
<p>
State of global counter is
<strong>{{ count }}</strong>
</p>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import "es6-promise/auto";
import Vuex from "vuex";
export default Vue.extend({
name: "Component01",
props: {
componentprop: String
},
methods: {
increment() {
console.log("about to increment");
this.$store.commit("increment");
console.log(this.$store.state.count);
localStorage.setItem("vuex-counter", this.$store.state.count.toString());
}
},
computed: Vuex.mapState(["count"])
});
</script>yarn add axios
import axios from 'axios'# vue-2019-10-05-firebase
Author : Philip Anderson
Date : 5 October 2019
Goal : to build a simple Vue app with Firebase to
a) Login
b) View A List Of Usernames
This project has a lot in it
1) Axios to get JSON data from an API
2) Typescript although I didn't implement classes
3) Components
4) Props and passing data to components
5) Local Storage
6) Global counters ie a button which works on different pages and stored also in localStorage
7) Iterating a list obtained as JSON from the API on the screenconst firebaseConfig = {
apiKey: "AIzaSyCfMwaRvBc6hd4ubtZo0obYC8YpG0sgVC0",
authDomain: "vue-with-firebase-01.firebaseapp.com",
databaseURL: "https://vue-with-firebase-01.firebaseio.com",
projectId: "vue-with-firebase-01",
storageBucket: "",
messagingSenderId: "1026739802852",
appId: "1:1026739802852:web:6c9291fcc7acaece"
};
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="/__/firebase/6.3.5/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#reserved-urls -->
<!-- Initialize Firebase -->
<script src="/__/firebase/init.js"></script>
npm install -g firebase-tools
firebase login
firebase init
firebase deployFollowing this tutorial
It's been updated to include Vue3.
# install Vue
npm install -g @vue/cli
vue create vue-2019-09-28-hello-world
cd ..
# run app
yarn serve
# run tests
yarn test:unit
# views\Login.vue
This one was obtained from the internet
// public\index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>Vue To Do</title>
</head>
<body>
<noscript>
<strong>We're sorry but Vue To Do doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>// src\main.js
import Vue from 'vue'
import ToDo from './ToDo.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(ToDo)
}).$mount('#app')
// src\ToDo.vue
<template>
<div id="app">
<div class="ToDo">
<img class="Logo" :src="logo" alt="Vue logo"/>
<h1 class="ToDo-Header">Vue To Do</h1>
<div class="ToDo-Container">
<div class="ToDo-Content">
<ToDoItem v-for="todo in list"
:todo="todo"
@delete="onDeleteItem"
:key="todo.id" />
</div>
<input type="text" v-model="todo" v-on:keyup.enter="createNewToDoItem"/>
<div class="ToDo-Add" @click="createNewToDoItem()">+</div>
</div>
</div>
</div>
</template>
<script>
import ToDoItem from './components/ToDoItem.vue'
import Logo from './assets/logo.png';
export default {
name: 'to-do',
components: {
ToDoItem
},
data() {
return {
list: [
{
id: 1,
text: 'clean the house'
},
{
id: 2,
text: 'buy milk'
}
],
todo: '',
logo: Logo
}
},
methods: {
createNewToDoItem() {
//validate todo
if (!this.todo){
alert("Please enter a todo!");
return
}
const newId = Math.max.apply(null, this.list.map(t => t.id)) + 1;
this.list.push({ id: newId, text: this.todo});
this.todo = '';
},
onDeleteItem(todo){
this.list = this.list.filter(item => item !== todo);
}
},
}
</script>
// src\components\ToDoItem.vue
<template>
<div class="ToDoItem">
<p class="ToDoItem-Text">{{todo.text}}</p>
<div class="ToDoItem-Delete"
@click="deleteItem(todo)">-
</div>
</div>
</template>
<script>
export default {
name: "to-do-item",
props: ['todo'],
methods: {
deleteItem(todo) {
this.$emit('delete', todo)
}
}
}
</script>It is possible to add to Vue.prototype in order to make a variable available globally within our vue app.
# add
Vue.prototype.$appName = 'My App'
# log
new Vue({
beforeCreate: function(){
console.log(this.$appName)
}
})# see vue-2019-10-05-firebase
# main.ts
import 'es6-promise/auto'
import Vuex from 'vuex';
Vue.use(Vuex)
if((localStorage.getItem("vuex-counter")===null)||(localStorage.getItem("vuex-counter")==='NaN')){
localStorage.setItem("vuex-counter",'0');
}
const counterFromStorage = localStorage.getItem("vuex-counter")
console.log('counterFromStorage = ' + counterFromStorage)
let vuexcuounter = counterFromStorage !== null ? parseInt(counterFromStorage) : 0;
const store = new Vuex.Store({
state: {
count: vuexcuounter
},
mutations: {
increment(state) {
state.count++
let item = state.count
localStorage.setItem("vuex-counter",item.toString())
}
}
})
console.log(store.state.count)
new Vue({
beforeCreate: function () {
console.log('hello');
},
router,
store,
data() {
return {
IncomingData: 'some data right here'
}
},
render: h => h(App)
}).$mount("#app");
# Now can use in a component
<template>
This is a global computed property {{ count }}
<button @click="increment">Increment</button>
</template>
<script>
import "es6-promise/auto";
import Vuex from "vuex";
export default Vue.extend({
name: "ComponentMaster",
components: {
HelloWorld,
Component01,
Component02
},
methods: {
increment() {
console.log("about to increment");
this.$store.commit("increment");
console.log(this.$store.state.count);
localStorage.setItem("vuex-counter",this.$store.state.count.toString())
}
},
computed: Vuex.mapState(["count"])
});
</script>https://www.youtube.com/watch?v=4pc6cgisbKE
Note : the following lab has been worked through on a MAC so the Windows process should be similar but not exactly the same so please be aware
Composer is a PHP dependency engine
GetComposer.org/download and copy PHP and install it
On Getting Started page, mkdir -p /usr/local/bin
Then mv composer.phar /usr/local/bin/composer
If this has worked then in terminal can just run the command ‘composer’ to activate the composer window
Now come back to Laravel website : Laravel.com
Download laravel installer : composer global require “laravel/installer” : when this runs it will install developer command line tools from the store
Install XAMPP
Generate a root XAMPP folder and test
Navigate to your root web folder
Create a new project with composer create-project –prefer-dist laravel/laravel larticles
Navigate to the larticles folder
Run sudo chmod -R 777 storage to grant permissions on the storage folder
Go to localhost/larticles/public on your web browser and you should see Laravel web site running
Use these instructions
https://jonathannicol.com/blog/2012/03/11/configuring-virtualhosts-in-xampp-on-mac/
Create a virtual directory in xamppfiles2.conf
Only keep 2 lines
Edit hosts file by using sudo nano /etc/hosts
Create new database in PHPMyAdmin larticles
From our larticles folder run php artisan make:migraion create_articles_table –create=articles which will appear in database/migrations folder
From terminal type php artisan make:seeder ArticlesTableSeeder
Find the file and edit the run function
Also edit the DatabaseSeeder.php file
Generate a factory with php artisan make:factory ArticleFactory
Edit the Factoryfile
Create model with php artisan make:model Article (permissions worked with user root and no password)
Add seed data with php artisan db:seed
Check database now which should be filled with data
Create controller and routes now
php artisan make:controller ArticleController –resource and check created OK in appfolder
Next configure routes in routes.php
Now create resources php artisan make:resource Article which creates, inside http folder a Resources folder then an Article.php file which returns an array
Go to Controllers.php and find the index() function
Can now test http://larticles.test/api/articles which should return data
Can now customise the fields which are returned by editing the Article.php file and editing the return statement
Next look at ArticleController.php show() method which will return only one record based on id
If this works then request to article/3 will return one record
Note that jsonapi.org we can see standards for JSON api responses
On Medium we can create own Laravel 5.5 api
Next move on with Api and in the ArticleController edit the store() method for updating
And finally the delete also
Now test out the API
Delete with article/3
Post to add a new article : Headers add Content-Type as application/json and body add raw json { “title”:“test title”,“body”:“test body”} and send to create a new record
https://www.youtube.com/watch?v=DJ6PD_jBtU0&t=1899s
Picking up from Video 1 which completed the API : we are now building VUE front end for this website
Firstly check package.json Vue.js dependency
Installing Node on a MAC
Firstly need XCode
While XCODE was downloading which will take several hours I just downloaded Node and installed it directly
Checking Make sure that /usr/local/bin is in your $PATH - how do I do that? echo $PATH will show this
node -v and npm -v will now check node and npm are installed ok
go to the larticles root and run npm install to install packages for your Vue app
now run npm run watch to watch for any changes to our files
Now go resources/assets/js to find app.js VUE application
Change the landing page at views/welcomeblade.php and when done, refreshing larticles.test will show just Articles
Now change the code to stop the CSRF error
GetBootstrap.com and get CSS and Javascript
Create a NAVBAR component
Put the NAVBAR in the BLADE
Register the NAVBAR as a COMPONENT in APP.JS
Edit the number of articles returned to 5 in http.controllers.articlecontroller
Change the order to orderBy(‘created_at’,‘desc’)
# installyarn global add @gridsome/cli# generate new projectgridsome create test-projectcd test-project# run at localhost:8080gridsome develop
Now add .vue components in the /pages directory
Saves only one copy of a needed library
Install it via npm
npm install -g pnpm
Once installed, update via pnpm
pnpm install -g pnpm
Now use pnpm in place of npm
There is also a pnpx client which we call a ‘package runner’
For example
pnpx create-react-app my-cool-new-app
This is a series of coding exercises, in order, to investigate OKTA Oauth2.0 Authentication And Authorization
In this project I have precompiled SASS so the CSS goes in the App.vue.
I don't know if this is a great idea - I think I would prefer the CSS in a regular CSS file but never mind, we can sort that later.
Now installing Bulma
https://dev.to/justaashir/bulma-vue-easy-setup-2b3
npm install bulma
That didn't really work so I will have to go back and find out how I installed bulma before which I did and it was lovely, so I do think it would be worth it!
Actually yes I did get bulma all working in the end.
yarn add bulma
Then, in main.ts
```javascript
import './../node_modules/bulma/css/bulma.css';
import "bulma/css/bulma.css"
That is all that is needed to apply bulma.js!
Easy when you know how!
OK so attempting to follow this
https://developer.okta.com/quickstart/#/vue/nodejs/express
now installing okta
npm install @okta/okta-vue --save
actually
yarn add @okta/okta-vue which has also added to package.json
Then in router/index.ts I also had to add
import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'
import Home from '../views/Home.vue'
import Auth from '@okta/okta-vue'
Vue.use(VueRouter)
Vue.use(Auth,{
issuer:'https://${}/oauth2/default',
clientId: '....',
redirectUri: 'http://localhost:8080/implicit/callback',
scopes:['openid','profile','email'],
pkce:true
});although before this worked I had to add
yarn add @types/okta__okta-vue
and then the project compiled
Now adding Okta code
import Auth from '@okta/okta-vue'
Vue.use(VueRouter)
Vue.use(Auth,{
issuer:'https://dev-961456.okta.com/oauth2/default',
clientId: process.env.VUE_APP_OKTA_CLIENT_ID,
redirectUri: 'http://localhost:8080/implicit/callback',
scopes:['openid','profile','email'],
pkce:true
});And this is compiling fine.
But is the data correct?
And we don't want secrets in our code? I am not sure! Let's check
so create file .env in the project root
also .env is in the .gitignore repository
so the variable must start with VUE_APP_ to be read
Vue.use(Auth,{
issuer:'https://dev-961456.okta.com/oauth2/default',
clientId: process.env.VUE_APP_OKTA_CLIENT_ID,
redirectUri: 'http://localhost:8080/implicit/callback',
scopes:['openid','profile','email'],
pkce:true
});this will correctly print out the id
Prevents default submission of a form
<form @submit.prevent="validate"></form>
<script>
export default {
data(){
return
},
methods:{
validate(){
return false
}
}
}