1.驳壳枪保险装置运作原理
2.你不知道的盒源k盒 useRef
3.大家 推荐一下 一款 LOL 皮肤盒子 非常好的 效果不错的那种?
4.没写过复杂 React 组件?来实现下 AntD 的 Space 组件吧
驳壳枪保险装置运作原理
毛瑟C手枪击发原理
盒子炮采用短後座力(Short Recoil)式作业。 见图。官方 闭锁榫(Locking Lug)套在滑套下方,盒源k盒 前方卡入闭锁机组(Locking Mechanism Frame),官方 上方嵌入枪机(Bolt)下的盒源k盒两个凹槽。
在击发时,官方防08影院源码 後座力使得枪管兼滑套(Barrel Extension)及枪机向後运动,盒源k盒 此时枪膛仍然是官方在闭锁状态。
由於闭锁榫前方是盒源k盒钩在主弹簧上, 因此有一小段自由行程。官方 由於闭锁机组上方的盒源k盒凹槽, 迫使得闭锁榫向後运动时,官方 只能顺时针向下倾斜,盒源k盒 因此脱出了枪机凹槽。官方 见图。盒源k盒
此时枪管兼滑套(图中省略)因为闭锁榫仍套在其下, 後退停止。 枪机则因为闭锁榫脱出, 得以自由行动, 继续进行扣下击铁、 抛壳的动作, 最後因力量用尽, 复进簧将枪机推回、 上弹, 回复到待击状态。
在这整个过程中, 闭锁榫以前端为圆心, 作顺时针及反时针的弧形运动。 後世的P-, Beretta 等, 与此相同,网站链接aide源码 均称为起落式闭锁枪机(Falling Block Locking Breech)。
速射原理
在提到速射型的自动作业原理前, 首先比较一下速射型与普通盒子炮零组件不同的地方。 见图。
一. 击铁的後下方, 速射型有几个刻角。
二. 闭锁机组的後侧, 速射型多了一道凹槽, 供给捕获钩(Catching Hook)运动用。
三. 枪管兼滑套後方左侧, 凹槽明显的长些。
四. 固定弹匣相对於插入式。
可以全自动发射的速射型, 在枪的左侧有一个选择钮, 当该钮在半自动状态时, 一切作业与普通盒子炮相同。 在该被旋到全自动时, 情况就大不相同了。
望采纳!!
你不知道的 useRef
如果你对React Hook有所了解,那么你可能会对useRef这一概念有所好奇。这篇文章将深入探讨useRef的含义,它与createRef的区别,以及何时选择使用它。什么是useRef
在React中,当你需要在组件生命周期中维护一个持久的变量时,useRef就派上用场了。它并非仅限于DOM操作,而是查看弹出窗口源码可以存储任何类型的值,就像组件实例中的this一样。createRef与useRef的区别
尽管createRef和useRef都可以用来引用组件的某个部分,但它们的工作方式有所不同。createRef每次渲染都会返回一个新的引用,而useRef则始终保持同一个引用。想象一下,createRef像是每次打开新盒子得到的全新物品,useRef则是固定盒子中的内容。 举例来说,如果用它们来存储一个计数器的值,createRef会随着组件渲染而更新计数器的引用,而useRef则保持计数器的最新值,这对于保持某个状态的持久性非常有用。何时使用useRef
useRef的设计初衷是为了解决在函数组件中处理闭包问题,比如在定时器或回调函数中保持状态。比如,你可能需要在handleAlertClick函数中获取上一次点击时的count值,这时useRef就能确保每次调用时都获取到同一值,而不是每次渲染时的新值。 此外,它还能用于在函数组件中模拟类组件的生命周期方法,如在useEffect中获取上一次的props值。总结
总的来说,useRef是一个强大而灵活的工具,它超越了DOM操作,允许你在React组件中持久地存储和操作变量。理解它的工作原理和使用场景,能让你在实际开发中更得心应手。大家 推荐一下 一款 LOL 皮肤盒子 非常好的 效果不错的那种?
LOL皮肤盒子现在免费的有两大类:
第一类:hook换肤,代表作品是源码符号位扩展国外友人设计的lolskinpro,这款插件是在游戏外换肤,换完了进游戏就不能再次切换。
第二类:call换肤,代表作品是中国人设计的CC换肤盒子,是在游戏内按F7可以一键换肤,在当前英雄的所有皮肤之间轮换。
这两类都是支持全英雄全音效的,当然也是仅仅只有自己可以看到。
没写过复杂 React 组件?来实现下 AntD 的 Space 组件吧
React 开发者在日常工作中经常编写组件,但这些大多为业务组件,复杂度并不高。
组件通常通过传入 props 并使用 hooks 组织逻辑来渲染视图,偶尔会用到 context 跨层传递数据。
相对复杂的组件是怎样的呢?antd 组件库中就有许多。
今天,我们将实现antd组件库中的一个组件——Space组件。
首先,我们来了解一下Space组件的使用方法:
Space是一个布局组件,用于设置组件的间距,还可以设置多个组件的对齐方式。
例如,我们可以使用Space组件来包裹三个盒子,设置方向为水平,渲染结果如下:
当然,我们也可以设置为垂直:
水平和垂直的间距可以通过size属性设置,如large、middle、small或任意数值。
多个子节点可以设置对齐方式,如start、开源php源码加密end、center或baseline。
此外,当子节点过多时,可以设置换行。
Space组件还可以单独设置行列的间距。
最后,它还可以设置split分割线部分。
此外,你也可以不直接设置size,而是通过ConfigProvider修改context中的默认值。
Space组件会读取context中的size值,这样如果有多个Space组件,就不需要每个都设置,只需要添加一个ConfigProvider即可。
这就是Space组件的全部用法,简单回顾一下几个参数和用法:
Space组件的使用方法很简单,但功能非常强大。
接下来,我们来探讨一下这样的布局组件是如何实现的。
首先,我们来看一下它最终的DOM结构:
每个box都包裹了一层div,并设置了ant-space-item类。
split部分包裹了一层span,并设置了ant-space-item-split类。
最外层包裹了一层div,并设置了ant-space类。
这些看起来很简单,但实现起来却有很多细节。
下面我们来写一下Space组件的实现代码:
首先,我们声明组件props的类型。
需要注意的是,style是React.CSSProperties类型,即可以设置各种CSS样式。
split是React.ReactNode类型,即可以传入jsx。
其余参数的类型根据其取值而定。
Space组件会对所有子组件包裹一层div,因此需要遍历传入的children并做出修改。
props传入的children需要转换为数组,可以使用React.Children.toArray方法。
虽然children已经是数组了,但为什么还要使用React.Children.toArray转换一下呢?
因为toArray可以对children进行扁平化处理。
更重要的是,直接调用children.sort()会报错,而toArray之后就不会了。
因此,我们会使用React.Children.forEach、React.Children.map等方法操作children,而不是直接操作。
但这里我们有一些特殊的需求,比如空节点不过滤掉,依然保留。
因此,我们使用React.Children.forEach自己实现toArray:
这部分比较容易理解,就是使用React.Children.forEach遍历jsx节点,对每个节点进行判断,如果是数组或fragment就递归处理,否则push到数组中。
保不保留空节点可以根据keepEmpty的option来控制。
这样,children就可以遍历渲染item了,这部分是这样的:
我们单独封装了一个Item组件。
然后,我们遍历childNodes并渲染这个Item组件。
最后,我们将所有的Item组件放在最外层的div中:
这样就可以分别控制整体布局和Item布局了。
具体的布局还是通过className和样式来实现的:
className通过props计算而来,使用了classnames包,这是react生态中常用的包,根据props动态生成className基本都会使用这个包。
这个前缀是动态获取的,最终就是ant-space的前缀。
这些class的样式都定义好了:
整个容器使用inline-flex,然后根据不同的参数设置align-items和flex-direction的值。
最后一个direction的css可能大家没用过,是设置文本方向的。
这样,就通过props动态给最外层div添加了相应的className,设置了对应的样式。
但还有一部分样式没有设置,也就是间距。
其实这部分可以使用gap设置,当然,也可以使用margin,但处理起来比较麻烦。
不过,antd这种组件自然要做得兼容性好一点,所以两种都支持,支持gap就使用gap,否则使用margin。
问题来了,antd是如何检测浏览器是否支持gap样式的呢?
antd创建一个div,设置样式,并添加到body下,然后查看scrollHeight的值,最后删除这个元素。
这样就可以判断是否支持gap、column等样式,因为不支持的话高度会是0。
然后antd提供了一个这样的hook:
第一次会检测并设置state的值,之后直接返回这个检测结果。
这样组件里就可以使用这个hook来判断是否支持gap,从而设置不同的样式了。
最后,这个组件还会从ConfigProvider中取值,我们之前见过:
所以,我们再处理一下这部分:
使用useContext读取context中的值,并设置为props的解构默认值,这样如果传入了props.size就使用传入的值,否则使用context中的值。
这里给Item子组件传递数据也是通过context,因为Item组件不一定会在哪一层。
使用createContext创建context对象:
把计算出的size和其他一些值通过Provider设置到spaceContext中:
这样子组件就能拿到spaceContext中的值了。
这里使用了useMemo,很多同学不会用,其实很容易理解:
props变化会触发组件重新渲染,但有时候props并不需要变化却每次都变,这样就可以通过useMemo来避免它不必要的更新。
useCallback也是同样的道理。
计算size时封装了一个getNumberSize方法,为字符串枚举值设置了一些固定的数值:
至此,这个组件我们就完成了,当然,Item组件还没展开讲。
先来欣赏一下这个Space组件的全部源码:
回顾一下要点:
思路理得差不多了,再来看一下Item的实现:
这部分比较简单,直接上全部代码了:
通过useContext从SpaceContext中取出Space组件里设置的值。
根据是否支持gap来分别使用gap或margin、padding的样式来设置间距。
每个元素都用div包裹一下,设置className。
如果不是最后一个元素并且有split部分,就渲染split部分,用span包裹。
这块还是比较清晰的。
最后,还有ConfigProvider的部分没有看:
这部分就是创建一个context,并初始化一些值:
有没有感觉antd里用context简直太多了!
确实。
为什么?
因为你不能保证组件和子组件隔着几层。
比如Form和FormItem:
比如ConfigProvider和各种组件(这里是Space):
还有刚讲过的Space和Item。
它们能用props传数据吗?
不能,因为不知道隔几层。
所以antd里基本都是用context传数据的。
你会你在antd里会见到大量的用createContext创建context,通过Provider修改context值,通过Consumer或useContext读取context值的这类逻辑。
最后,我们来测试一下自己实现的这个Space组件吧:
测试代码如下:
这部分不用解释了。就是ConfigProvider包裹了两个Space组件,这两个Space组件没有设置size值。
设置了direction、align、split、wrap等参数。
渲染结果是正确的:
就这样,我们自己实现了antd的Space组件!
完整代码在github:github.com/QuarkGluonPl...
总结:
一直写业务代码,可能很少写一些复杂的组件,而antd里就有很多复杂组件,我们挑Space组件来写了下。
这是一个布局组件,可以通过参数设置水平、垂直间距、对齐方式、分割线部分等。
实现这个组件的时候,我们用到了很多东西:
很多同学不会封装布局组件,其实就是对整体和每个item都包裹一层,分别设置不同的class,实现不同的间距等的设置。
想一下,这些东西以后写业务组件是不是也可以用上呢?