import 相關物件
import { ref, readonly, computed, watch, watchEffect, onMounted, provide} from 'vue';
import * as common from "@/utils/common"; // @ = clientapp/src
基本用法
setup() {
const itemRefs = []; // 定義內部使用物件
const orders = ref([]); // 定義HTML可使用物件
const obj = readonly(ref({value:0,text:'123'})); // 定義唯讀物件
const no = computed(() => `$No.{obj.value}`); // 定義計算物件
const f1= (p1, p2) => { // 定義函數
orders.value=xxx; // 設定物件值
}
onMounted(() => { // html rendered
...
})
... // 預先執行程式
return {orders, f1} // 回傳HTML可存取的物件和函數
}
等待 dom 更新完畢
import { nextTick } from 'vue'
用法1:
const xxx = async () => {
await nextTick(); // 等待 dom 更新完畢
...
}
用法2:
const xxx = () => {
nextTick(() => ...); // 設定 dom 更新完畢後要執行的程式
}
使用 props 和 emits
props: ['id'],
emits: ['done'],
setup(props, context) {
console.log(props.id) // 取得 props
context.emit('done'); // 回拋事件
若要修改 props 物件內容,需要另外建立參考物件
const objref = ref(props.obj)
objref.name='123'
使用 provide 和 inject
上層元件(例如 app.vue)
provide("userName", userName) // 設定子元件可讀取寫入的物件
provide('book', readonly(book)) // 設定子元件可讀取的物件
provide("hasRight", { hasRight }) // 設定子元件可呼叫的函數
子元件
const userName = inject("userName"); // 注入上層元件的物件
const { hasRight } = inject("hasRight"); // 注入上層元件的函數
設定watch
watch(id, (newValue, oldValue) => { // 監聽變數
});
watch(()=>obj.id, (newValue, oldValue) => { // 監聽物件屬性
});
watch(()=>obj, (newValue, oldValue) => { // 監聽物件所有屬性
},{deep:true});
watchEffect(() => { // 自動監控使用到的變數
fetchData(); // 只要 props.id 有變化就會自動呼叫 fetchData(),但若 props.id 包在 setTimeout 裡面則不會自動監控
})
const fetchData = () => {
if (props.id)
axios.get(...)
.then(response => {
...
});
}
v-for 搭配 ref
<div v-for="order in orders" :key="order.id" :ref="setItemRef">
let itemRefs = [];
const setItemRef = el => {
if (el) {
itemRefs.push(el) // 將 v-for 每次產生出來的元件放入陣列
}
if (itemRefs.length == orders.value.length) { // 當元件全部產生後執行
const index = orders.value.findIndex(a => a.id == props.id); // 取得特定元件
itemRefs[index].scrollIntoView(); // 讓特定元件顯示在最上面
}
}
onBeforeUpdate(() => {
itemRefs = []
})
避免 import .vue 出現 typescript 編譯錯誤
修改 src/shims-vue.d.ts
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
異步載入元件
import { defineAsyncComponent } from 'vue';
export default {
components: {
xxx: defineAsyncComponent(() =>
import('./xxx.vue')
),
},
DOM出現於視野內時觸發執行動作
import { useIntersectionObserver } from '@vueuse/core'
export default {
setup(props) {
const targetEl = ref();
const { stop } = useIntersectionObserver(
targetEl,
([{ isIntersecting }]) => {
if (isIntersecting) {
...
stop(); // 避免重複觸發
}
}
);
return { targetEl }
},
};
<template>
<div ref="targetEl"></div>
</template>
強制更新元件內容
例如屬性值是動態判斷且會參考 props,但 props 改變時並不會更新屬性值
設定元件的 key 並更新其值會強制更新元件內容
html
====
<WaitSchedule :key="updatekey"></WaitSchedule>
javascript
====
import WaitSchedule from './xxx.vue';
export default {
components: {
WaitSchedule
},
setup() {
const updatekey=ref(1)
watch(() => xxx, () => {
updatekey.value++;
});
設定日期可選最大值為今天
<input class="form-control" type="date" :max="(new Date()).toISOString().split('T')[0]">
import self
須設定元件名稱否則會跳警告且無法正確載入第二個自己
export default {
name: 'name1',
動態css
綁定 css 的值為某個屬性,以達到動態設定目的
<style>
.cv-week {
min-height: v-bind(weekheight);
}
</style>
export default {
setup() {
const maxevents=ref()
const weekheight = computed(() => `${1 + maxevents.value * 2}em`)
return {weekheight }
※單檔元件才有作用 (javascript 寫在同一個 .vue)
※vue3 v-on:change & v-on:input 會抓到舊值,寫法可改為 @change="xxx($event)",$event 放的是新值
※作為 component 必須有唯一的root element否則會有異常狀況