Live Note

Remain optimistic

起因

如果 wrapp 的 flex-direction 为 row 的时候,Text 内部不自动 wrap。还是测试拿给我看,才发现某些机型会存在这种问题。

开始以为是 Text 内部会根据flexbox而有不同的展现,但是翻阅官方文档:

The element is unique relative to layout: everything inside is no longer using the Flexbox layout but using text layout. This means that elements inside of a are no longer rectangles, but wrap when they see the end of the line.

Text 组件内部默认是 wrap 的,除非这一整个是一个超长的单词,否则就会在 white space 的时候自动 break 了。
如果给 wrapp 设置 wrap,那么整个 text 直接就 wrap 到下一行,icon 单独一行了。(这部分官方是有案例的,根据 Text 外部的 Container,wrap 也是不一样的)

好嘛,到底是什么东西导致的?为什么 flex-direction: row 就给我炸了?

原因: element 的宽度计算方式导致的

解决

官方的解释:每个 element 的 size 大致可以分为两种方式:

  • content-driven
  • parent-driven
  1. flex-direction: column 的时候,宽度首先由 content-driven,然后再由 parent-driven,高度直接由 content-driven,完美,一点问题没有。
  2. flex-direction: row 的时候:高度由 comtent-driven,宽度呢?那当然是 content-driven 啊! … 不好意思,Text 无法计算自己的 width,why?因为 Text 是 autosize 的!(也有意外情况,如果你把 Text 给 absolute 起来,那么就可以计算了)。所以此时的 Text 的 width,是由 parent-driven,也就是整个 wrapper 的宽度了。

解决方法也很简单,Text 上挂一个 flexShrink: 1,让它自己玩去吧。

  1. 从 Reflect 对象上可以获得语言内部的方法
  2. 修改某些 Object 方法的返回结果,让其变得更合理。比如 Object.defineProperty 在无法定义属性时会抛出一个错误,而 Reflect.defineProperty 则会返回 false
  3. 让 Object 操作都变成函数行为。
  4. 只要是 Proxy 对象的方法,就能在 Reflect 对象上找到相应的方法,无论 Proxy 怎么修改默认行为,总可以在 Reflect 上获取默认行为

静态方法

  • Reflect.apply(target, thisArg, args)
    等同于 Function.prototype.apply.call(func, thisArg, args),用于绑定 this 对象后执行给定函数。

  • Reflect.construct(target, args)
    等同于 new target(…args),提供了一种不使用 new 来调用构造函数的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    function Greeting(name) {
    this.name = name
    }
    //new 的写法
    const instance = new Greeting("张三")

    //Reflect.construct 写法
    const instance = Reflect.construct(Greeting, ["张三"])
Read more »

先行断言

  • lookahead assertionxy之前才匹配,格式为/x(?=y)/
  • negative lookahead assertion:只有x不在y之前才匹配,格式为/x(?!y)/
1
2
3
4
let str = 'now is 02:11:44'

/\d+(?=:)/.exec(str) // ['02']
/\d+(?!\.)/.exec(str) // ['0']
Read more »

1. Make Sure the compileSdkVersion is correct.

Cause if you don’t have the correct version of compileSdkVersion, the Context.RECEIVER_EXPORTED will not found.

build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
buildscript {
// ...
ext {
buildToolsVersion = "***"
minSdkVersion = ***
compileSdkVersion = 33
targetSdkVersion = 34
ndkVersion = "***"
googlePlayServicesAuthVersion = "***"
}
// ...
}

2. Rewrite the registerReceiver in MainApplication.java

Make sure the registerReceiver is override before the onCreate function.

MainApplication.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ...
@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) {
if (Build.VERSION.SDK_INT >= 34 && getApplicationInfo().targetSdkVersion >= 34) {
return super.registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
} else {
return super.registerReceiver(receiver, filter);
}
}

@Override
public void onCreate() {
// some code here
}
// ...

3. Clean Project and Rebuild the apk package

Reference here: React Native App Crashes — On upgrading to targetSdkVersion 34(Android 14)

Proxy 用于修改某些操作的默认行为,等同与在语言层面做出修改,属于一种 meta programming。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let obj = new Proxy(
{},
{
get: function (target, key, receiver) {
console.log(`getting ${key}`)
return Reflect.get(target, key, receiver)
},
set: function (target, key, receiver) {
console.log(`setting ${key}`)
return Reflect.set(target, key, receiver)
},
}
)
obj.count = 1
//setting count
obj.count
//getting count
Read more »