二货爱吃白萝卜
2 years ago
committed by
GitHub
2 changed files with 214 additions and 0 deletions
@ -0,0 +1,107 @@ |
|||
--- |
|||
title: To be what you see |
|||
date: 2023-05-10 |
|||
author: zombieJ |
|||
--- |
|||
|
|||
With daily development, have you thought about a problem. When the range limit is different from the actual value, how should we deal with it? Suppose we have a display component that simply displays your value: |
|||
|
|||
```tsx |
|||
interface StrProps { |
|||
value: string; |
|||
} |
|||
|
|||
function MyStr({ value }: StrProps) { |
|||
return <div>{value}</div>; |
|||
} |
|||
<MyStr value="Hello World" />; |
|||
``` |
|||
|
|||
Without a doubt, `Hello World` should be displayed on the page. Next, we add a scope limit: |
|||
|
|||
```tsx |
|||
interface StrProps { |
|||
value: string; |
|||
maxLen?: number; |
|||
} |
|||
``` |
|||
|
|||
What should be displayed if we use a value out of range at this time? |
|||
|
|||
```tsx |
|||
<MyStr value="Hello World" maxLen={5}> |
|||
``` |
|||
|
|||
"Obviously", since you have `maxLen`, you should display `Hello` instead of `Hello World`. |
|||
|
|||
But this intuitive approach is not correct in all cases. If you use native input, you will find that the behavior is not like this: |
|||
|
|||
```tsx |
|||
<input value="Hello World" maxLength={5} /> |
|||
``` |
|||
|
|||
<img height="50" alt="input limit" src="https://github.com/ant-design/ant-design/assets/5378891/31352b9b-6d68-4a42-832d-5a639fed80cc"> |
|||
|
|||
As described by the standard, `maxLength` only limits user input. Is this standard wrong? |
|||
|
|||
> A form control maxlength attribute, controlled by the dirty value flag, declares a limit on the number of characters a user can input. |
|||
|
|||
### "Unnecessary over design" |
|||
|
|||
With the above questions in mind, we imagine an input scenario. Now you have an e-commerce system, set prices for products: |
|||
|
|||
```tsx |
|||
<Form> |
|||
<Form.Item label="Name" name="name"> |
|||
<Input /> |
|||
</Form.Item> |
|||
|
|||
<Form.Item label="Price" name="price"> |
|||
<InputNumber /> |
|||
</Form.Item> |
|||
</Form> |
|||
``` |
|||
|
|||
<img height="160" alt="Form" src="https://github.com/ant-design/ant-design/assets/5378891/f9ad7f13-d2bf-4537-9265-48789e2c4d0e"> |
|||
|
|||
One day your manager said that the price of our product cannot exceed $99 according to regulations, and you have to set the limit directly on the form. This change is not difficult: |
|||
|
|||
```diff |
|||
-- <InputNumber /> |
|||
++ <InputNumber max={99} /> |
|||
``` |
|||
|
|||
But for existing products, we obviously cannot restrict them directly on the form. Otherwise, when the user edits the product, he will find that the price of his product has been changed. This is obviously unreasonable. |
|||
|
|||
<img height="162" alt="Form modify" src="https://github.com/ant-design/ant-design/assets/5378891/08d07ec2-7be8-45fa-b30b-51395252bcd0"> |
|||
|
|||
(Users will never be able to understand why the data in the background does not match what they see) |
|||
|
|||
In fact, in many scenarios, components should not directly modify the actual value. Especially for input components, changing the display value without authorization will have very serious consequences. |
|||
|
|||
### To be what you see |
|||
|
|||
At the component library level, we cannot "guess" the user's usage scenarios, so we need to implement the processing of boundary scenarios in the most conservative way. But at the same time, we can actually do some optimization methods. For example, set the restriction to the `rules` of Form.Item, and use the form validation ability to make restrictions: |
|||
|
|||
<img height="160" alt="Form rules" src="https://github.com/ant-design/ant-design/assets/5378891/52b35fb3-a800-447f-85b3-684d9a65c8d1"> |
|||
|
|||
For some components themselves, it is also possible to add explicit style reminders: |
|||
|
|||
<img height="40" alt="InputNumber" src="https://github.com/ant-design/ant-design/assets/5378891/e14ab877-4778-49c7-af75-91e36e60ce0f"> |
|||
|
|||
For non-input custom components, you can also consider reminding users through design. For example, we can add a Tooltip to the display component: |
|||
|
|||
```tsx |
|||
// Same demo we've seen before |
|||
<MyStr value="Hello World" maxLen={5}> |
|||
``` |
|||
|
|||
<img height="90" alt="Customize" src="https://github.com/ant-design/ant-design/assets/5378891/18b095c4-eee9-45df-aa05-b4f5c20c81f8"> |
|||
|
|||
Or use some other display way: |
|||
|
|||
<img height="40" alt="Ellipsis" src="https://github.com/ant-design/ant-design/assets/5378891/24162b19-985c-4fc4-908a-cdddfc507fc9"> |
|||
|
|||
### Finally |
|||
|
|||
Boundary scenarios need to be carefully handled when developing components. In complex system, upstream users may not know how your internal logic is handled. Therefore, as the complexity and usage scenarios increase, we recommend always choosing a conservative approach to the default behavior. For situations that do not meet the requirements, it can be implemented in the form of HOC or some additional Props configuration, so as to prevent developers from having too many agreements when using it without knowing it. |
@ -0,0 +1,107 @@ |
|||
--- |
|||
title: 所见即所得 |
|||
date: 2023-05-10 |
|||
author: zombieJ |
|||
--- |
|||
|
|||
在日常开发过程中,你是否思考过一个问题。那就是范围限定和实际值不同的时候,应该如何去处理?假设我们有一个展示组件,它很简单的将你的值进行展示: |
|||
|
|||
```tsx |
|||
interface StrProps { |
|||
value: string; |
|||
} |
|||
|
|||
function MyStr({ value }: StrProps) { |
|||
return <div>{value}</div>; |
|||
} |
|||
<MyStr value="Hello World" />; |
|||
``` |
|||
|
|||
毫无疑问,页面上就该展示 `Hello World`。接着,我们加个范围限定: |
|||
|
|||
```tsx |
|||
interface StrProps { |
|||
value: string; |
|||
maxLen?: number; |
|||
} |
|||
``` |
|||
|
|||
这个时候如果我们使用了超出范围的值应该显示什么? |
|||
|
|||
```tsx |
|||
<MyStr value="Hello World" maxLen={5}> |
|||
``` |
|||
|
|||
“显而易见”,既然有了 `maxLen`,那么就应该显示 `Hello` 而非 `Hello World`。 |
|||
|
|||
但是这种直觉的处理方式,却并不是所有情况下都是正确的。如果你使用原生的 input,你就发现表现并不是这样的: |
|||
|
|||
```tsx |
|||
<input value="Hello World" maxLength={5} /> |
|||
``` |
|||
|
|||
<img height="50" alt="input limit" src="https://github.com/ant-design/ant-design/assets/5378891/31352b9b-6d68-4a42-832d-5a639fed80cc"> |
|||
|
|||
按照标准描述,`maxLength` 只限制用户输入。这是标准错了吗? |
|||
|
|||
> A form control maxlength attribute, controlled by the dirty value flag, declares a limit on the number of characters a user can input. |
|||
|
|||
### “多此一举” |
|||
|
|||
带着上面的疑问,我们想象一个输入场景。现在你有一个电商系统,给商品设定价格: |
|||
|
|||
```tsx |
|||
<Form> |
|||
<Form.Item label="Name" name="name"> |
|||
<Input /> |
|||
</Form.Item> |
|||
|
|||
<Form.Item label="Price" name="price"> |
|||
<InputNumber /> |
|||
</Form.Item> |
|||
</Form> |
|||
``` |
|||
|
|||
<img height="160" alt="Form" src="https://github.com/ant-design/ant-design/assets/5378891/f9ad7f13-d2bf-4537-9265-48789e2c4d0e"> |
|||
|
|||
某天你的经理说,我们的商品价格按规定不能超过 99 元,你要直接在表单上做限制。这个改动并不难: |
|||
|
|||
```diff |
|||
-- <InputNumber /> |
|||
++ <InputNumber max={99} /> |
|||
``` |
|||
|
|||
但是对于现有的商品,我们显然不能直接在表单上做限制。否则,用户在编辑商品的时候,就会发现自己的商品价格被改了。这显然是不合理的。 |
|||
|
|||
<img height="162" alt="Form modify" src="https://github.com/ant-design/ant-design/assets/5378891/08d07ec2-7be8-45fa-b30b-51395252bcd0"> |
|||
|
|||
(用户永远无法明白为什么后台的数据和看到的对不上了) |
|||
|
|||
实际上在很多场景下,组件都不应该直接修改实际值。尤其是输入型组件,擅自更改展示值会出现非常严重的后果。 |
|||
|
|||
### 所见即所得 |
|||
|
|||
在组件库层面,我们不能“推测”用户的使用场景,因而需要以最保守的方式实现边界场景的处理。但是同时我们其实可以做一些优化手段。比如说将限制设置到 Form.Item 的 `rules` 上,利用表单校验能力来做限制: |
|||
|
|||
<img height="160" alt="Form rules" src="https://github.com/ant-design/ant-design/assets/5378891/52b35fb3-a800-447f-85b3-684d9a65c8d1"> |
|||
|
|||
对于一些组件本身,也可以添加显式的样式提醒: |
|||
|
|||
<img height="40" alt="InputNumber" src="https://github.com/ant-design/ant-design/assets/5378891/e14ab877-4778-49c7-af75-91e36e60ce0f"> |
|||
|
|||
对于非输入型自定义组件,也可以考虑通过设计来提醒用户。比如说我们可以在展示组件上添加一个 Tooltip: |
|||
|
|||
```tsx |
|||
// Same demo we've seen before |
|||
<MyStr value="Hello World" maxLen={5}> |
|||
``` |
|||
|
|||
<img height="90" alt="Customize" src="https://github.com/ant-design/ant-design/assets/5378891/18b095c4-eee9-45df-aa05-b4f5c20c81f8"> |
|||
|
|||
或者使用一些其他的展示方式: |
|||
|
|||
<img height="40" alt="Ellipsis" src="https://github.com/ant-design/ant-design/assets/5378891/24162b19-985c-4fc4-908a-cdddfc507fc9"> |
|||
|
|||
### 总结 |
|||
|
|||
在进行组件研发时,需要慎重处理边界场景。在大型项目中,上游使用者可能并不知道你的内部逻辑是如何处理的。因而随着复杂度以及使用场景的增加,我们更加推荐对于默认行为总是选择保守的处理方式。而对于不满足需求的情况,可以通过 HOC 的形式或者是一些额外的 Props 配置来实现,以防止开发者在使用时有过多的约定而不知。 |
Loading…
Reference in new issue