如何在安装 vue 后更新模板引用
How to update template ref after mounted vue
我正在尝试 运行 一个函数,它可以在模板安装后计算或观察或观察效果。
watcheffect 只执行一次,当然是在安装前计算 运行s。
我试过 flush: 'post'
的 watcheffect 和 flush in watch,我有点卡住了。
查看文档它应该按预期工作:
https://v3.vuejs.org/guide/composition-api-template-refs.html#watching-template-refs
Therefore, watchers that use template refs should be defined with the flush: 'post' option. This will run the effect after the DOM has been updated and ensure that the template ref stays in sync with the DOM and references the correct element.
app.vue
<template>
<div ref="target">
<h1>my title</h1>
<p>Tenetur libero aliquam at distinctio.</p>
<h1>hello</h1>
<p class="fuckyeah yolo">quia nam voluptatem illum ratione ipsum.</p>
<img src="img.jpg" />
" title="hello" alt />
<h2>hello</h2>
<ol>
<li>hello inital</li>
<li v-for="i in inc">hello</li>
</ol>
</div>
<div>
<button @click="inc++">inc</button>
</div>
<pre>
<code>
{{ toJson }}
</code>
</pre>
</template>
<script>
import { ref } from '@vue/reactivity'
import { templateRef } from '@vueuse/core'
import { useParser } from './markcomposable.js'
import { onMounted, computed, watchEffect } from '@vue/runtime-core';
export default {
setup() {
const inc = ref(0);
const target = ref(null);
const { toJson } = useParser(target);
return {
inc, target, toJson
}
}
}
</script>
//composable.js
import { parse, validate } from "fast-xml-parser"
import { ref, reactive, watchEffect, toRef, nextTick } from 'vue'
const useParser = (target) => {
const toJson = ref(null);
const jsonOptions = reactive({
//defaults
attributeNamePrefix: "",
ignoreAttributes: false,
textNodeName: "text",
arrayMode: true
})
const dumpJson = (target, options) =>
validate(target.outerHTML) ? parse(target.outerHTML, options) : isValid.value;
watchEffect(() => {
if (target.value) {
toJson.value = dumpJson(target.value, jsonOptions)
console.log(toJson.value)
}
}, {
flush: 'post',
})
return {
target,
toJson,
}
}
export { useParser }
澄清一下:
您正在尝试将模板引用传递给您的函数,但在您执行逻辑时它总是变成 null,对吗?
您可以简单地在 composable.js 文件中使用 onMounted(() => {})
挂钩 或者 您可以实施 templateRef
(您已经尝试包含从它的外观来看) 和 until
(https://vueuse.org/shared/until/#usage).
因此,您将 const target = templateRef('target', null)
而不是 const target = ref(null)
并将其传递给您的 composable.js。
在那里你会看到直到裁判是真实的。
所以在你的实际逻辑之前你会这样做:
await until(unrefElement(target)).toBeTruthy()
之后 ref 应提供一个实际元素(使用 unrefElement
获取 templateRef 的元素),您可以开始对其应用实际逻辑。
如果我没理解错的话,您正在尝试观察模板引用的 outerHTML
,并且您希望在插入节点时调用模板引用观察器(通过按钮回调) , 但它只被调用过一次。
发生这种情况是因为观察者实际上只观察模板引用而不是它的属性。只有在使用 component/element 引用初始化模板引用时才会调用观察者。无法重新分配模板引用,因此不会再次调用观察者。此外,模板 ref 的属性不是反应性的,因此如果目标节点的 HTML 更改,则不会调用观察者。
解决方案
代替watcher,使用MutationObserver
来观察对目标节点所做的更改,包括outerHTML
.
创建一个使用 MutationObserver
调用回调的函数:
const observeMutations = (targetNode, callback) => {
const config = { attributes: true, childList: true, subtree: true }
const observer = new MutationObserver(callback)
observer.observe(targetNode, config)
return observer
}
在 onMounted
hook 中,使用该函数观察 target.value
中的模板引用,传递设置 toJson.value
:
的回调
let observer = null
onMounted(() => {
toJson.value = dumpJson(target.value.outerHTML, jsonOptions)
observer = observeMutations(target.value, () => {
toJson.value = dumpJson(target.value.outerHTML, jsonOptions)
})
})
在 onUnmounted
挂钩中,断开观察者作为清理:
onUnmounted(() => observer?.disconnect())
我正在尝试 运行 一个函数,它可以在模板安装后计算或观察或观察效果。
watcheffect 只执行一次,当然是在安装前计算 运行s。
我试过 flush: 'post'
的 watcheffect 和 flush in watch,我有点卡住了。
查看文档它应该按预期工作:
https://v3.vuejs.org/guide/composition-api-template-refs.html#watching-template-refs
Therefore, watchers that use template refs should be defined with the flush: 'post' option. This will run the effect after the DOM has been updated and ensure that the template ref stays in sync with the DOM and references the correct element.
app.vue
<template>
<div ref="target">
<h1>my title</h1>
<p>Tenetur libero aliquam at distinctio.</p>
<h1>hello</h1>
<p class="fuckyeah yolo">quia nam voluptatem illum ratione ipsum.</p>
<img src="img.jpg" />
" title="hello" alt />
<h2>hello</h2>
<ol>
<li>hello inital</li>
<li v-for="i in inc">hello</li>
</ol>
</div>
<div>
<button @click="inc++">inc</button>
</div>
<pre>
<code>
{{ toJson }}
</code>
</pre>
</template>
<script>
import { ref } from '@vue/reactivity'
import { templateRef } from '@vueuse/core'
import { useParser } from './markcomposable.js'
import { onMounted, computed, watchEffect } from '@vue/runtime-core';
export default {
setup() {
const inc = ref(0);
const target = ref(null);
const { toJson } = useParser(target);
return {
inc, target, toJson
}
}
}
</script>
//composable.js
import { parse, validate } from "fast-xml-parser"
import { ref, reactive, watchEffect, toRef, nextTick } from 'vue'
const useParser = (target) => {
const toJson = ref(null);
const jsonOptions = reactive({
//defaults
attributeNamePrefix: "",
ignoreAttributes: false,
textNodeName: "text",
arrayMode: true
})
const dumpJson = (target, options) =>
validate(target.outerHTML) ? parse(target.outerHTML, options) : isValid.value;
watchEffect(() => {
if (target.value) {
toJson.value = dumpJson(target.value, jsonOptions)
console.log(toJson.value)
}
}, {
flush: 'post',
})
return {
target,
toJson,
}
}
export { useParser }
澄清一下: 您正在尝试将模板引用传递给您的函数,但在您执行逻辑时它总是变成 null,对吗?
您可以简单地在 composable.js 文件中使用 onMounted(() => {})
挂钩 或者 您可以实施 templateRef
(您已经尝试包含从它的外观来看) 和 until
(https://vueuse.org/shared/until/#usage).
因此,您将 const target = templateRef('target', null)
而不是 const target = ref(null)
并将其传递给您的 composable.js。
在那里你会看到直到裁判是真实的。 所以在你的实际逻辑之前你会这样做:
await until(unrefElement(target)).toBeTruthy()
之后 ref 应提供一个实际元素(使用 unrefElement
获取 templateRef 的元素),您可以开始对其应用实际逻辑。
如果我没理解错的话,您正在尝试观察模板引用的 outerHTML
,并且您希望在插入节点时调用模板引用观察器(通过按钮回调) , 但它只被调用过一次。
发生这种情况是因为观察者实际上只观察模板引用而不是它的属性。只有在使用 component/element 引用初始化模板引用时才会调用观察者。无法重新分配模板引用,因此不会再次调用观察者。此外,模板 ref 的属性不是反应性的,因此如果目标节点的 HTML 更改,则不会调用观察者。
解决方案
代替watcher,使用MutationObserver
来观察对目标节点所做的更改,包括outerHTML
.
创建一个使用
MutationObserver
调用回调的函数:const observeMutations = (targetNode, callback) => { const config = { attributes: true, childList: true, subtree: true } const observer = new MutationObserver(callback) observer.observe(targetNode, config) return observer }
在
的回调onMounted
hook 中,使用该函数观察target.value
中的模板引用,传递设置toJson.value
:let observer = null onMounted(() => { toJson.value = dumpJson(target.value.outerHTML, jsonOptions) observer = observeMutations(target.value, () => { toJson.value = dumpJson(target.value.outerHTML, jsonOptions) }) })
在
onUnmounted
挂钩中,断开观察者作为清理:onUnmounted(() => observer?.disconnect())