-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
13-Watchers-opAPI : basic 、 deep 、 flush post 、 stop watch 、 one eage…
…r dot
- Loading branch information
Showing
11 changed files
with
354 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
<script setup></script> | ||
<script> | ||
import eventHandling from "@/pages/op-doc/App-event-handling.vue" | ||
import watcher from "@/pages/op-doc/App-watcher.vue" | ||
export default { | ||
data() { | ||
return { | ||
} | ||
}, | ||
components: { | ||
eventHandling | ||
watcher | ||
} | ||
} | ||
</script> | ||
<template> | ||
<eventHandling></eventHandling> | ||
<watcher></watcher> | ||
</template> | ||
<style scoped></style> |
33 changes: 33 additions & 0 deletions
33
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Basic.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<script>// Watch-Basic.vue | ||
export default { | ||
data() { | ||
return { | ||
question: '', | ||
answer: 'Questions usually contain a question mark. ;-)', | ||
loading: false, | ||
} | ||
}, | ||
watch: { | ||
question(newQuestion, oldQuestion) { | ||
console.log("new ", newQuestion, "old ", oldQuestion) | ||
if (newQuestion.includes('?')) { this.getAnswer() } | ||
} | ||
}, | ||
methods: { | ||
async getAnswer() { | ||
this.loading = true | ||
this.answer = 'Thinking...' | ||
try { | ||
const res = await fetch('https://yesno.wtf/api') | ||
this.answer = (await res.json()).answer | ||
} | ||
catch (error) { this.answer = 'Error! Could not reach the API. ' + error } | ||
finally { this.loading = false } | ||
} | ||
} | ||
} | ||
</script> | ||
<template> | ||
檢查包含 ? 字元 <input v-model="question" :disabled="loading" /> | ||
<p>{{ answer }}</p> | ||
</template> |
40 changes: 40 additions & 0 deletions
40
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Deep.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<template><!-- Watch-Deep.vue --> | ||
deepData.user.age<input type="number" v-model="deepData.user.age"><br> | ||
deepData.user.name<input type="text" v-model="deepData.user.name"><br> | ||
deepData.details.email<input type="email" v-model="deepData.details.email"><br> | ||
deepData.details.address<input type="address" v-model="deepData.details.address"> | ||
<br> <br> | ||
noDeepData.user.age<input type="number" v-model="noDeepData.user.age"><br> | ||
noDeepData.user.name<input type="text" v-model="noDeepData.user.name"><br> | ||
noDeepData.details.email<input type="email" v-model="noDeepData.details.email"><br> | ||
noDeepData.details.address<input type="address" v-model="noDeepData.details.address"><br> | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
deepData: { | ||
user: { name: '深入監聽', age: 100 }, | ||
details: { email: 'deep@data.com', address: '看內層 資源消耗大' } | ||
}, | ||
noDeepData: { | ||
user: { name: '無深入監聽', age: 10 }, | ||
details: { email: 'noDeep@data.com', address: '只看當前被監聽之屬性內層不看' } | ||
} | ||
}; | ||
}, | ||
watch: { | ||
deepData: { | ||
handler(newValue, oldValue) { | ||
console.log('新值:', newValue); | ||
console.log('舊值:', oldValue); | ||
}, | ||
deep: true // 啟用深度監視器 | ||
}, | ||
noDeepData(newValue, oldValue) { | ||
console.log('noDeepData新值:', newValue); | ||
console.log('noDeepData舊值:', oldValue); | ||
} | ||
} | ||
} | ||
</script> |
27 changes: 27 additions & 0 deletions
27
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Dot.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<template><!-- Watch-Dot.vue --> | ||
<input type="text" v-model="userInfo.name"> | ||
<input type="number" v-model="userInfo.age"> | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
userInfo: { name: 'John', age: 25 } | ||
} | ||
}, | ||
computed: { | ||
fullName() { | ||
console.log("computed", this.userInfo.name) | ||
return this.userInfo.name; | ||
} | ||
}, | ||
watch: { | ||
fullName(newValue, oldValue) { | ||
console.log('New name:', newValue); | ||
},// Note: only simple paths. Expressions are not supported. | ||
'userInfo.age'(newValue, oldValue) { | ||
if (newValue > 18) { alert('You are an adult!'); } | ||
} | ||
} | ||
} | ||
</script> |
34 changes: 34 additions & 0 deletions
34
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Eager.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<template><!-- Watch-Eager.vue --> | ||
<!-- 首次数据初始化,并不会触发watch --> | ||
watch 預設是 lazy (資料有變動才會呼叫)<br> | ||
部分狀況如 拿取(fetch)初始資料 ,而相關資料又變動時再拿取一次。 <br> | ||
eager後: {{ eagerData }} <br> 沒eager前長這樣: {{ eagerOri }} <br> | ||
一般後: {{ data }} <br> 一般沒eager前長這樣: {{ dataOri }} | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
eagerData: "eager初始資料", | ||
eagerOri: "eager初始資料 ", | ||
data: "一般監聽原始", | ||
dataOri: "一般監聽原始", | ||
}; | ||
}, | ||
watch: { | ||
eagerData: { | ||
// handler 執行時 在 create hook 之前 | ||
handler(newValue, oldValue) { | ||
if (this.eagerData === "eager初始資料") { | ||
this.eagerData = "eager 觸發";// 代替re-fetch 一次 | ||
} | ||
}, | ||
immediate: true // 啟用 Eager Watcher,立即觸發回調函數 | ||
}, | ||
data(newV, oldV) { | ||
if (this.data === "一般監聽原始") { this.data = "一般的有變動到 實際不會" } | ||
} | ||
}, | ||
mounted() { console.log('mounted 的console', this.eagerData); } | ||
} | ||
</script> |
38 changes: 38 additions & 0 deletions
38
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Flush-Post.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<template><!-- Watch-Flush-Post.vue --> | ||
<!-- Callback Flush Timing <br> | ||
預設情況下,偵聽器回呼會在父元件更新 (如有) 之後、所屬元件的 DOM 更新之前被調用,<br> | ||
在偵聽器回呼中存取所屬元件的 DOM,那麼 DOM 將處於更新前的狀態。<br> | ||
Post Watchers: 取得更新後的。<br> --> | ||
<p>Counter: {{ counter1 }} noPost</p> | ||
<span>Counter: {{ counter2 }} post</span> | ||
<button @click="increment">Increment</button> | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
counter1: 0, | ||
counter2: 0 | ||
}; | ||
}, | ||
methods: { | ||
increment() { | ||
this.counter1++; | ||
this.counter2++; | ||
} | ||
}, | ||
watch: { | ||
counter1(newValue, oldValue) { | ||
console.log('Watcher triggered:', newValue); | ||
console.log('DOM updated:', document.querySelector('p').textContent); | ||
}, | ||
counter2: { | ||
handler(newValue, oldValue) { | ||
console.log('Watcher triggered (flush: post):', newValue); | ||
console.log('DOM updated (flush: post):', document.querySelector('span').textContent); | ||
}, | ||
flush: 'post', // 使用 'post' 選項,確保在 Vue 更新 DOM 後才觸發 watcher 回調 | ||
} | ||
} | ||
}; | ||
</script> |
27 changes: 27 additions & 0 deletions
27
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Flush-Sync.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<template><!-- Watch-Flush-Sync.vue --> | ||
<input type="text" v-model="message" placeholder="輸入訊息"> | ||
訊息: {{ message }} | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { message: '111', count: 0 }; | ||
}, | ||
created() { | ||
// 在同一个事件循环中VUE会在最后才用data数据刷新DOM | ||
this.message += 1; | ||
this.message += 1; | ||
this.message += 1; | ||
}, | ||
watch: { | ||
message: { | ||
handler(newValue, oldValue) { | ||
this.count++; | ||
console.log(this.count, ' new :', newValue); | ||
}, | ||
flush: 'sync', // 同時我們也知道在VUE中DOM的更新渲染是異步的 透過改成同步 count 能符合預期顯示3次。 建議只觀察布林值 | ||
// https://juejin.cn/post/7095271649573863437 | ||
} | ||
} | ||
}; | ||
</script> |
24 changes: 24 additions & 0 deletions
24
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-One.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<template><!-- Watch-One.vue --> | ||
3.4 版本以上才有 | ||
<input type="text" v-model="data"> | ||
{{ checkOne }} | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
data: "data ", | ||
checkOne: "data change", | ||
} | ||
}, | ||
watch: { | ||
data: { | ||
handler(newValue, oldValue) { | ||
// when `source` changes, triggers only once | ||
this.checkOne = newValue; | ||
}, | ||
once: true | ||
} | ||
} | ||
} | ||
</script> |
51 changes: 51 additions & 0 deletions
51
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Stop-Choose.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<template><!-- Watch-Stop-Choose.vue --> | ||
<div> | ||
結論 使用 Option API 定義的監聽器沒有直接的方法可以手動停止。這是因為在 Option API 中,監聽器是通過 watch 選項來定義的,而這些監聽器不會返回一個可以用來停止它們的函數。<br> | ||
data<input type="text" v-model="data" placeholder="輸入data訊息"> <br> | ||
torch<input type="text" v-model="torch" placeholder="輸入torch訊息"><br> | ||
message<input type="text" v-model="message" placeholder="輸入message訊息"><br> | ||
<button @click="stopWatchers(kill)">停止 watcher</button> | ||
<select v-model="kill" id="killName"> | ||
<option value="data">砍掉data監聽器</option> | ||
<option value="torch">砍掉torch監聽器</option> | ||
<option value="message">砍掉message監聽器</option> | ||
<option value="all">砍掉all</option> | ||
</select> | ||
看似有砍掉實則只是沒動作 因為沒方法可執行 | ||
<br> | ||
</div> | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
message: '123', | ||
data: "一二三", | ||
torch: "火炬", | ||
kill: "", | ||
}; | ||
}, | ||
watch: { | ||
message(newV, oldV) { console.log("message new ", newV, "old", oldV); }, | ||
data(newV, oldV) { console.log("data new ", newV, "old", oldV); }, | ||
torch(newV, oldV) { console.log("torch new ", newV, "old", oldV); }, | ||
$options(newV, oldV) { console.log("$options new ", newV, "old", oldV); }, | ||
}, | ||
methods: { | ||
stopWatchers(killWatch) { | ||
const watchers = this.$options.watch; | ||
console.log(watchers, killWatch); // 有取得到 三個監聽器 | ||
// 判断是否需要停止所有观察者 | ||
console.log(watchers[killWatch]) // 等同 watchers.data 。尤其內容看與正統stop console比較內容 應該是無法stop 因為沒有定義如何停止 | ||
const unwatch = watchers[killWatch]; | ||
console.log(unwatch()); // undefined 表示沒有這個可以取消的方法 | ||
// how to stop watcher without unwatch() in vue | ||
if (killWatch === 'all') { Object.keys(watchers).forEach(prop => { }); } | ||
else { | ||
if (watchers[killWatch]) { } | ||
else { console.log("找不到" + killWatch + "的观察者"); } | ||
} | ||
} | ||
} | ||
} | ||
</script> |
28 changes: 28 additions & 0 deletions
28
Vue3-Official-Doc-Learn/src/components/op-doc/watchers-docs/Watch-Stop.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<template><!-- Watch-Stop.vue --> | ||
<input v-model="data" placeholder="输入一些内容" /> | ||
<p>data : {{ data }}</p> | ||
<button @click="stopWatcher">stop Watch</button> | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { data: '' }; | ||
}, | ||
created() { | ||
// 創建一個觀察者 | ||
this.unwatch = this.$watch('data', this.handleFooChange); | ||
}, | ||
methods: { | ||
handleFooChange(newValue, oldValue) { | ||
console.log(oldValue, '=>', newValue); | ||
}, | ||
stopWatcher() { | ||
// console.log(this.unwatch()); // 這樣也會殺掉 監聽 | ||
this.unwatch(); // 或是在最後生命週期 鉤子 方法 時給去掉 unmounted 之類 (組件卸载時) | ||
}, | ||
}, | ||
unmounted() { | ||
this.unwatch(); // 最好是在組件卸载時 // 清除掉防抖計時器 | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<script> | ||
import WatchBasic from '@/components/op-doc/watchers-docs/Watch-Basic.vue' | ||
import WatchDot from '@/components/op-doc/watchers-docs/Watch-Dot.vue' | ||
import WatchDeep from '@/components/op-doc/watchers-docs/Watch-Deep.vue' | ||
import WacthEager from '@/components/op-doc/watchers-docs/Watch-Eager.vue' | ||
import WatchOne from '@/components/op-doc/watchers-docs/Watch-One.vue' | ||
import WatchPost from '@/components/op-doc/watchers-docs/Watch-Flush-Post.vue'; | ||
import WatchSync from '@/components/op-doc/watchers-docs/Watch-Flush-Sync.vue' | ||
import WatchKill from '@/components/op-doc/watchers-docs/Watch-Stop.vue' | ||
import WatchKill2 from '@/components/op-doc/watchers-docs/Watch-Stop-Choose.vue'; | ||
export default { | ||
components: { WatchBasic, WatchDot, WatchDeep, WacthEager, WatchOne, WatchPost, WatchSync, WatchKill, WatchKill2 }, | ||
} | ||
</script> | ||
<template> | ||
Watch <br> | ||
<WatchBasic></WatchBasic> | ||
<hr> | ||
<WatchDot></WatchDot> | ||
<hr> | ||
<WatchDeep></WatchDeep> | ||
<hr> | ||
<WacthEager></WacthEager> | ||
<hr> | ||
<WatchOne></WatchOne> | ||
<hr> | ||
<WatchPost></WatchPost> | ||
<hr> | ||
<WatchSync></WatchSync> | ||
<hr> | ||
<WatchKill></WatchKill> | ||
<hr> | ||
<WatchKill2></WatchKill2> | ||
https://michaelnthiessen.com/difference-between-computed-property-and-watcher <br> | ||
計算較有聲明性 | ||
Computed props are more declarative than watched properties<br> | ||
計算 較純粹:回傳值 同步 無副作用(如異步請求 更改DOM) | ||
Computed props should be pure: return a value, synchronous, and have no side-effects<br> | ||
計算確實產生(屬性)監聽則指呼叫函式 | ||
Computed props create new reactive properties, watched props only call functions<br> | ||
計算可受多屬性影像(多對一)監聽可影響多屬性(一對多) | ||
Computed props can react to changes in multiple props, whereas watched props can only watch one at a time<br> | ||
經過計算得到的屬性值,它們會被緩存 只在需要時才會被重新計算,監聽屬性發生改變時立即執行相應的函數 | ||
Computed props are cached, so they only recalculate when things change. Watched props are executed every time<br> | ||
同上Computed props are evaluated lazily, meaning they are only executed when they are needed to be used. Watched props | ||
are executed whenever a prop changes<br><br> | ||
Watch is for side effects. If you need to change state you want to use a computed prop instead.<br> | ||
Most of the time you'll want a computed prop, so try to use that first.<br> | ||
</template> |