Vue3
Vue.js is a popular front-end JavaScript framework for building user interfaces and single-page applications (SPAs). Vue 3 is the latest version of Vue.js
Install Vue
project
npm init vue@latest
npm create vue@latest //Install in other backends
Install NPM
npm i
Install Axios
(if needed)
npm i axios
Startup
npm run dev
Vue Basics
Add to .eslintrc.cjs
file, you can name the file whatever you want (if needed, you can ignore it)
rules: {
'vue/multi-word-component-names': 0, // Invitation component naming is no longer mandatory
}
Differences:
reactive
is applicable to wrapped objects and applies to all properties of the object.ref
is applicable to wrapped single values and needs to use.value
to access and update the value.
Reactive Usage
import { reactive } from 'vue'
const state = reactive({
count: 0
})
// Access properties
console.log(state.count) // Output: 0
// Update properties
state.count++
console.log(state.count) // Output: 1
Ref usage
import { ref } from 'vue'
const count = ref(0)
// Access property
console.log(count.value) // Output: 0
// Update property
count.value++
console.log(count.value) // Output: 1
Computed usage
Automatically recalculate and then output
import { computed } from 'vue'
const list = ref([1,2,3,4,5,6,7,8])
const computedList = conputed(() => {
return list.value.filter(item => item > 2);
})
setTimeout(() => {
list.value.push(9,10);
})
Watch function
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log('count has changed, the old value is ${oldValue}, the new value is ${newValue}')
})
Watch Function Listen to changes
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('cp')
watch(
[count, name],
([newCount, newName], [oldCount, oldName]) => {
console.log('count or name has changed, [newCount, newName], [oldCount, oldName]')
}
)
Watch Function Deep Mode
import { ref, watch } from 'vue'
const state = ref({ count: 0})
const changeStateByCount = () => {
state.value.count++
}
watch(state, () => {
console.log('count changed')
}, {
deep: true
})
Watch Function Deep Mode (Watch starts only when a specific value changes)
import { ref, watch } from 'vue'
const state = ref({
name: 'Hoo',
age: 18
})
const changeName = () => {
state.value.name = 'Superman'
}
watch(
() => state.value.age,
() => {
console.log('age has changed')
}
)
v-for
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
v-if
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else>
C
</div>
v-show
<div v-show="isVisible">
Display content
</div>
@click
<button @click="handleClick">Click me</button>
v-model
<script setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>
<template>
<div>
<input type="text" v-model="inputValue">
</div>
</template>
Provide And Inject
Parent Component
provide('data-key','this is room data')
Other subcomponents
const roomData = inject('data-key')
Route
Route
File
import {createRouter, createWebHistory} from "vue-router";
import invoiceIndex from "../components/invoices/index.vue";
import notFound from "../components/NotFound.vue";
import invoiceNew from '../components/invoices/new.vue';
import invoiceShow from '../components/invoices/show.vue';
import invoiceEdit from '../components/invoices/edit.vue';
const routes = [
{
path: '/',
component: invoiceIndex
},
{
path:'/invoice/new',
component: invoiceNew
},
{
path:'/invoice/show/:id',
component: invoiceShow,
props: true
},
{
path:'/invoice/edit/:id',
component:invoiceEdit,
props: true
},
{
path: '/:pathMatch(.*)*',
component: notFound
}
]
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
Use
<router-view />
<router-link to="/">Back to home page</router-link>
useRouter
<script setup>
import axios from "axios";
import { onMounted, ref } from "vue";
import { useRouter } from "vue-router"
const router = useRouter()
let invoices = ref([])
let searchInvoice = ref([])
onMounted(async() => {
getInvoices()
})
const getInvoices = async() => {
let response = await axios.get("/api/get_all_invoice")
//console.log('response',response)
invoices.value = response.data.invoices
}
const search = async() => {
let response = await axios.get('/api/search_invoice?s='+searchInvoice.value)
//console.log('response',response.data.invoices)
invoices.value = response.data.invoices
}
const newInvoice = () => {
router.push('/invoice/new')
}
const onShow = (id) => {
router.push('/invoice/show/'+id)
}
</script>
<template>
<div class="container">
<div class="invoices">
<div class="card__header">
<div>
<h2 class="invoice__title">Invoices</h2>
</div>
<div>
<a class="btn btn-secondary" @click="newInvoice">
New Invoice
</a>
</div>
</div>
<div class="table card__content">
<div class="table--filter">
<span class="table--filter--collapseBtn ">
<i class="fas fa-ellipsis-h"></i>
</span>
<div class="table--filter--listWrapper">
<ul class="table--filter--list">
<li>
<p class="table--filter--link table--filter--link--active">
All
</p>
</li>
<li>
<p class="table--filter--link ">
Paid
</p>
</li>
</ul>
</div>
</div>
<div class="table--search">
<div class="table--search--wrapper">
<select class="table--search--select" name="" id="">
<option value="">Filter</option>
</select>
</div>
<div class="relative">
<i class="table--search--input--icon fas fa-search "></i>
<input class="table--search--input" type="text" placeholder="Search invoice"
v-model="searchInvoice" @keyup="search()">
</div>
</div>
<div class="table--heading">
<p>ID</p>
<p>Date</p>
<p>Number</p>
<p>Customer</p>
<p>Due Date</p>
<p>Total</p>
</div>
<!-- item 1 -->
<div class="table--items" v-for="item in invoices" :key="item.id" v-if="invoices.length">
<a href="#" @click="onShow(item.id)">
#{{item.id}}
</a>
<p>{{item.date}}</p>
<p>#{{item.number}}</p>
<p v-if="item.customer">
{{item.customer.firstname}}
</p>
<p v-else></p>
<p>{{item.due_date}}</p>
<p> $ {{item.total}}</p>
</div>
<div class="table--items" v-else>
<p>Invoice not found</p>
</div>
</div>
</div>
</div>
</template>