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:
reactiveis applicable to wrapped objects and applies to all properties of the object.refis applicable to wrapped single values and needs to use.valueto 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>