gloriasoft / veaury

Use React in Vue3 and Vue3 in React, And as perfect as possible!
MIT License
1.27k stars 81 forks source link

[React in Vue] Input 组件在使用双向数据绑定时的性能问题 #119

Closed baijunjie closed 4 months ago

baijunjie commented 4 months ago

经过 applyPureReactInVue 转换过的 Input 组件,如果使用双向数据绑定,那么在每次输入值时,似乎都会触发整个组件的重新渲染。这会导致一个问题,就是如果在一段已经输入的文本的中间进行内容修改,只要输入一个字符,光标就会重新回到内容的尾部,让文本的修改变得非常麻烦,体验变得很差。

<script setup lang="ts">
import { ref } from "vue";
import { applyPureReactInVue } from "veaury";
import { Input } from "@nextui-org/react";

const value = ref("");

function onValueChange(val: string) {
  value.value = val;
}

const ReactInput = applyPureReactInVue(Input);
</script>

<template>
  <div>
    <ReactInput :value="value" @valueChange="onValueChange" />
  </div>
</template>

我尝试了在 React 项目中使用双向绑定时是没有这个问题的。不清楚问题是否出在 applyPureReactInVue 的内部实现中?

React DEMO Vue最小重现 DEMO

devilwjp commented 4 months ago

@baijunjie 这个不是性能问题,是react和vue在处理input的焦点的两个微任务不在同一个事件循环中,这个缺陷后面会有语法糖或者插件去避免

baijunjie commented 4 months ago

@baijunjie 这个不是性能问题,是react和vue在处理input的焦点的两个微任务不在同一个事件循环中,这个缺陷后面会有语法糖或者插件去避免

原来如此,期待后续的解决方案

devilwjp commented 4 months ago

@baijunjie 安装一下beta版本,veaury@beta 添加了injectSyncUpdateForPureReactInVue方法,用法如下:

import { Input } from "@nextui-org/react";
import { applyPureReactInVue, injectSyncUpdateForPureReactInVue } from 'veaury'

// 对原始的Input组件注入一次即可,之后无需再注入
injectSyncUpdateForPureReactInVue(Input, {
  // 函数名和组件状态更新的钩子函数名称要保持一致,接收到的参数也一致
  onValueChange(...args) {
    // 函数应该返回一个对象,对象的key代表了组件内容的状态值的key
    return {
      value: args[0]
    }
  }
})
const ReactInput = applyPureReactInVue(Input);
baijunjie commented 4 months ago

@baijunjie 安装一下beta版本,veaury@beta 添加了injectSyncUpdateForPureReactInVue方法,用法如下:

import { Input } from "@nextui-org/react";
import { applyPureReactInVue, injectSyncUpdateForPureReactInVue } from 'veaury'

// 对原始的Input组件注入一次即可,之后无需再注入
injectSyncUpdateForPureReactInVue(Input, {
  // 函数名和组件状态更新的钩子函数名称要保持一致,接收到的参数也一致
  onValueChange(...args) {
    // 函数应该返回一个对象,对象的key代表了组件内容的状态值的key
    return {
      value: args[0]
    }
  }
})
const ReactInput = applyPureReactInVue(Input);

太棒了,完美解决!

devilwjp commented 4 months ago

@baijunjie 这个问题还没有完全解决 可以合并到#120 一起解决

devilwjp commented 4 months ago

@baijunjie 再重新安装一下beta版本,2.3.17-beta.1

baijunjie commented 4 months ago

@baijunjie 再重新安装一下beta版本,2.3.17-beta.1

升级了,看上去一切正常