一、意思不同
FLOAT浮点型数据类型,FLOAT 数据类型用于存储单精度浮点数或双精度浮点数。32313133353236313431303231363533e58685e5aeb931333431373262浮点数使用IEEE(电气和电子工程师协会)格式。real是不精确的双精度浮点型,float 和 real 数据类型被称为近似的数据类型。
二、字节不同
real型数据的存储大小为4个字节,可精确到小数点后第7位数字。这种数据类型的数据存储范围为从-3.40E+38~-1.18E-38,0和1.18E-38~3.40E+38。
float型的数据存储大小为8个字节,可精确到小数点后第15位数字。这种数据类型的数据存储范围为从-1.79E+308~-2.23E-308,0和2.23E+308~1.79E+308。 FLOAT(size,d) 带有浮动小数点的小数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
二、写法
float型的数据可写成float[(n)]的形式。其中n是1~15之间的整数值,指定float型数据的精度。当n为1~7时,实际上用户定义了一个real型的数据,系统用4个字节存储;当n为8~15时,系统认为它是个float型的数据,用8个字节存储它。这样既增强了数据定义的灵活性,又节省了空间。
float 和 real 的使用遵循有关近似数值数据类型的 IEEE 754 规范。
20行代码,封装一个 React 图片懒加载组件
React 知命境第 34 篇,原创第 141 篇
图片懒加载是我们在做性能优化时非常重要的手段。我们常常需要图片在进入页面可视区域时,才让加载图片的行为发生。
如何判断图片进入视口
我们可以使用传统的方式,监听页面的 scroll 事件,然后调用目标函数的 getBoundingClientRect 方法,得到目标元素在网页中的位置信息。
但是我并不喜欢监听 scroll 事件。因为他会大量的执行,并且 getBoundingClientRect 是一个同步方法,都在主线程上运行,当其频繁执行时可能会导致性能出现问题。
我们可以使用另外一种方式来做到同样的效果。他就是 IntersectionObserver
var observer = new IntersectionObserver(callback[, option])
IntersectionObserver 提供了一种异步观察目标元素与其祖先元素或者顶级文档 viewport 交叉状态的方法。其祖先元素或者视口,被称为根 root。当目标元素与根元素在视图上产生交集时,回调函数就会执行。
我们也可以在 options 中,自定义配置 root 元素
let options = {
root: document.querySelector("#scrollArea"),
rootMargin: "0px",
threshold: 1.0,
};
let observer = new IntersectionObserver(callback, options);
options 接受三个参数
root
自定义目标元素的根节点。该节点必须是目标元素的祖先元素。如果未指定,默认为视口。
rootMargin
根元素周围的边距。其值可以类似于 CSS 的 margin 属性,例如 10px 20px 30px 40px,以此表示上、右、下、左。这些值夜可以是百分比。在计算交叉点之前,这组值用于增大或者缩小根元素边框的每一侧,默认为 0.
threshold
一个数字或者一组数字。表示目标可见度达到多少百分比时,回调函数就应该执行。例如,如果我希望交叉部分每超过目标元素 25% 就执行,那么我就传入 [0, 0.25, 0.5, 0.75, 1]. 默认值为 0
创建的实例有 4 个方法可以让我们使用。
回调函数执行时,接收一个参数,该参数为回调函数提供目标对象的位置信息,一共有六个属性
{
// 回调执行的时间
time: 3893.92,
// 被观察的目标对象
target: element
// 根元素位置信息
rootBounds: ClientRect {
bottom: 920,
height: 1024,
left: 0,
right: 1024,
top: 0,
width: 920
},
// 目标元素位置信息
boundingClientRect: ClientRect {
// ...
},
// 交叉区域矩形的位置大小信息
intersectionRect: ClientRect {
// ...
},
// 元素可见度比例
intersectionRatio: 0.54,
}
该参数返回一个数组包含一个或者多个元素的位置信息。
图片懒加载原理
在浏览器中,展示一张图片,我们使用的是 img 标签。img 标签有一个必须传入的属性 src,当我们不传入 src 时,图片无法加载,一旦传入 src,那么图片就会立即开始加载
因此,我们需要做的事情就是,当图片没有出现在可视区域时,不传入正确的 src 属性,当通过上述的方法判断图片已经出现在可视区域,我们就传入正确的 src,此时图片会立即加载
代码实现
首先,我们封装的新组件,一定要继承原有 img 标签的所有能力。先定义一个 Props 类型声明,目前我们并不需要扩展其他的属性,暂时先这样,未来会根据需求的变动逐渐新增新的属性值。
interface LazyLoadProps extends DetailedHTMLProps, HTMLImageElement> {
}
然后我们我要的事情是,除了 src 属性,我们要把其他属性全部直接传给 img 标签,具体方式如下
export default function LazyLoad(props: LazyLoadProps) {
const {src = '', ...other} = props
return (
)
}
然后我们需要定义一个 ref 属性,用于获取 img 标签的元素对象
export default function LazyLoad(props: LazyLoadProps) {
const {src = '', ...other} = props
const img = useRef(null)
return (
)
}
准备工作做好之后,我们最后只需要借助 useEffect 声明 IntersectionObserver 实例然后监听图片元素即可
export default function LazyLoad(props: LazyLoadProps) {
const {src = '', ...other} = props
const [URL, setURL] = useState('')
const img = useRef(null)
useEffect(() => {
var io = new IntersectionObserver((entries) => {
// @ts-ignore
if (entries[0].intersectionRatio > 0) {
setURL(src)
img.current && io.unobserve(img.current)
}
}, {})
if (img.current) {
io.observe(img.current)
}
}, [])
return (
)
}
这样,一个满足基本要求的图片懒加载组件就封装好了。
扩展思考
在我们做首屏优化的时候,为了能够达到最快的速度渲染页面,图片的加载往往也需要延后,但是又不能延后太多。因此此时的问题是,图片已经出现在可视区域了,我们又应该如何做才能做到懒加载呢?
在实践中可能还会遇到的需求变动是,给图片添加一个占位符。然后占位符元素与图片元素的切换不是立即发生的,而是要等到我们确保图片已经全部加载完成之后才发生的,否则的话,可能会出现图片只加载了一小半的视图情况。这又应该如何实现
继续优化。我们希望占位符元素与图片元素的切换没那么生硬,而是结合动画渐入渐出,又该如何实现。
继续优化,我们希望支持传入 aspectFill 等属性,确保图片的缩放比例,不能因为宽高的设置导致图片比例变形,又该如何实现
这些思考就留给大家在实践中去尝试验证了。本文就不在详细介绍。
「React 知命境」 是一本从知识体系顶层出发,理论结合实践,通俗易懂,覆盖面广的精品小册,点击下方标签可阅读其他文章。欢迎关注我的公众号,我会持续更新。,或者赞赏本文 30 元,可进入 React 付费讨论群,学习氛围良好,学习进度加倍。赞赏之后也能看到 React 哲学的全部内容