最近换了新工作终于凑齐一些有趣的bug与问题了, 比如在ts方面做了深入的研究, 国际化开发方面有了一些思考等等, 总之新的工作刚刚开始就收获满满, 有对'字节跳动'国际化业务感兴趣的同学可以把简历砸过来, 将来一起挑战各种有趣的难题。(当然除了国际化其它岗位我也可以内推的! )
小声说: 最近实在是好多事要忙, 像3d地球那个系列只能过段时间更新了...
当我们通过url来传递一些信息的时候, 可能会出现一些读取的问题,我们常用encodeURI
与encodeURIComponent
进行编码后再进行传递, 但是我发现项目中所有地方都用encodeURIComponent
, 为什么会这样这两种有什么区别?
因为encodeURI
并不会对;/?:@&=+$,#
之类的字符进行转移, 这就会导致某些特殊情况下解析uri出现问题(后端使用的语言不同导致解析方式不同), encodeURIComponent
会转义URI各个部分的标点符号比如常用的连接符&
与?
, 也就是说它转义的更彻底安全性更高, 所以建议尽可能使用encodeURIComponent
来处理。
image.png
来到国际化前端团队才学习到, 从左往右写的为"LTR", 从右往左写的为"RTL", 比如'希伯来语'、'阿拉伯语'等,如果你的公司要开发一款app提供给多个国家使用, 那就要考虑到有的国家书写文字是从右往左的, 并且很多图片也要从右往左展示, 比如把返回按钮放在右上方!
我们要做的就是文字书写的翻转、输入框的翻转、图标的自身翻转以及位置的镜像、但是某些图标不用反转比如 "时钟" 亦或者 30%
不用反转为%03
, 当然这些头疼的问题也是有成熟的解决方案的。
image.png
image.png
dir="rtl"
属性设置为body
元素加上属性dir="rtl"
, 浏览器就可以自动翻转了, 没试过的快试试很好玩的。
缺点也很明显, 就比如我们的css属性margin: left;
仍然是作用于左边。
rtlcss
rtlcss
的官网, 他的实现思路就是配合rtl
属性使用, 将页面上的left
相关属性都转为right
属性, 核心思想就是某些属性的全局替换。
公司内部有一个库可以把后端的rpc接口规范直接转成ts规范供前端使用, 但是突然有一天出现了类型错误, 比如后端规定返回参数为code
数字类型, msg
为字符串类型, 那么就会生成如下文件:
export type XxxxApi = {
code: number;
msg: string;
}
但是一天夜里后端返回的code
对应的类型竟然变成了string
, 我和同事查看了后端同学的代码, 定义的也的确是int
类型, 但不过不是int32
而是int64
, 原来是因为js
的数字的极限是2的53次方:
image.png
所以才采用string
的方式来表达int64
这个数据类型, 后端同学将类型改为int32
就没问题了, 当然啦后端同学擅自改类型不通知我们要提出批评。
* bug 场景 明明开发时候好好的, 但为什么打包之后就会出现各种错误, 比如样式丢失, 这里说下原因之一:
很久之前的某天我把开发好的前端项目代码发布到了服务器上, 在我本地访问时样式很完美, 但是当我通过测试环境url打开这个项目的时候, 竟然表格样式有些崩坏宽高与我本地的不一样, 但是我没有想明白bug的原因, 就去与 '同学a' 交流为什么出现这种现象。
'同学a' 说是因为用户的浏览器和我不一样导致的, 可是我就是用户, 开发就在我的浏览器上也是我用浏览器访问的测试环境, 但是是同一个浏览器, 但'a同学'坚持说不可能发生这种状况, 我就给他演示了一遍从开发到发布到测试环境的全流程, 看到bug确实再次出现的他说是我'人品'的问题.... (后来是通过改了一些css
的写法解决的)
我对这个事情印象还是比较深刻的, 但在今年的某一天, 我在配置webpack
的时候突然发现了一个问题点, 比如postcss
在配置的时候会有一个设置, 在development
与production
两种模式下分别兼容到主流浏览器什么版本, 那这里其实就很可能是问题所在, 因为针对开发与打包进行了不同的翻译, 这就会导致无法预期的错误产生, 虽然已经不在那家公司了当年的代码已经找不到了, 但想到这点还是会很强烈的感觉到之前毫无头绪的问题有了一个解决方向!
要想学习唤起app就要先知道Schema
是什么, 我通俗点讲一下, 就是你下载到系统里的每个app其实都可以注册一个属于它的url地址, 这个地址你可以理解为就是Schema
。
而我们唤起某个app就可以利用这个"Schema 地址"。
假设联系人的电话号码为 18200000000, 并且为中国的号码区号为(86)
- window.open("https://wa.me/8618200000000") 会闪屏
- 或
- window.open("https://api.whatsapp.com/send/?phone=8618200000000")
image.png
不建议用window.location.href
的方式跳转, 他会导致闪屏。
image.png
mailto是一种类似http的url协议, 但它属于本地协议(本地协议比较典型的还有file), 也就是不需要连接网络就可以解析的协议, mailto的功能是唤起默认邮箱。
指定收件人
- window.location.href="mailto: xxx@qqqqq.com"
如果为多个人发邮件则 ',' 分割
- window.location.href="mailto: xxx1@qqqqq.com, xxx2@qqqqq.com"
如果要添加主题, 增加subject参数
- window.location.href=`mailto: xxx@qqqqq.com?subject=${encodeURIComponent("我是主题xxx")}`
如果要添加主题, 增加body参数
- window.location.href=`mailto: xxx@qqqqq.com?subject=${encodeURIComponent("我是主题xxx")}&body=${encodeURIComponent('我是内容xxx')}`
image.png
经常出现React.Fc
这个函数, 比如我不使用React.Fc
来处理组件的函数, 则在组件里面使用props.children
会报错, 我们一起进入源码分析一下。
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
// 第一句
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
FC
这个type
接收一个参数P
, 默认值为空对象, 而这个P
。FunctionComponent
就是个过度的名称而已, 可以认为FC
就是FunctionComponent
。PropsWithChildren<P>
类型, 第二个参数可有可无, 有则为任意类型, 返回React的dom或者返回null
。我们追查一下PropsWithChildren
type PropsWithChildren<P> = P & { children?: ReactNode | undefined };
只是将传入的P的类型与{ children?: ReactNode | undefined }
合并而已, 看到这里我们就明白了, 其实用React.FC
包裹一下是可以帮助ts
推导出props
身上可能有children
属性。
rematch官网;
rematch
是对Redux
的二次封装, 而RematchRootState
是rematch
导出的一个ts推导函数, RematchRootState
到底做了什么令程序员脱发的操作...
项目里使用了这个RematchRootState
之后, 发现某些类型推导出来never
类型如图所示:
image.png
export type RematchRootState<M> = ExtractRematchStateFromModels<M>
export type ExtractRematchStateFromModels<M> = {
[modelKey in keyof M]: M[modelKey] extends ModelConfig ? M[modelKey]['state'] : never
}
1 . 在使用RematchRootState
时我们使用typeof的形式导出了一个ts类型, typeof在ts里面使用就不是js里面的意义了:
Xxx<typeof {name:'金毛', age:9}>
// 此处就相当于:
Xxx<typeof {name:string, age:number}>
2 . [modelKey in keyof M]
循环M
对象里面所有的key值, 每次循环时命名为modelKey。
3 . M[modelKey]
就是取出对应的值, 这里特指ts
里面的类型值。
4 . M[modelKey] extends ModelConfig ? M[modelKey]['state'] : never
, 也就是每次取出'值', 并且此'值'符合ModelConfig类型
的话则返回M[modelKey]['state']
的类型, 否则返回never
, 这里的extends
你可以理解为is
用来判断某个值是不是符合规范的, 以后文章还会涉及extends
的其他用法。
至此我们已经明白了, 问题一定出在M[modelKey]
的类型未符合 ModelConfig
的类型规范导致的返回的never
, 那ModelConfig
又是什么规范那?
export interface ModelConfig<S = any, SS = S, K extends string = string> {
name?: string
state: S
baseReducer?: (state: SS, action: Action) => SS
reducers?: ModelReducers<S>
effects?:
| ModelEffects<any>
| (<M extends Models<K> | void = void>(dispatch: RematchDispatch<M>) => ModelEffects<any>)
}
ModelConfig
时什么参数都没传, 则使用默认值。name
属性我们赋予了number
类型时会导致错误。state
对应的S
类型, 也就是默认的any
任何类型都可以。baseReducer
的参数不符合规范, 或是返回值不符合规范时。effects
要单独拿出来讲第一个: effects = ModelEffects<any>
type ModelEffects<S> = {
[key: string]: ( this: { [key: string]: (payload?: any, meta?: any) => Action<any, any> },payload: any,rootState: S) => void
}
export type Action<P = any, M = any> = {
type: string,
payload?: P,
meta?: M,
}
[key: string]
这种写法意思就是取出里面所有的项进行循环。ModelEffects
每一项都为函数, 并且没有返回值。ModelEffects
对象的每个函数的第一个参数为一个对象, 这个对象里面值都为函数, 并且返回值为Action<any, any>
。ModelEffects
对象的每个函数的第二个参数为任意类型。ModelEffects
对象的每个函数的第三个参数为rootState: S
S类型, S则是我们上一步传入进来的, 也就是any
。第二个:
effects = (<M extends Models<K> | void = void>(dispatch: RematchDispatch<M>)
=> ModelEffects<any>)
M
是新定义的一个泛型, 它符合Models<K>
的规范, 如果不符合的话就为void
类型。K
就是上面默认的string
(写到这里我都感觉好麻烦)。这里是Models
的类型:
export type Models<K extends string = string> = {
[key in K]: ModelConfig
}
每项都是ModelConfig
, 而ModelConfig
我们上面已经讲过啦。
3 . 这个函数接收的第一个参数dispatch
要符合类型RematchDispatch<M>
, 这里就不再扩展了, 往下还有特别深:
export type RematchDispatch<M = void> =
ExtractRematchDispatchersFromModels<M> &
(RematchDispatcher | RematchDispatcherAsync) &
(Redux.Dispatch<any>)
可以看出来, 这个参数的类型我们用Redux.Dispatch<any>
来定义就没问题的。
4 . 返回值必须为: ModelEffects<any>
这个我们刚才也讲过了。
正确的用法可以是如下的样子:
effects: (dispatch: Redux.Dispatch) => ({
async FnXxx(_: any, state: RootState) {
console.log(state.xxx.xxxList)
},
}),
总结一句话就是"读这代码好心累"!
假设当前我有这样一个type
:
type Obj = {
getX: (a: string, c: boolean) => void;
getN: (a: number) => void;
};
而我希望将这个type
处理成下面这个样子:
type Obj = {
getX: (s: string[], a: string, c: boolean) => void;
getN: (s: string[], a: number) => void;
};
这里的关键点就是取到函数返回值的类型, 以及函数参数的类型集合, 实现代码如下:
type Obj2<T> = {
[Key in keyof T]: T[Key] extends (...arg: any) => any
?(s: string[], ...arg: Parameters<T[Key]>) => ReturnType<T[Key]>
: T[Key];
};
T
里面所有的值。T[Key]
不满足(...arg: any) => any
则不处理, 因为T[Key]
可能不是函数类型。T[Key]
为函数类型, 则第一个参数为s: string[]
。...arg
为后续参数类型, Parameters<>
为自带方法, 可以推导出函数的所有参数组成的数组的类型。ReturnType<>
为自带方法, 可以推导出函数的返回值的类型。使用方法就是:
type NewObj = Obj2<Obj1>
假设当前我有这样一个type
:
type Obj = {
getX: (a: string, c: boolean) => void;
getN: (a: number) => void;
};
而我希望将这个type
处理成下面这个样子:
type Obj = {
getX: (c: boolean) => void;
getN: () => void;
};
这里的关键点就是, 在ts里如何剔除数组的第一个元素, 并使用剩下的元素组成数组返回出来:
type Obj2<T> = {
[Key in keyof T]: T[Key] extends (s: any, ...arg: infer Arg) => any
? (...arg: Arg) => ReturnType<T[Key]>
: T[Key];
};
(s: any, ...arg: infer Arg) => any
, 这里是核心, 将函数处理第一个参数以外的参数单独拿出来命名为Arg
, 然后使用Arg
来定义函数的参数。infer
是ts内置的关键字, 有点类似js中的var
, 他可以定义一个变量。使用方法就是:
type NewObj = Obj2<Obj1>
gzip
压缩可以用什么替代之前我一直认为gzip压缩是当前最好的前端压缩方案, 但是其压缩方案并不唯一并且有着很多分类, 压缩方式被"无状态压缩", "有状态压缩"。
无状态意味着它看到的任何大块数据,它都会压缩,而不依赖于以前的输入。速度更快但通常压缩程度更低;有状态压缩查看以前的数据来决定如何压缩当前数据,但速度较慢但压缩好得多。
比如zstd压缩属于有状态压缩, 会根据压缩过程中遇到的重复代码块生成字典, 再遇到相同的代码用字典里对应的key来标识即可
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/9ozYH4N1vnoKaI0VnsgSAw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。