React Native工程中TSLint静态检查工具的探索之路

  建立的代码规范没人遵守,项目中遍地风格迥异的代码,你会不会抓狂?
  
  通过测试用例的程序还会出现Bug,而原因仅仅是自己犯下的低级错误,你会不会抓狂?
  
  某种代码写法存在问题导致崩溃时,只能全工程检查代码,这需要人工花费大量时间Review代码,你会不会抓狂?
  
  以上这些问题,可以通过静态检查有效地缓解!
  
  静态检查(Static Program Analysis)主要是以不运行程序的方式对于程序源代码进行检查分析的技术,而与之相反的就是动态检查(Dynamic Program Analysis),通过实际运行程序输入测试数据产生预期结果的技术。通过代码静态检查,我们可以快速定位代码的错误与缺陷,可以减少逐行阅读代码浪费的时间,可以(根据需要)快速扫描代码中可能存在的漏洞等。代码静态检查可以在代码的规范性、安全性、可靠性、可维护性等方面起到重要作用。
  
  在客户端中,Android可以使用CheckStyle、Lint、Findbugs、PMD等工具,iOS可以使用Clang Static Analyzer、OCLint等工具。而在React Native的开发过程中,针对于JavaScript的ESLint,与TypeScript的TSLint,则成为了主要代码静态检查的工具。本文将按照使用TSLint的原因、使用TSLint的方法、自定义TSLint的步骤进行探究分析。
  
  一、使用TSLint的原因
  
  在客户端团队进入React Native项目的开发过程中,面临着如下问题:
  
  由于大家从客户端转入到React Native开发过程中,容易出现低级语法错误;
  
  开发者之前从事Android、iOS、前端等工作,因此代码风格不同,导致项目代码风格不统一;
  
  客户端效果不一致,有可能Android端显示正常、iOS端显示异常,或者相反的情况出现。
  
  虽然以上问题可以通过多次不断将雷点标记出,并不断地分享经验与强化代码Review过程等方式来进行缓解,但是仍面临着React Native开发者掌握的技术水平千差万别,知识分享传播的速度缓慢等问题,既导致了开发成本的不断增加和开发效率持续低下的问题,还难以避免一个坑被踩了多次的情况出现。这时急需一款可以满足以下目标的工具:
  
  可检测代码低级语法错误;
  
  规范项目代码风格;
  
  根据需要可自定义检查代码的逻辑;
  
  工具使用者可以“傻瓜式”的接入部署到开发IDE环境;
  
  可以快速高效地将检查工具最新检查逻辑同步到开发IDE环境中;
  
  对于检查出的问题可以快速定位。
  
  根据上述要求的描述,静态检查工具TSLint可以较为有效地达成目标。
  
  二、TSLint介绍
  
  TSLint是硅谷企业Palantir的一个项目,它是一款可以检查TypeScript代码可读性、可维护性以及功能性错误的静态检查工具,当前许多编辑器(Editors)和构建系统(Build Systems)支持这一工具,同时支持自定义编写Lint规则、配置、格式化等。
  
  当前TSLint已经包含了上百条规则,这些规则构筑了当前TSLint检查的基础。在代码开发阶段中,通过这些配置好的规则可以给工程一个完整的检查,并随时可以提示出可能存在的问题。本文内容参考了TSLint官方文档https://palantir.github.io/tslint/。
  
  2.1 TSLint常见规则
  
  以下规则主要来源于TSLint规则,是某些规则的简单介绍。
  
  TSLint规则示例
  
  2.2 常用TSLint规则包
  
  上述2.1所列出的规则来源于Palantir官方TSLint规则。实际还有多种,可能会用到的有以下:
  
  TSLint规则示例
  
  我们在项目的规则配置过程中,一般采用上述规则包其中一种或者若干种同时配置,那如何配置呢?请看下文。
  
  三、如何进行TSLint规则配置与检查
  
  首先,在工程package.json文件中配置TSLint包:
  
  TSLint规则示例
  
  在根目录中的tslint.json文件中可以根据需要配置已有规则,例如:
  
  TSLint规则示例
  
  其中extends数组内放置继承的TSLint规则包,上图包括了airbnb配置的规则包、tslint-react的规则包,而rules用于配置规则的开关。
  
  TSLint规则目前只有true和false的选项,这导致了结果要么正常,要么报错ERROR,而不会出现WARNING等警告。
  
  有些时候,虽然配置某些规则开启,但是某个文件内可能会关闭某些甚至全部规则检查,这时候可以通过规则注释来配置,如:
  
  /* tslint:disable */
  
  上述注释表示本文件自此注释所在行开始,以下的所有区域关闭TSLint规则检查。
  
  /* tslint:enable */
  
  上述注释表示本文件自此注释所在行开始,以下的所有区域开启TSLint规则检查。
  
  /* tslint:disable:rule1 rule2 rule3... */
  
  上述注释表示本文件自此注释所在行开始,以下的所有区域关闭规则rule1 rule2 rule3...的检查。
  
  /* tslint:enable:rule1 rule2 rule3... */
  
  上述注释表示本文件自此注释所在行开始,以下的所有区域开启规则rule1 rule2 rule3...的检查。
  
  // tslint:disable-next-line
  
  上述注释表示此注释所在行的下一行关闭TSLint规则检查。
  
  someCode(); // tslint:disable-line
  
  上述注释表示此注释所在行关闭TSLint规则检查。
  
  // tslint:disable-next-line:rule1 rule2 rule3...
  
  上述注释表示此注释所在行的下一行关闭规则rule1 rule2 rule3...的检查检查。
  
  以上配置信息,这里具体参考了https://palantir.github.io/tslint/usage/rule-flags/。
  
  3.1 本地检查
  
  在完成工程配置后,需要下载所需要依赖包,要在工程所在根目录使用npm install命令完成下载依赖包。
  
  IDE环境提示
  
  在完成下载依赖包后,IDE环境可以根据对应配置文件进行提示,可以实时地提示出存在问题代码的错误信息,以VSCode为例:
  
  TSLint规则示例
  
  本地命令检查
  
  VSCode目前还有继续完善的空间,如果部分文件未在窗口打开的情况下,可能存在其中错误未提示出的情况,这时候,我们可以通过本地命令进行全工程的检查,在React Native工程的根目录下,通过以下命令行执行:
  
  tslint --project tsconfig.json --config tslint.json
  
  (此命令如果不正确运行,可在之前加入./node_modules/.bin/)即为:
  
  ./node_modules/.bin/tslint --project tsconfig.json --config tslint.json
  
  从而会提示出类似以下错误的信息:
  
  src/Components/test.ts[1, 7]: Class name must be in pascal case
  
  3.2 在线CI检查
  
  本地进行代码检查的过程也会存在被人遗忘的可能性,通过技术的保障,可以避免人为遗忘,作为代码提交的标准流程,通过CI检查后再合并代码,可以有效避免代码错误的问题。CI系统可以为理解为一个云端的环境,环境配置与本地一致,在这种情况下,可以生成与本地一致的报告,在美团内部可以使用基于Jenkins的Castle CI系统, 生成结果与本地结果一致:
  
  TSLint规则示例
  
  3.3 其他方式
  
  代码检查不止局限上述阶段,在代码commit、pull request、打包等阶段均可触发。
  
  代码commit阶段,通过Hook方式可以触发代码检查,可以有效地将在线CI检查阶段强制提前,基本保证了在线CI检查的完全正确性。
  
  代码pull request阶段,通过在线CI检查可以触发代码检查,可以有效保证合入分支尤其是主分支的正确性。
  
  代码打包阶段,通过在线CI检查可以触发代码检查,可以有效保证打包代码的正确性。
  
  四、自定义编写TSLint规则
  
  4.1 为什么要自定义TSLint规则
  
  当前的TSLint规则虽然涵盖了比较普遍问题的一些代码检查,但是实践中还是存在一些问题的:
  
  团队中的个性化需求难以满足。例如,saga中的异步函数需要在最外层加try-catch,且catch块中需要加异常上报,这个明显在官方的TSLint规则无法实现,为此需要自定义的开发。
  
  官方规则的开启与配置不符合当前团队情况。
  
  基于以上原因其他团队也有自定义TSLint的先例,例如上文提到的tslint-microsoft-contrib、tslint-eslint-rules等。
  
  4.2 自定义规则步骤
  
  那自定义TSLint大概需要什么步骤呢,首先规则文件根据规范进行按部就班的编写规则信息,然后根据代码检查逻辑对语法树进行分析并编写逻辑代码,这也是自定义规则的核心部分了,最后就是自定义规则的使用了。
  
  TSLint规则示例
  
  自定义规则的示例直接参考官方的规则是最直接的,我们能这里参考一个比较简单的规则"class-name"。
  
  "class-name"规则上文已经提到,它的意思是对类命名进行规范,当团队中类相关的命名不规范,会导致项目代码风格不统一甚至其他出现的问题,而"class-name"规则可以有效解决这个问题。我们可以看下具体的源码文件:https://github.com/palantir/tslint/blob/master/src/rules/classNameRule.ts。
  
  然后将分步对此自定义规则进行讲解。
  
  TSLint规则示例
  
  第一步,文件命名
  
  TSLint规则示例
  
  规则命名必须是符合以下2个规则:
  
  驼峰命名。
  
  以‘Rule‘为后缀。
  
  第二步,类命名
  
  规则的类名是Rule,并且要继承Lint.Rules.AbstractRule这个类型,当然也可能有继承TypedRule这个类的时候,但是我们通过阅读源码发现,其实它也是继承自Lint.Rules.AbstractRule这个类。
  
  TSLint规则示例
  
  第三步,填写metadata信息
  
  metadata包含了配置参数,定义了规则的信息以及配置规则的定义。
  
  ruleName 是规则名,使用烤串命名法,一般是将类名转为烤串命名格式。
  
  description 一个简短的规则说明。
  
  descriptionDetails 详细的规则说明。
  
  rationale 理论基础。
  
  options 配置参数形式,如果没有可以配置为null。
  
  optionExamples 参数范例 ,如没有参数无需配置。
  
  typescriptOnly true/false 是否只适用于TypeScript。
  
  hasFix true/false 是否带有修复方式。
  
  requiresTypeInfo 是否需要类型信息。
  
  optionsDescrition options的介绍。
  
  type 规则的类型。
  
  规则类型有四种,分别为:"functionality"、"maintainability"、"style"、"typescript"。
  
  functionality : 针对于语句问题以及功能问题。
  
  maintainability:主要以代码简洁、可读、可维护为目标的规则。
  
  style:以维护代码风格基本统一的规则。
  
  typescript:针对于TypeScript进行提示。
  
  第四步,定义错误提示信息
  
  TSLint错误信息
  
  这个主要是在检查出问题的时候进行提示的文字,并不局限于使用一个静态变量的形式,但是大部分官方规则都是这么编写,这里对此进行介绍,防止引起歧义。
  
  第五步,实现apply方法
  
  apply主要是进行静态检查的核心方法,通过返回applyWithFunction方法或者返回applyWithWalker来进行代码检查,其实applyWithFunction方法与applyWithWalker方法的主要区别在于applyWithWalker可以通过IWalker实现一个自定义的IWaker类,区别如下:
  
  TSLint
  
  其中实现IWaker的抽象类AbstractWalker里面也继承了WalkContext,
  
  TSLint
  
  而这个WalkContext就是上面提到的applyWithFunction的内部实现类。
  
  TSLint
  
  第六步,语法树解析
  
  无论是applyWithFunction方法还是applyWithWalker方法中的IWaker实现都传入了sourceFile这个参数,这个相当于文件的根节点,然后通过ts.forEachChild方法遍历整个语法树节点。
  
  这里有两个查看AST语法树的工具:
  
  AST Explorer: https://astexplorer.net/
  
  对应源码: https://github.com/fkling/astexplorer
  
  TypeScript AST Viewer: https://ts-ast-viewer.com/
  
  对应源码: https://github.com/dsherret/ts-ast-viewer
  
  AST Explorer
  
  优点:
  
  在AST Explorer可以高亮显示所选中代码对应的AST语法树信息。
  
  缺点:
  
  不能选择对应版本的解析器,导致显示的语法树代码版本固定。
  
  TSLint
  
  语法树显示的信息相对较少。
  
  TSLint
  
  TypeScript AST Viewer
  
  优点:
  
  解析器对应版本可以动态选择:
  
  TSLint
  
  语法树显示的信息不仅显示对应的数字代码,还可为对应的实际信息:
  
  TSLint
  
  每个版本对应对kind信息数值可能会变动,但是对应的枚举名字是固定的,如下图:
  
  TSLint
  
  从而这个工具可以避免频繁根据其数值查找对应信息。
  
  缺点: 不能高亮显示代码对应的AST语法树区域,定位效率较低。
  
  综上,通过同时使用上述两个工具定位分析,可以有效地提高分析效率。
  
  第七步,检查规则代码编写
  
  通过ts.forEachChild方法对于语法树所有的节点进行遍历,在遍历的方法里可以实现自己的逻辑,其中节点的类为ts.Node:
  
  TSLint
  
