Skip to content

开发小知识分享

分享一些我所知道的容易踩坑的小知识点。

CSS

flex 布局下的弹性宽度处理

flex 布局是现在开发中使用的最多也是最主流的一个布局方式了,非常的好用,但是在一些特殊场景下,flex 布局会影响一些子元素的宽度,这时候就需要特殊的设置一些 API。

涉及的 API

  • flex
  • width
  • max-widthmin-width

背后的小故事

有一天我在开发的时候,一个同事看我写了以下一段代码:

css
// ... 省略以上的代码
.coupon {
	max-width: 100px;
	min-width: 100px;
}
// ... 省略以上的代码
.coupon {
	max-width: 100px;
	min-width: 100px;
}

同事发表评论:为什么要写max-widthmin-width,你这样和直接写width又有什么区别呢?

我:在flex布局下特殊情况直接写width是会有问题的。

同事:能有什么问题?

我:吧啦吧啦

之后同事是比较应付的说了哦,显然他不太愿意听我继续往下说,应付的回了一下我。之后也就没有再提这个了。

到底直接写 width 会有什么问题呢?

直接上一个案例吧~,一个很常见的一个布局,使用 flex 实现,效果大致如下(简单的画一下,大致意思应该能够表达到位了)

image-20220508135358722

我们给立即使用的按钮设置了宽度为 80px,在左边的内容不是特别多的时候是能够正常的显示的,按钮也是 80px,没有一点儿问题~

但是当左侧的内容一多起来,由于 flex 布局的”弹性“的原因,就会去挤压左侧立即使用按钮的宽度,就会造成页面的形变,如果线上这样展示,无疑就是一个 bug!如下:

image-20220508135929926

这种情况,我的解决方案就是,不再使用width来限定宽度,而是使用max-widthmin-width一起限制宽度,这时候即使左侧文案再长,也不会去挤压到右侧的宽度,或者说,挤压不动右侧的宽度!

image-20220508140150877

这个就是我解决flex布局宽度被挤压的问题的解决方式啦,就是使用max-widthmin-width一起配合使用,替换width

相信这个场景下应该还有其他的解决方案,如果有更好的解决方案的小伙伴们可以私信告诉我呀,或者直接分享出来,咱们大家一起学习一下~😋

小案例源码:传送门

感谢大家的观看,希望我的分享能够对你们有帮助!

最新解决方案

感谢一位老铁特地加我微信告诉了我一个更加优雅的实现方案:

image-20220525203212345

右侧按钮设置:flex-shrink:0 或者左侧文案区域设置: flex:1

亲测有效,而且更加的优雅,今后都会使用这个方式来解决这个问题了!

JS

优雅的处理浮点数的加减法

今天看到一个非常惊艳到我的一段代码,足足惊艳了半个多小时!代码如下:

js
export function formatFloat(num: number, accuracy = 2) {
  return +num.toFixed(accuracy)
}
export function formatFloat(num: number, accuracy = 2) {
  return +num.toFixed(accuracy)
}

这代码使用公司前辈写在公用工具库里的方法,第一眼看上去感觉也没什么了不起的,不就是toFixed方法可以四舍五入截取小数点位数嘛,但是我用了之后发现并没有那么简单:

大家可以先思考一下,大家可以想一下,这两种情况,返回值分别是什么:

  • formatFloat(1.333334)

    是1.33吗?🤔

  • formatFloat(1.2)

    1.20 ?🤔

  • formatFloat(0)

    0.00 ? 🤔

以上我想的结果,实际情况下它的结果分别是:1.33、1.2、0。😱

奇怪了,它的accuracy不是默认是2吗,肯定会有2位小数点截取的呀,为什么传0的时候它返回的不是0.00?🤔

我开始怀疑我对toFixed的理解,然后开始在控制台写了一些测试代码。

image-20220706165746996

发现确实是会有2位小数,研究了好一会儿也没有发现到底是为什么,于是我问了一下框架的作者。才知道原因...:😯

+num.toFixed()前面加了一个+toFixed的返回值是一个string类型,因为+的原因,会自动的将返回值转成一个number类型,'0.00'转正number类型就是0。

所以破案了🎉🎉,这段代码涉及隐式转换和执行顺序的知识。我理解的执行顺序是:(+num).toFixed(2),可真正的执行顺序是:+(num.toFixed(2))

image-20220706170214772

现在回想起来我会认为执行顺序是(+num).toFixed(2)是因为只有数值类型才会有toFixed方法,这样理解是能兼容一些字符串的数字,当num是字符串的'1.23'时,页面就不会报错了,可是确忽略了,这是TS,num已经给了是一个number类型。🧐

总结

被这段代码经验到之后,知道了其实涉及隐式转换和执行顺序的基础知识还是很重要的,还有就是TS的重要性,这就是一个TS非常给力的场景!💪🏻💪🏻

我终于搞懂了weakMap与Map💪🏻

二者对标的数据类型都是对象类型 => 存储的键值对

我们要理解,为什么Vue3响应式系统使用的是weakMap而不是Map!

优势

  • 有更加优雅&灵活的api用于增删改查

  • 不会触发原型链的查找

过去其实一直不知道map与weakMap的区别,或者说看过书面的官方解释,也背过面试题,知道weakMap存储的是弱类型的key,那么到底什么是弱类型(引用类型)的key呢?

什么是弱类型

我们都知道的字符串,数字这种属于值类型,弱类型我的简单理解就是、对象、函数。

所以基于这一点,我们就知道,weakMap的key只能是存弱类型,就不能存储字符串或者数字之类的作为key,而这个map可以

不会发生内存溢出

一个简单的例子过一下就能完全理解了!

js
const map = new Map()
  const wMap = new WeakMap()

  (() => {
    const foo = { foo: 1 }
    const bar = { bar: 2 }

    map.set(foo, 1)
    map.set(2, 1)
    wMap.set(bar, 1)
    // wMap.set(3, 1) // 报错,key必须是弱类型

    /**
     * WeakMap 是弱引用, 一旦表达式执行结束,垃圾回收就会把 bar 从内存中移除,所以无法从 weakMap中取到bar
     *  一旦被垃圾回收机制回收了,就无法获取到对应的 键和值了
     */
  })()

  console.log(map, map.keys()) // 依旧有办法获取 键和值
  console.log(wMap) // 已经无法获取键和值了,因为是弱引用,已经被垃圾回收机制所回收了
const map = new Map()
  const wMap = new WeakMap()

  (() => {
    const foo = { foo: 1 }
    const bar = { bar: 2 }

    map.set(foo, 1)
    map.set(2, 1)
    wMap.set(bar, 1)
    // wMap.set(3, 1) // 报错,key必须是弱类型

    /**
     * WeakMap 是弱引用, 一旦表达式执行结束,垃圾回收就会把 bar 从内存中移除,所以无法从 weakMap中取到bar
     *  一旦被垃圾回收机制回收了,就无法获取到对应的 键和值了
     */
  })()

  console.log(map, map.keys()) // 依旧有办法获取 键和值
  console.log(wMap) // 已经无法获取键和值了,因为是弱引用,已经被垃圾回收机制所回收了

总结

通过这个例子我算是比较清晰的理解了二者的区别了,已经在什么场景下对应应该使用哪种map来存储,比之前光看书去强行理解文字好多了。

知道了这个之后,set和weakSet也是一样的方式取理解即可!

最后应该可以很好回答上面的那个问题了,当一个响应式对象已经被垃圾回收机制所回收时,我们就不需要继续存储这个key-value了,这是一个性能优化的点,同时也能避免内存溢出!☀️