Subscribe on changes!

在模板中使用函数动态生成dom导致模板中使用的响应式数据发生更改时,函数都会被重新执行

avatar
Jun 20th 2023

Vue version

"vue": "^3.2.47"

Link to minimal reproduction

https://play.vuejs.org/#eNpNjkEOgjAQRa8yYQPEBFxjIfEe3RAoCQm0TRnYNE28hTdwpS5MTDgQ6jVsBcVZzfz5+e9rby9lNPTMSzyCrJVNjiyjHOyQsh6W9XdqXeaYR10jMAiNIfHq+e4k/sshXaFqidAx7KW961YKhaAVqwxUSrTgW7hPOeWF4B1CIXqOkII1BNtwtz4cd9H1DHQlEghCSDNYJDefhGjIm55tNqusbAPFwZ/Gw/N6f1yOr/NpGm8W7b6GchM6GInnxrYr5Z55AwrBY0c=

Steps to reproduce

What is expected?

希望可以不不会递归导致页面卡死

What is actually happening?

image

System Info

No response

Any additional comments?

No response

avatar
Jun 20th 2023

This writing is incorrect. The render function depends on count, and every time the render function is executed, it will run data.slot. Within data.slot, count is changed, causing the render function to be executed again, resulting in an infinite loop.

avatar
Jun 20th 2023

This writing cause infinite loop

avatar
Jun 21st 2023

This writing is incorrect. The render function depends on count, and every time the render function is executed, it will run data.slot. Within data.slot, count is changed, causing the render function to be executed again, resulting in an infinite loop.

Because the scene is rendered through the v-for loop in the template, each sub-element needs to be dynamically rendered into the template as a parameter of the function. Is there any way to avoid the infinite loop? Similar to using markRaw api? grateful

avatar
Jun 21st 2023

Do not modify variables dependent on the render function in the render function.

avatar
Jul 27th 2023

As we know. template converted to dom need compiler -> render -> patch-> dom

check the compiler code

function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _createTextVNode(_toDisplayString(_ctx.count) + " ", 1 /* TEXT */),
    _createElementVNode("div", null, _toDisplayString(_ctx.data.slot()), 1 /* TEXT */)
  ], 64 /* STABLE_FRAGMENT */))
}

when invoke _ctx.count. trigger getter and then put the render function to deps. when count changes the render function execute again .

so . u change count . the vue execute render again. The render execute again. the _ctx.data.slot() execute again ( log 11111 again )

Although log 11111 is executed twice but there will be no additional dom creation or destruction during patch. Because <div>{{ data.slot() }}</div> not changed

@RayforReal