Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a-input 组件不受控 #7720

Closed
1 task done
guaijie opened this issue Jul 9, 2024 · 13 comments · May be fixed by #7737
Closed
1 task done

a-input 组件不受控 #7720

guaijie opened this issue Jul 9, 2024 · 13 comments · May be fixed by #7737
Labels

Comments

@guaijie
Copy link

guaijie commented Jul 9, 2024

  • I have searched the issues of this repository and believe that this is not a duplicate.

Version

undefined

Environment

vue: 3.x ; ant-design-vue: 4.2.3

Reproduction link

Edit on CodeSandbox

a-input 组件不受控

<template>
  <h1>{{ msg }}</h1>
  <a-input v-model:value="msg" @input="handleChange" />
  <!-- 非受控组件 -->
  <a-input :value="1" />
  <!-- 受控组件 -->
  <a-select style="width: 100%" :value="1" :options="options" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
const msg = ref();
const options = [
  { label: 1, value: 1 },
  { label: 2, value: 2 },
];
const handleChange = () => {
  msg.value = "Hello";
};
</script>

What is expected?

期待 a-input 组件与 a-select 组件一样,都是受控组件

What is actually happening?

no response

@pangao66
Copy link

input的输入触发事件是 @input事件 跟html原生保持一致, @change 是失焦的时候触发的

@guaijie
Copy link
Author

guaijie commented Jul 12, 2024

input的输入触发事件是 @input事件 跟html原生保持一致, @change 是失焦的时候触发的

那你改成 input 事件再尝试,我强调的是 a-input 组件不受控,而不在于用哪个事件去主动修改值

@jack-7788
Copy link

首先你为什么会有如此奇怪的想法, v-model:value , 是由 :value + @update:value 组成的语法糖,
你想 使用 const handleChange = () => msg.value = 'Hello' 生效,
那么就不用使用 v-model ,应该这么写
<a-input :value="msg" @update:value ="handleChange " />

@cc-hearts
Copy link
Contributor

作者的意思应该是

<a-input :value="msg" /> 

如果 msg 为 hello world 的话,说明组件是受控的(意思由 value 控制组件的值), 由于没有进行 msg的值变更操作。 因此预期的情况是无论在输入框中输入任何内容,值始终是hello world

如有误,请指正

@guaijie
Copy link
Author

guaijie commented Jul 31, 2024

首先你为什么会有如此奇怪的想法, v-model:value , 是由 :value + @update:value 组成的语法糖, 你想 使用 const handleChange = () => msg.value = 'Hello' 生效, 那么就不用使用 v-model ,应该这么写 <a-input :value="msg" @update:value ="handleChange " />

那你就拆成以下这种写法再去尝试嘛,所有的事件都控制不了输入框的显示值,。

<template>
  <h1>{{ msg }}</h1>
  <a-input :value="msg" @update:value="handleChange" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
1;
const msg = ref();
const handleChange = () => {
  msg.value = "Hello";
};
</script>

不管你是用 update:value 还是 change 还是 input 你首先得清楚这些事件的触发时机吧。
image

@guaijie
Copy link
Author

guaijie commented Jul 31, 2024

作者的意思应该是

<a-input :value="msg" /> 

如果 msg 为 hello world 的话,说明组件是受控的(意思由 value 控制组件的值), 由于没有进行 msg的值变更操作。 因此预期的情况是无论在输入框中输入任何内容,值始终是hello world

如有误,请指正

像你所描述的:’组件完全受控‘,这样当然是最好的。但 vue 官方并未提及受控组件的概念,不像 react 。因此组件受控需要交给组件库去实现。所以我并不清楚提出质疑的那位同志是否了解过这一概念。

我也不说这组件能完全受控,但现在是任何一个事件居然都控制不了输入框的值,直接导致我无法控制字符类型、长度等
事实上,我更期望的就是你所描述的,所有表单组件皆为受控组件,但这要看库的维护者是否有意愿这么改

@jack-7788
Copy link

首先你为什么会有如此奇怪的想法, v-model:value , 是由 :value + @update:value 组成的语法糖, 你想 使用 const handleChange = () => msg.value = 'Hello' 生效, 那么就不用使用 v-model ,应该这么写 <a-input :value="msg" @update:value ="handleChange " />

那你就拆成以下这种写法再去尝试嘛,所有的事件都控制不了输入框的显示值,。

<template>
  <h1>{{ msg }}</h1>
  <a-input :value="msg" @update:value="handleChange" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
1;
const msg = ref();
const handleChange = () => {
  msg.value = "Hello";
};
</script>

