import createDetectDirective from './createDetectDirective.mjs'
//keys, 可用設定鍵: MutationObserver之設定
let keys = ['attributes', 'attributeFilter', 'attributeOldValue', 'characterData', 'characterDataOldValue', 'childList', 'subtree']
//normalize, 未給指令值時使用預設設定, 給物件時原樣作為MutationObserver之設定(不與預設合併)
function normalize(cfg, { given }) {
if (given) {
return {
cfg,
warns: [],
}
}
return {
cfg: {
attributes: true,
childList: true, //節點清單有變更
subtree: true, //所屬子節點變更
// characterData: true,
},
warns: [],
}
}
//create
function create(el, cfg, emit) {
//MutationObserver
let ob = new MutationObserver(function(mutations) {
//console.log('mutations', mutations)
//msg
let msg = {
ele: el,
mutations,
}
//emit
emit(msg)
})
//observe, 設定無效時(例如attributes、childList、characterData皆非true)瀏覽器拋錯, 警告後視為停用
try {
ob.observe(el, cfg)
}
catch (err) {
ob.disconnect()
console.warn(`[v-dommutation] MutationObserver設定無效而不偵測: ${err && err.message}`)
return null
}
return {
clear: () => {
ob.disconnect()
},
}
}
/**
* 自訂指令v-dommutation, 元素(預設含其子孫)之屬性或子節點變更時觸發@dommutation
*
* 指令值: 未給或true為啟用並使用預設設定{attributes:true,childList:true,subtree:true}; false或null為停用(不建立偵測器、不觸發); 其他型別視同未給並警告
* 指令值為物件時原樣作為MutationObserver之設定(不與預設合併), 可用鍵attributes、attributeFilter、attributeOldValue、characterData、characterDataOldValue、childList、subtree, 設定無效時警告並不偵測, 其他鍵不採用並警告
* 宿主重繪後設定改變則重建偵測器; 重建時舊偵測器已記錄而尚未送達之異動不送出
*
* 事件內容為物件{ele,mutations}, ele為元素, mutations為MutationRecord陣列
* 處理函式經Vue之監聽器(invoker)呼叫: 多個處理函式依序執行, 同步錯誤與Promise拒絕交Vue之錯誤處理(自處理函式所屬元件之$parent起經errorCaptured, 再Vue.config.errorHandler), 與原生v-on相同
* 監聽之新增、移除或改名於宿主重繪後跟隨; 元件標籤上同時有@dommutation與@dommutation.native時只呼叫前者, 無前者時呼叫後者; 解除綁定後不再觸發
* 不支援.once、.capture、.passive, 事件名須小寫(@dommutation), 元素上之.native無效, 以上於綁定時警告; .ctrl、.shift、.alt、.meta使處理函式不被呼叫, .stop、.prevent、.left、.right與按鍵修飾字使處理函式拋錯, 皆無法於執行期警告
* 綁定時於元素設ev-mutation屬性, 解除時改為'null'
*
* @returns {Object} 回傳Vue 2自訂指令定義物件, 以Vue.directive('dommutation', domMutation())或元件directives註冊
*/
function domMutation() {
return createDetectDirective({
name: 'dommutation',
attr: 'ev-mutation',
keys,
normalize,
create,
})
}
export default domMutation