###### tags: `Vue` # 【Vue】響應式基礎 (Reactivity Fundamentals) >Document: https://vuejs.org/guide/essentials/reactivity-fundamentals.html ## 響應式物件 (Reactive objects) >能夠追蹤物件的存取權與狀態改變  ### SFC (Single-File Component) vs Codepen [option api](https://codepen.io/intHuang/pen/rNqOzgr) [composition api](https://codepen.io/intHuang/pen/PoyPKMz) 1. 創建 2. 使用 3. 方法宣告 ### DOM 的更新時機 DOM 的更新是非同步的(不是你按下 Click Me 按鈕 DOM 就會馬上更新),使用 nextTick() 來確保 DOM 已經完全更新 ### 深層響應 預設都是深層響應 (有淺層響應 [shallowReactive](https://vuejs.org/api/reactivity-advanced.html#shallowreactive)) ### 【響應式 proxy】 與 【原始對象】 ```js= const raw = {} const proxy = reactive(raw) // proxy is NOT equal to the original. console.log(proxy === raw) // false console.log(proxy === reactive(raw)) // true ``` -> 要更改 proxy 才會具有響應式 ### reactive() 的限制 * 只能作用在 object type (string、number、boolean 都不能作用) * 響應式系統是通過屬性追蹤 ```js= let state = reactive({ count: 0 }) state = reactive({ count: 1 }) ``` :::warning 更改區域變數、解構物件或是函數參數的值都不會影響原始的響應式物件 ::: ```js= const state = reactive({ count: 0 }) let n = state.count // does not affect original state n++ let { count } = state // does not affect original state count++ callSomeFunction(state.count) ``` ### 使用 ref() ```js= import { ref } from 'vue' const count = ref(0) ``` ref() 會回傳一個 reactive 的物件( ref ),包含一個 value 屬性 #### ref 物件在模板中的展開( unwrapping ) >你不用寫 `.value` ```js= const count = ref(0); console.log(count); console.log(count.value); ``` * **只會作用在最上層的物件** ```js= const object = { foo: ref(1) } ``` * 不會動: ```html= {{ object.foo + 1 }} ``` #### ref 物件在響應式物件中的展開 * ref 物件如果被當成 reactive 物件的屬性,也會自己展開 ```js= const count = ref(0) const state = reactive({ count }) console.log(state.count) // 0 state.count = 1 console.log(count.value) // 1 ``` * ref 會取代 ref ```js= const otherCount = ref(2) state.count = otherCount console.log(state.count) // 2 // original ref is now disconnected from state.count console.log(count.value) // 1 ``` * 只會作用在深層響應式物件 #### Arrays 與 [Collections](https://zh.wikipedia.org/zh-tw/%E9%9B%86%E5%90%88_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)) 的 ref 物件展開 * array 與 collection 中不會自動展開(你要自己加上 `.value`) ```js= const books = reactive([ref('Vue 3 Guide')]) // need .value here console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) // need .value here console.log(map.get('count').value) ``` ## 小結 1. option api 中的 data 在 composition api 中 要使用 reactive() 或 ref() 來宣告 2. reactive() 只能用在物件上 3. ref 物件除了陣列與集合,其他都不需要用 `.value` ## 其他 ### option api 中的 debounce function 因為 Vue 的方法都是有狀態的 (stateful),在 Vue 中如果同時調用 debounce function component 之間就可能會互相影響 >* Stateful: 一個方法的計算結果會影響到其他程式碼就稱為 Stateful,反之稱為 Unstateful >* debounce 是一種控制事件觸發頻率的方法,當一個事件被觸發時,它會延遲一段時間,如果在這段時間內有其他事件被觸發,則這個事件會被忽略掉。透過 debounce,可以控制事件的觸發頻率,防止事件被過度觸發。 ```js= import { debounce } from 'lodash-es' export default { methods: { // Debouncing with Lodash click: debounce(function () { // ... respond to click ... }, 500) } } ``` 解決方法: 把 debounce 的創建移到 created 週期 ```js= export default { created() { // each instance now has its own copy of debounced handler this.debouncedClick = _.debounce(this.click, 500) }, unmounted() { // also a good idea to cancel the timer // when the component is removed this.debouncedClick.cancel() }, methods: { click() { // ... respond to click ... } } } ``` ## 提問 1. 什麼時候要用 ref(),什麼時候用 reactive() 2. debounce ? ## 補充 [Reactivity](https://vuejs.org/api/reactivity-core.html#ref) [Collection](https://zh.wikipedia.org/zh-tw/%E9%9B%86%E5%90%88_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)) pinia cheat sheet 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up