2024-05-09 08:28:45    5    0    0

除了直接在渲染逻辑中使用 form.getFieldValueuseWatch 之外,Ant Design Form 还提供了shouldUpdate属性在 Form.Item 组件上,这是另一种实现表单项之间联动的方式。shouldUpdate 允许你根据其他字段的变化来重新渲染 Form.Item,而不需要直接操作表单状态或使用额外的状态管理。这种方法更适合于当你需要根据一个或多个表单项的值变化来改变当前表单项的行为时使用。

使用 shouldUpdate 实现表单项联动
下面是一个使用shouldUpdate 的例子,它展示了如何根据一个单选按钮的选择来显示一个额外的输入框:

  1. import React from 'react';
  2. import { Form, Input, Radio, Button } from 'antd';
  3. const FormItemDependencyWithShouldUpdate = () => {
  4. return (
  5. <Form layout="vertical">
  6. <Form.Item name="choice" label="选择">
  7. <Radio.Group>
  8. <Radio value="option1">选项1</Radio>
  9. <Radio value="option2">选项2</Radio>
  10. </Radio.Group>
  11. </Form.Item>
  12. {/* 使用shouldUpdate监听choice字段的变化 */}
  13. <Form.Item shouldUpdate={(prevValues, currentValues) => prevValues.choice !== currentValues.choice}>
  14. {({ getFieldValue }) => {
  15. return getFieldValue('choice') === 'option2' ? (
  16. <Form.Item
  17. name="inpu
2024-05-08 06:26:25    2    0    0

原因

使用了 listType="picture-card" 后, 删除/上传图片父元素 .ant-upload-list-picture-card 下面会同时存在两个元素, 一个为上传触发元素, 另一个为显示图片的元素

解决

父元素设置 overflow: hidden 来隐藏多余的元素

  1. .ant-upload-list-picture-card {
  2. overflow: hidden;
  3. height: 300px; // 自行设置合适的高度
  4. .ant-upload-select, .ant-upload-list-item-container {
  5. width: 100% !important;
  6. height: 100% !important;
  7. }
  8. }
2024-04-18 03:36:42    1    0    0

组件

  1. // ElevatorScroll.vue
  2. <template>
  3. <div
  4. class="elevator-container"
  5. @touchstart="handleTouchStart"
  6. @touchmove="handleTouchMove"
  7. @touchend="handleTouchEnd"
  8. ref="elevatorContainerRef"
  9. >
  10. <div
  11. class="section"
  12. v-for="(item, index) in items"
  13. :key="item.id"
  14. :ref="`section-${index}`"
  15. >
  16. <slot :item="item.list" :index="index"></slot>
  17. </div>
  18. <div v-if="showHint && consistentDirection" :class="['scroll-hint', hintPosition]"
  19. :style="{ opacity: hintOpacity }">{{ hintMessage }}
  20. </div>
  21. </div>
  22. </template>
  23. <script>
  24. export default {
  25. props: {
  26. items: {
  27. type: Array,
  28. required: true,
  29. },
  30. activeSectionDate: {
  31. type: Number,
  32. default: 0,
  33. },
  34. },
  35. data() {
  36. return {
  37. startY: 0,
  38. currentY: 0,
  39. hasMoved: false, // 用于记录是否发生了有效滑动
  40. hintOpacity: 0,
  41. showHint: false,
  42. hintMessage: '',
  43. hintPosition: 'hint-bottom',
  44. initialDirection: n
2024-04-17 06:32:18    0    0    0

组件

  1. // CurrentWeekMenu.vue
  2. <template>
  3. <div class="CurrentWeekMenu_root">
  4. <div class="week_box">
  5. <div v-for="(item, index) in weekList" :key="item.id" class="week-item_box"
  6. :class="activeSectionDate === index ? 'active' : ''" @click="scrollToSection(index)">
  7. <div class="week-item_name">{{ item.name }}</div>
  8. <div class="week-item_date">{{ item.date }}</div>
  9. </div>
  10. </div>
  11. <div class="food-menu_box" ref="foodMenuBoxRef">
  12. <div class="food-menu-group_box" v-for="(weekItem, weekIndex) in thisWeek" :key="weekIndex"
  13. :id="'food-menu-group_' + weekIndex">
  14. <div class="food-menu-item_box" v-for="item in weekItem" :key="item.id" :id="item.id"
  15. @click="checked = !checked">
  16. <div class="food-menu-item_img">
  17. <van-image
  18. width="2.13333rem"
  19. height="1.52rem"
  20. fit="cover"
  21. :src="item.imgUrl"
  22. >
2023-09-25 08:36:43    15    0    0
  1. const ForwardTable = React.forwardRef(InternalTable) as <RecordType extends object = any>(
  2. props: React.PropsWithChildren<TableProps<RecordType>> & { ref?: React.Ref<HTMLDivElement> },
  3. ) => React.ReactElement;
  4. // so u can use
  5. <Table<{id: string, b: number}> />
2023-06-09 17:41:49    9    0    0
  1. type InputRefType<T> = T extends React.Ref<infer ElementType> ? ElementType : never;
  2. const inputRef = useRef<HTMLInputElement>(null)
  3. type MyInputRefType = InputRefType<typeof inputRef>
  4. const a: React.MutableRefObject<MyInputRefType> = inputRef
  5. a.current?.focus()
2023-06-09 17:38:17    9    0    0

React 中,React.RefReact.RefObjectReact.MutableRefObject 是三个不同的类型。

  • React.Ref 是一个泛型接口,它定义了 React 元素的类型,用于表示该元素所引用的对象的类型,例如 DOM 元素和自定义组件。

  • React.RefObject<T> 是一个泛型类型,它是 React.Ref 的具体实现,用于引用可变的对象。它表示一个引用,该引用可以包含对某个具体对象的引用,并且可以通过 current 属性访问引用对象。在大多数情况下,当我们需要引用 DOM 元素时,我们使用 React.RefObject

  • React.MutableRefObject<T> 也是一个泛型类型,它是 React.RefObject 的子类型,它提供了一种访问当前引用的可变版本。current 属性是一个可变的对象,可以通过它来更改当前引用指向的对象。在某些情况下,例如使用 useRef 创建引用对象时,可能需要使用 React.MutableRefObject

综上所述,React.Ref 是一个泛型接口,React.RefObject 是它的具体实现,并且用于引用不可变对象,而 React.MutableRefObjectReact.RefObject 的子类型,它提供了访问该引用的可变版本。通常情况下,我们使用 React.RefObject 来引用 DOM 元素,在某些情况下,可能需要使用 React.MutableRefObject

2023-06-08 01:43:46    18    0    0
  1. 图片地址没带任何图片标识(如.png或者http://xxx?id=11)后缀
  2. 刚刚上传的图片回显不出来
    上传图片后图片的status属性一直是uploading状态,图片上传成功,却一直是进度条状态。
    解决方法是在 onCancel={this.handleCancel}回调方法开头加setFileList([…data.fileList]);
  3. 其他官网未显示可用配置
    可配置 onSuccess={e => onSuccess(e)}获取请求返回结果
2023-05-23 02:18:10    5    0    0

测试网站

  • jsperf
  • jsfiddle
  • JSBench
    执行并比较不同 JavaScript 代码片段的执行速度。 通过简单而简短的 URL 与他人在线共享和协作。

合并

测试条件 Chrome版本94.0.4606.81 Firefox版本93.0 (64 位)
Object.assign对象合并 14.07080078125 ms 12.11 ms
展开运算符对象合并 18201.126953125 ms 7424.69 ms
展开运算符数组加单个 42.848876953125 ms 877.14 ms
push方法数组加单个 0.489013671875 ms 0.89 ms
concat方法数组加单个 0.6640625 ms 2.40 ms
展开运算符两个大数组合并 38.1337890625 ms 43.64 ms
concat方法两个大数组合并 4.3740234375 ms 31.28 ms

性能测试结论

在循环比较多或者操作的数组长度比较大的情况下:

  1. Object.assign 多数情况下性能比 展开运算符(...) 的性能高
  2. 数组自带的方法 connat、push 性能比 展开运算符(...) 的性能高

小结

Chrome版本94.0.4606.81Firefox版本93.0 (64 位) 的浏览器下

  • 对象合并,数组合并,Object.assign、connat 的性能会比 展开运算符“...” 的性能高
  • Object.assign 会触发 Proxy/Object.definedPropertyset 方法,展开运算符“...” 不会触发
  • Object.assign展开运算符 都是浅拷贝
  • 合并对象、数组的时候,展开运算符放在前面的性能比放在后面的性能高
  • 不定参数(function (a, ...b) {})的时候,有自己的使用方式
  • 在拷贝的情况下, 展开运算符“...”Object.assign 性能高
2023-04-17 11:30:32    18    0    0

getBoundingClientRect方法简介

getBoundingClientRect 返回的是一个 DOMRect 对象,是一组矩形集合,我们这次所使用的返回值主要是left、top、bottom和right。其余的返回值width、height、x、y这次用不到,就不再讨论。
使用方法如下:

  1. let domToTop = dom.getBoundingClientRect().top // dom 的顶边到视口顶部的距离
  2. let domToLeft = dom.getBoundingClientRect().left // dom 的左边到视口左边的距离
  3. let domToBottom = dom.getBoundingClientRect().bottom // dom 的底边到视口顶部的距离
  4. let domToRight = dom.getBoundingClientRect().right // dom 的右边到视口左边的距离

注意事项:

  1. 得到的值是相对于视口而言的,即如果页面的滚动位置发生变化,那么得到的top、left也会发生变化;如果需要计算到body边框的距离,需要再加上网页滚动条的长度。下面会给出完整例子。
    这个方法返回的四个值都是相对于当前视口的左上角而言的。即top和bottom是dom的顶边和底边到视口的顶部的距离,同理left和right是相对于视口左边的距离。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. .box {
  8. width: 110%;
  9. height: 200%;
  10. position: absolute;
  11. top: 0;
  12. left: 0;
  13. border: 1px solid red;
  14. }
  15. .content {
  16. width: 20%;
1/18