>>> import jwt
>>> encoded_jwt = jwt.encode({‘username‘:‘运维咖啡吧‘,‘site‘:‘https://ops-coffee.cn‘},‘secret_key‘,algorithm=‘HS256‘)
这里传了三部分内容给JWT,

第一部分是一个Json对象,称为Payload,主要用来存放有效的信息,例如用户名,过期时间等等所有你想要传递的信息

第二部分是一个秘钥字串,这个秘钥主要用在下文Signature签名中,服务端用来校验Token合法性,这个秘钥只有服务端知道,不能泄露

第三部分指定了Signature签名的算法

查看生成的Token
>>> print(encoded_jwt)
b‘eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Ilx1OGZkMFx1N2VmNFx1NTQ5Nlx1NTU2MVx1NTQyNyIsInNpdGUiOiJodHRwczovL29wcy1jb2ZmZWUuY24ifQ.fIpSXy476r9F9i7GhdYFNkd-2Ndz8uKLgJPcd84BkJ4‘
JWT生成的Token是一个用两个点(.)分割的长字符串

点分割成的三部分分别是Header头部,Payload负载,Signature签名:Header.Payload.Signature

JWT是不加密的,任何人都可以读的到其中的信息,其中第一部分Header和第二部分Payload只是对原始输入的信息转成了base64编码,第三部分Signature是用header+payload+secret_key进行加密的结果

可以直接用base64对Header和Payload进行解码得到相应的信息

>>> import base64
>>> base64.b64decode(‘eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9‘)
b‘{"typ":"JWT","alg":"HS256"}‘

>>> base64.b64decode(‘eyJ1c2VybmFtZSI6Ilx1OGZkMFx1N2VmNFx1NTQ5Nlx1NTU2MVx1NTQyNyIsInNpdGUiOiJodHRwczovL29wcy1jb2ZmZWUuY24ifQ==‘)
# 这里最后加=的原因是base64解码对传入的参数长度不是2的对象,需要再参数最后加上一个或两个等号=
因为JWT不会对结果进行加密,所以不要保存敏感信息在Header或者Payload中,服务端也主要依靠最后的Signature来验证Token是否有效以及有无被篡改

解密Token
>>> jwt.decode(encoded_jwt,‘secret_key‘,algorithms=[‘HS256‘])
{‘username‘: ‘运维咖啡吧‘, ‘site‘: ‘https://ops-coffee.cn‘}
服务端在有秘钥的情况下可以直接对JWT生成的Token进行解密,解密成功说明Token正确,且数据没有被篡改

当然我们前文说了JWT并没有对数据进行加密,如果没有secret_key也可以直接获取到Payload里边的数据,只是缺少了签名算法无法验证数据是否准确,pyjwt也提供了直接获取Payload数据的方法,如下

>>> jwt.decode(encoded_jwt, verify=False)
{‘username‘: ‘运维咖啡吧‘, ‘site‘: ‘https://ops-coffee.cn‘}
Django案例
Django要兼容session认证的方式,还需要同时支持JWT,并且两种验证需要共用同一套权限系统,该如何处理呢?我们可以参考Django的解决方案:装饰器,例如用来检查用户是否登录的login_required和用来检查用户是否有权限的permission_required两个装饰器,我们可以自己实现一个装饰器,检查用户的认证模式,同时认证完成后验证用户是否有权限操作

于是一个auth_permission_required的装饰器产生了:

from django.conf import settings
from django.http import JsonResponse
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied

UserModel = get_user_model()

def auth_permission_required(perm):
def decorator(view_func):
def _wrapped_view(request, *args, **kwargs):
# 格式化权限
perms = (perm,) if isinstance(perm, str) else perm

if request.user.is_authenticated:
# 正常登录用户判断是否有权限
if not request.user.has_perms(perms):
raise PermissionDenied
else:
try:
auth = request.META.get(‘HTTP_AUTHORIZATION‘).split()
except AttributeError:
return JsonResponse({"code": 401, "message": "No authenticate header"})

# 用户通过API获取数据验证流程
if auth[0].lower() == ‘token‘:
try:
dict = jwt.decode(auth[1], settings.SECRET_KEY, algorithms=[‘HS256‘])
username = dict.get(‘data‘).get(‘username‘)
except jwt.ExpiredSignatureError:
return JsonResponse({"status_code": 401, "message": "Token expired"})
except jwt.InvalidTokenError:
return JsonResponse({"status_code": 401, "message":www.gcyl158.com "Invalid token"})
except Exception as e:
return JsonResponse({"status_code": 401, "message": "Can not get user object"})

try:
user = UserModel.objects.get(username=username)
except UserModel.DoesNotExist:
return JsonResponse({"status_www.gcyL157.com code": 401, "message"www.haitianguo.cn : "User Does not exist"})

if not user.is_active:
return JsonResponse({"status_code": 401, "message": "User inactive or deleted"})

# Token登录的用户判断是否有权限
if not user.has_perms(perms):
return JsonResponse({"status_code": 403, "message"www.078881.cn :www.fengshen157.com/ "PermissionDenied"})
else:
return JsonResponse({"status_code": 401, "message": "Not support auth type"})

return view_func(request, *args, **kwargs)

return _wrapped_view

  其中kind为当前节点的类型,当然Node是所有节点的基类,它的实现还包括Statement、Expression、Declaration等,回到开头这个"class-name"规则,我们的所有声明类主要是class与interface关键字,分别对应ClassExpression、ClassDeclaration、InterfaceDeclaration, 我们可以通过上步提到的AST语法树工具,在语法树中看到其为一一对应的。
  
  TSLint
  
  在规则代码中主要通过isClassLikeDeclaration、isInterfaceDeclaration这两个方法进行判断的。
  
  TSLint
  
  其中isClassLikeDeclaration、isInterfaceDeclaration对应的方法我们可以在node.js文件中找到:
  
  TSLint
  
  TSLint
  
  判断是对应的类型时,调用addFailureAtNode方法把错误信息和节点传入,当然还可以调用addFailureAt、addFailure方法。
  
  TSLint
  
  最终这个规则编写结束了,有一点再次强调下,因为每个版本所对应的类型代码可能不相同,当判断kind的时候,一定不要直接使用各个类型对应的数字。
  
  第八步,规则配置使用
  
  完成规则代码后,是ts后缀的文件,而ts规则文件实际还是要用js文件,这时候我们需要用命令将ts转化为js文件:
  
  tsc ./src/*.ts --outDir dist
  
  将ts规则生成到dist文件夹(这个文件夹命名用户自定),然后在tslint.json文件中配置生成的规则文件即可。
  
  TSLint
  
  之后在项目的根目录里面,使用以下命令既可进行检查:
  
  tslint --project tsconfig.json --config tslint.json
  
  同时为了未来新增规则以及规则配置的更好的操作性,建议可以封装到自己的规则包,以便与规则的管理与传播。
  
  总结
  
  TSLint的优点:
  
  速度快。相对于动态代码检查,检查速度较快,现有项目无论是在本地检查,还是在CI检查,对于由十余个页面组成的React Native工程,可以在1到2分钟内完成;
  
  灵活。通过配置规则,可以有效地避免常见代码错误与潜在的Bug;
  
  易扩展。通过编写配置自定义规则,可以及时准确快速查找出代码中特定风险点。
  
  TSLint缺点:
  
  规则的结果只有对与错两种等级结果,没有警告等级的的提示结果;
  
  无法直接报告规则报错数量,只能依赖其他手段统计;
  
  TSLint规则针对于当前单一文件可以有效地通过语法树进行分析判定,但对于引用到的其他文件中的变量、类、方法等,则难以通过AST语法树进行判定。
  
  使用结果及分析
  
  在美团,有十余个页面的单个工程首次接入TSLint后,检查出的问题有近百条。但是由于开启的规则不同,配置规则包的差异,检查后的数量可能为几十条到几千条甚至更多。现在已开发十余条自定义规则,在单个工程内,处理优化了数百处可能存在问题的代码。最终TSLint接入了相关React Native开发团队,成为了代码提交阶段的必要步骤。
  
  通过团队内部的验证,文章开头遇到的问题得到了有效地缓解,目标基本达到预期。TSLint在React Native开发过程中既保证了代码风格的统一,又保证了React Native开发人员的开发质量,避免了许多低级错误,有效地节省了问题排查和人员沟通的成本。
  
  同时利用自定义规则,能够将一些兼容性问题在内的个性化问题进行总结与预防,提高了开发效率,不用花费大量时间查找问题代码,又避免了在一个问题上跌倒多次的情况出现。对于不同经验的开发者而言,不仅可以进行友好的提示,也可以帮助快速地定位问题,将一个人遇到的经验教训,用极低的成本扩散到其他团队之中,将开发状态从“亡羊补牢”进化到“防患未然”。

原文地址:https://www.cnblogs.com/qwangxiao/p/10305899.html

时间: 2024-09-30 03:43:59

React Native工程中TSLint静态检查工具的探索之路的相关文章

项目架构基础之二 ---- 工程中创建静态库文件(.a)库文件

步骤1.创建工程HLStaticTest 步骤2.创建静态库文件 步骤3. 关闭HLStatic,回到HLStaticTest Targets - >Build Phases ->Link Binary With Libraries 然后进入到  Targets -> Build Setting ->Header Search Paths 步骤 4. 进入AppDelegate 工程中创建静态库文件(.a)库文件 成功 版权声明:本文为博主原创文章,未经博主允许不得转载.

Andoid java文件中的Log检查工具

AndroidLogChecker 由于发布软件版本的时候我们需要把Log注释掉,此工具可以检查java类中的Log所在行以及是否已经注释. Github: https://github.com/cumtkangyi/AndroidLogChecker package com.leo.kang.tools; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; impor

Shell学习---Shell脚本的静态检查工具shellcheck

Shell脚本的静态检查工具shellcheck ubuntu下 apt install shellcheck ,即可安装shellcheck.写完shell脚本,记得用它检查一下,能给你点建议的.要检查现有项目的所有的脚本, find your_project_folder -name "*.sh" | xargs -i shellcheck {} 即可实现批量检查 原文地址:https://www.cnblogs.com/ftl1012/p/9568635.html

C/C++代码静态检查工具Cppcheck在VS2008开发环境中的安装配置和使用

Cppcheck is an analysis tool for C/C++code. Unlike C/C++ compilers and many other analysis tools, it doesn’t detect syntax errors. Cppcheck only detects the types of bugs that the compilers normally fail to detect. The goal is no false positives. Cpp

四种java代码静态检查工具

[转载]常用 Java 静态代码分析工具的分析与比较 转载自 开源中国社区 http://www.oschina.net/question/129540_23043 1月16日厦门 OSC 源创会火热报名中,奖品多多哦 »   简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBugs,PMD,Jtest),最后从功能.特性等方面对它们进行分析和比较,希望能够帮助 Java 软件开发人员了解静态代码

Python静态检查工具

Python是一门动态语言.在给python传参数的时候并没 有严格的类型限制.写python程序的时候,发现错误经常只能在执行的时候发现.有一些 错误由于隐藏的比较深,只有特定逻辑才会触发,往往导致需要花很多时间才能将语法错误慢慢排查出来.其实有一些错误是很明显的,假如能在写程序的时候发现这些错误,就能提高工作效率. 注:习惯了C/C++等编译语言,使用像Python这种动态语言,总有点不放心,特别是搭建比较大的系统的时候.Python静态语法检查工具就出现了. Pyflakes(错误检查利器

React native开发中常见的错误

react native环境搭建请移步:react native环境搭建 这里说说react native创建完成之后,运行中出现的常见问题, 问题1: java.lang.RuntimeException: SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable. 这个是原因是工程找不到我们的and

组装者模式在React Native项目中的一个实战案例

前言 在实际的开发中,如果遇到多个组件有一些共性,我们可以提取一个BaseItem出来,然后在多个组件中进行复用,一种方式是通过继承的方式,而今天我们要说的是另一种方式--组装者模式. 什么是组装者模式? 就是在一个类中封装一些共有特性,然后使得在使用的组件中,可以动态的去添加一些属性或者行为,相比较于继承来说,组装者模式会更加的灵活. 实例演示 /** * AboutCommon.js * 组装者模式 模仿一些生命周期函数 */ export default class AboutCommon

nginx下使用asan和valgrind两个静态检查工具

1.valgrind valgrind安装:参考:https://blog.csdn.net/justheretobe/article/details/52986461 wegit:http://valgrind.org/downloads/valgrind-3.12.0.tar.bz2 tar -jxvf valgrind-3.12.0.tar.bz2 cd valgrind-3.12.0 ./configure make sudo make install 输入valgrind–h显示val