不管你是用 update:value 还是 change 还是 input 你首先得清楚这些事件的触发时机吧。 image

第一 , msg.value = 'Hello'; 肯定你键盘怎么敲始终都是 Hello 呀,因为只有这里在赋值呀

第二, 如果你想拿到你想输入的值 , 不管是update:value 事件,还是chang事件,还是input事件, 他都有回调参数的,

<template>
  <h1>{{ msg }}</h1>
  <a-input :value="msg" @update:value="handleChange" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
1;
const msg = ref();
const handleChange = (value) => {
//value 是回调参数的值 , 你可以根据此参数进行逻辑判断,在进行下一行的赋值逻辑
  msg.value = "xxx";
};
</script>

@guaijie
Copy link
Author

guaijie commented Aug 1, 2024

首先你为什么会有如此奇怪的想法, v-model:value , 是由 :value + @update:value 组成的语法糖, 你想 使用 const handleChange = () => msg.value = 'Hello' 生效, 那么就不用使用 v-model ,应该这么写 <a-input :value="msg" @update:value ="handleChange " />

那你就拆成以下这种写法再去尝试嘛,所有的事件都控制不了输入框的显示值,。

<template>
  <h1>{{ msg }}</h1>
  <a-input :value="msg" @update:value="handleChange" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
1;
const msg = ref();
const handleChange = () => {
  msg.value = "Hello";
};
</script>

不管你是用 update:value 还是 change 还是 input 你首先得清楚这些事件的触发时机吧。 image

第一 , msg.value = 'Hello'; 肯定你键盘怎么敲始终都是 Hello 呀,因为只有这里在赋值呀

第二, 如果你想拿到你想输入的值 , 不管是update:value 事件,还是chang事件,还是input事件, 他都有回调参数的,

<template>
  <h1>{{ msg }}</h1>
  <a-input :value="msg" @update:value="handleChange" />
</template>
<script lang="ts" setup>
import { ref } from "vue";
1;
const msg = ref();
const handleChange = (value) => {
//value 是回调参数的值 , 你可以根据此参数进行逻辑判断,在进行下一行的赋值逻辑
  msg.value = "xxx";
};
</script>

你到底有没有明白别人提这个 issue 的意思,你能不能自己先去理解别人的意思和先尝试再来表达自己的看法。
怕有人误解,特地重新改了 demo。首先你先去 demo 里尝试,看看这个 a-input 是否满足你所说的第一条
要是你还不理解就认真去看 cc-hearts 这位参与者的评论

你第一个评论明显是没理解各个事件的触发时机,
以下代码第一种,第二种有什么区别,我通过 input 事件把值重新改成 'Hello' 有什么问题吗?此时的输入框难道不应该总是显示 'Hello'?然而实际情况是这样的吗?

<template>
  <h1>{{ msg }}</h1>
  <!-- 第一种 -->
  <a-input :value="msg" @update:value="handleChange" />
  <!-- 第二种 -->
  <a-input v-model:value="msg" @input="handleChange" />
</template>
<script lang="ts" setup>
import { ref } from "vue";

const msg = ref();
const handleChange = () => {
  msg.value = "Hello";
};
</script>

@23431
Copy link

23431 commented Aug 1, 2024

今天也遇到这个问题了,试了下 elemnt-plus是正常的

@JonathanLiuc
Copy link

JonathanLiuc commented Aug 5, 2024

问题是有,具体原因可以看一下原生input dom的value逻辑,然后看下作者在setValue之后nextTick中回调的逻辑就能看出原因了,作者用的那个$forceUpdate应该是最终比对了属性一样没更新原生input的dom,临时解法是在自己的update:value事件触发时补一个nextTick,回调里通过外层ref取到input的dom节点,如果dom的value与传入给a-input的value不同,就赋值input的dom的value为外面的传入给a-input的value

Copy link

github-actions bot commented Oct 5, 2024

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

@GuoOcean
Copy link

4.2.5版本还是没修改啊

@GuoOcean
Copy link

<a-input
ref="feeInputRef"
:value="formParams.fee"
@update:value="onFeeInput($event)"
>
<template #addonAfter>

%



const onFeeInput = (e: any) => {
nextTick(() => {
if (formParams.value.feeType === 1) {
feeInputRef.value.$el.querySelector("input").value = formatValue100(e);
formParams.value.fee = formatValue100(e);
} else {
feeInputRef.value.$el.querySelector("input").value = formatDecimal(e);
formParams.value.fee = formatDecimal(e);
}
});
};

临时解法

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants