TS核心知识点总结及项目实战案例分析

2023-05-16

前言

最近工作一直很忙,复盘周期也有所拉长,不过还是会坚持每周复盘。今天笔者将复盘一下typescript在前端项目中的应用,至于为什么要学习typescript,我想大家也不言自明,目前主流框架vue和react以及相关生态的内部构建大部分都采用了typescript,其原因就在于它的静态类型检查极大的提高了代码的可读性和可维护性,而且定位问题非常方便。下面上一份关于typescript的官方定义,方便大家理解:

TypeScript 是由微软开发的自由和开源的编程语言, 是JavaScript 的一个超集,支持 ECMAScript 6 标准。其设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。

本文将通过介绍ts的核心知识点以及实际案例来带大家轻松掌握typescript。

概要

任何语言的学习都要有学习和思考体系,前端也不例外,笔者将按照如下图所示结构来进行讲解:

正文

我们目前项目开发用的最多的就是webpack,对于ts,我们也很方便的可以通过ts-loader对其进行编译配置,为了降低大家学习ts的难度,笔者推荐采用vue-cli3或者umi直接搭建ts项目,这样可以更快的上手ts开发。

核心知识点

1. 基础类型

TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。接下来我们简单介绍一下这几种类型的用法.

// 布尔类型
let isCookie:boolean = true

// 数值类型
let myMoney:number = 12

// 字符串类型
let name:string = '徐小夕'

// 数组类型, 有两种表示方式,第一种可以在元素类型后面接上[],表示由此类型元素组成的一个数组
let arr:number[] = [1,2,2]

// 数组类型, 使用数组泛型
let arr:Array<number> = [1,2,2]

// 元组类型, 允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
let xi: [string, number];
// 初始化xi
xi = ['xu', 10]; // 正确
xi = [11, 'xu']; // 错误

// 枚举类型, 可以为一组数值赋予友好的名字
enum ActionType { doing, done, fail }
let action:ActionType = ActionType.done    // 1

// any, 表示任意类型, 可以绕过类型检查器对这些值进行检查
let color:any = 1
color = 'red'

// void类型, 当一个函数没有返回值时,通常会设置其返回值类型是 void
function getName(): void {
    console.log("This is my name");
}

// object类型, 表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型
let a:object;
a = {props: 1}

复制代码

以上是typescript中常用的几种类型, 也是我们必须掌握的基本知识. 这里值得补充的是typescript的类型断言, 也是解决ts警告的利器,比如我们确切的知道某种数据的数据类型,我们可以这么做:

let arrLen: number = (someValue as Array<string>).length;
// 解决window下设置属性的ts报错, 但不可滥用
(window as any).name = 'xuxi'

复制代码

2. 接口

TypeScript的核心原则之一是对值所具有的结构进行类型检查。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。接下来我们看看如何定义和使用接口(Interface):

interface Product {
  name: string;
  size: number;
  weight: number;
}

let product1:Product = {
    name: 'machine1',
    size: 20,
    weight: 10.5
}

复制代码

类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。其次我们还可以定义可选属性和只读属性. 可选属性表示了接口里的某些属性不是必需的,所以可以定义也可以不定义.可读属性使得接口中的某些属性只能读取而不能赋值. 具体案例如下:

interface Product {
  name: string;
  size?: number;
  readonly weight: number;
}

复制代码

在实际场景中, 我们往往还会遇到不确定属性名和属性值类型的情况, 这种情况往往发生在第三发SDK接入或者后端响应中, 这个时候我们可以利用索引签名来设置额外的属性和类型, 案例如下:

interface App {
  name: string;
  color?: number;
  [propName: string]: any;
}

复制代码

接口除了描述带有属性的普通对象外,也可以描述函数类型。我们需要给接口定义一个调用签名, 参数列表里的每个参数都需要名字和类型。案例如下:

interface MyFunc {
  (value:string, type: number): boolean;
}
// 使用
let myLoveFront: MyFunc;
myLoveFront = function(value:string, type: number) {
    return type > 1
}

复制代码

我们在vue和react开发中,也会经常使用class这种类来编写可复用组件和库, 既然ts可以描述函数类型, 那么是不是也可以用来描述类类型呢? 答案是可以的.但是类接口的定义稍微有点复杂, 我们都知道类是具有两个类型的:静态部分的类型和实例的类型. 当一个类实现了一个接口时,只对其实例部分进行类型检查。constructor存在于类的静态部分,所以不在检查的范围内。. 这句话相当关键, 我们在定义类接口的时候也要主要这一特点, 案例如下:

interface TickConstructor {
    new (hour: number, minute: number): TickInterface;
}
interface TickInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): TickInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements TickInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("xu xu");
    }
}
class MyTick implements TickInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalTick, 12, 17);
let analog = createClock(MyTick, 7, 32);

复制代码

掌握了这些关键的接口类型和使用方法, 对于ts的学习基本上可以入门了.

3. 类

关于类接口的话题我们在上文已经介绍了, 这里我们来具体了解一下类. 和js的class一致, typescript的类有公共,私有与受保护的修饰符. 具体含义如下:

  • public 在TypeScript里,成员都默认为 public,我们可以自由的访问程序里定义的成员

  • private 当成员被标记成 private时,它就不能在声明它的类的外部访问

  • protected 和private类似, 但是protected成员在派生类中仍然可以访问

具体案例如下:

class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name)
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

复制代码

同样我们也可以为类中的某个属性定义readonly修饰符和定义static静态属性, 唯一值得说的是抽象类.

抽象类做为其它派生类的基类使用。它们一般不会直接被实例化。不同于接口,抽象类可以包含成员的实现细节。abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

有关抽象类的案例简单介绍如下:

abstract class MyAbstract {
    constructor(public name: string) {}
    say(): void {
        console.log('say name: ' + this.name);
    }
    abstract sayBye(): void; // 必须在派生类中实现
}

class AccountingMyAbstract extends MyAbstract {
    constructor() {
        super('小徐'); // 在派生类的构造函数中必须调用 super()
    }
    sayBye(): void {
        console.log('趣谈小夕.');
    }
    getOther(): void {
        console.log('loading...');
    }
}

let department: MyAbstract; // 允许创建一个对抽象类型的引用
department = new MyAbstract(); // 错误: 不能创建一个抽象类的实例
department = new AccountingMyAbstract(); // 允许对一个抽象子类进行实例化和赋值
department.say();
department.sayBye();
department.getOther(); // 错误: 方法在声明的抽象类中不存在

复制代码

4. 函数

函数类型在上文已经介绍过了, 这里主要在讲一下可选参数这个概念. JavaScript里每个参数都是可选的,可传可不传。没传参的时候其值就是undefined。在TypeScript里我们可以在参数名旁使用 ?实现可选参数的功能。具体案例如下:

function createName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

复制代码

注意, 我们的可选参数必须跟在必选参数后面.

5. 泛型

我们可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。泛型是typescript中比较难懂的知识点, 但是非常重要, 几乎任何第三方组件库里都会用到. 我们先来看个最简单的例子:

function iSay<T>(arg: T): T {
    return arg;
}
// 调用泛型函数
let come = iSay<number>(123);

复制代码

我们给iSay添加了类型变量T。T帮助我们捕获用户传入的类型(比如:string),这样我们就可以使用这个类型。之后我们再次使用T当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。这允许我们跟踪函数里使用的类型的信息。

我们还可以把泛型变量T当做类型的一部分使用,而不是整个类型, 这样可以增加我们的使用灵活性, 案例如下:

function iSay<T>(arg: T[]): T[] {
    console.log(arg.length)
    return arg;
}

复制代码

类似于函数类型的定义, 我们也可以定义泛型接口, 并且可以把泛型参数当作整个接口的一个参数, 这样我们就能清楚的知道使用的具体是哪个泛型类型. 案例代码如下:

interface SayLove {
    <T>(arg: T): T
}

// 把泛型参数当作整个接口的一个参数
interface SayLoveArg<T> {
    (arg: T): T
}

// 泛型函数
function iSay<T>(arg: T): T {
    return arg;

let mySay1:SayLove = iSay
let mySay2:SayLoveArg<number> = iSay

复制代码

同样的我们还可以定义泛型类.我们只需要使用(<>)括起泛型类型,跟在类名后面即可. 具体案例如下:

class MyNumber<T> {
    year: T;
    compute: (x: T, y: T) => T;
}

let myGenericNumber = new MyNumber<number>();

复制代码

我们还可以定义泛型约束来更准确的控制类的类型. 案例如下:

interface NumberControl {
    length: number
}

class MyObject<T extends NumberControl>(arg: T):T {
    console.log(arg.length)
    return arg
}

复制代码

6. 高级类型

typescript的高级类型里我们主要讲解如下核心知识点:

  • 交叉类型

  • 联合类型

  • 多态的 this类型

  • 索引类型查询操作符

  • 索引访问操作符

交叉类型是将多个类型合并为一个类型。我们可以把现有的多种类型叠加到一起成为一种类型,下面有个经典的例子供大家参考:

function extend<T, U>(first: T, second: U): T & U {
    let result = <T & U>{};
    for (let id in first) {
        (<any>result)[id] = (<any>first)[id];
    }
    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (<any>result)[id] = (<any>second)[id];
        }
    }
    return result;
}

复制代码

我们通过字符 & 来表示联合, 此时以上代码中的返回值会具有T和U的类型.

联合类型表示一个值可以是几种类型之一。我们用竖线(|)分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean。具体例子如下:

let name: string | number = 'xuxiaoxi'

function sayName(name: string):(string|number) {
  return name
}

复制代码

值得注意的是: 如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。

还有一种常见的需求是, 我们在实现自己的类后,需要支持类方法的链式调用, 这个时候我们应该返回this, 在typescript中我们就需要了解多态的 this类型. 它表示的是某个包含类或接口的子类型。这被称做 F-bounded多态性。要想在typescript中支持链式, 我们可以这么写:

class MyCalculator {
    public constructor(number = 0) { }
    public add(n: number): this {
        this.value += n;
        return this;
    }
    public multiply(n: number): this {
        this.value *= n;
        return this;
    }
    // ... 其他操作 ...
}

let v = new MyCalculator(2).multiply(5).add(1);

复制代码

下面一个我们需要知道的知识点是索引类型查询操作符. 一般用keyof表示。对于任何类型T, keyof T的结果为T上已知的公共属性名的联合。比如我们定义一个接口Animal:

interface Animal {
    cat: string;
    dog: string;
}

let AnimalProps: keyof Animal; // 'cat' | 'dog'

复制代码

keyof Animal是完全可以与 'cat' | 'dog'互相替换的。不同的是如果我们添加了其它的属性到 Animal,例如 pig: string,那么 keyof Animal会自动变为 'cat' | 'dog' | 'pig'。

7. 命名空间

命名空间主要作用是用来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。由于命名空间的用法很简单,这里我们以网上比较流行的D3作为例子, 代码如下:

declare namespace D3 {
    export interface Selectors {
        select: {
            (selector: string): Selection;
            (element: EventTarget): Selection;
        };
    }

    export interface Event {
        x: number;
        y: number;
    }

    export interface Base extends Selectors {
        event: Event;
    }
}

declare var d3: D3.Base;

复制代码

8. 使用第三方类库 

在熟悉以上基础知识之后, 我们看一下如何使用支持typescript的第三方类库. 比如说我们常用的lodash, 那么正确的使用步骤如下:

// 安装lodash和对应的类型文件
npm install --save lodash @types/lodash

// 在代码中使用
import * as _ from "lodash";
_.padStart("Hello xuxiaoxi!", 12, " ");

复制代码

9. 声明文件 

声明文件也是一个非常重要的知识点.对于使用未经声明的全局函数或者全局变量, typescript往往会报错, 所以我们可以在对应位置添加xxx.d.ts文件, 并在里面声明我们所需要的变量, ts会自动检索到该文件并进行解析. 以下是几个案例, 供大家参考学习:

// global.d.ts

// 声明全局变量
declare var name: string;

// 全局函数
declare function say(name: string): void;

// 带属性的对象
declare namespace myObj {
    function say(s: string): string;
    let money: number;
}

// 可重用的接口
interface Animal {
    kind: string;
    age: number;
    weight?: number;
}
declare function findAnmiate(animal:Animal):void

复制代码

当然我们还可以定义更多有用的声明, 这里就不一一举例了.

React + Typescript项目实战

1. 使用umi搭建react+typescript项目

为了帮助大家快速上手typescript开发, 这里我们采用umi来搭建一个支持ts的项目, 不熟悉的朋友可以参考笔者之前学习umi的文章.

2. 定义去全局声明文件

我们在项目src目录下创建一个global.d.ts来作为我们全局的声明文件, 用来处理全局声明和兼容第三方库.

3. 使用ts实现工具类库 

我们在src目录下创建一个utils目录用来存放我们的工具类或者通用库, 比如在utils下新建一个tool.ts作为我们的通用工具函数, 这里我们写个最简单的例子:

/**
* 生成uuid
*/
const uuid = ():string => {
    let s:Array<any> = [];
    let hexDigits:string = "0123456789abcdef";
    for (let i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4"; 
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); 
    s[8] = s[13] = s[18] = s[23] = "-";
    let uuid = s.join("");
    return uuid;
};

// 可以来自于外部的type.ts文件
interface Params {
  [propName: string]: string | number
}

/**
 * reverseJson 反转对象键值对
 * @param {object} obj 待反转的对象
 * @param {object} target 反转的目标对象
 */
const reverseJson = (obj:Params = {}, target:Params = {}):Params => {
  Object.keys(obj).forEach((key:string) => { target[obj[key]] = key })
  return target
}

复制代码

以上只是几个简单的案例, 还不够完善, 大家可以根据自己的需求实现相应的封装.

4. 在React组件中使用typescript

笔者将在下一篇文章中继续实现该章节, 让大家对实际的typescript开发有一个具体的认识.

最后

如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TS核心知识点总结及项目实战案例分析 的相关文章

  • Arch Linux 安装和配置(陆续更新)

    Arch Linux 安装和配置 陆续更新 南国一年一度的回南天到来 xff0c 周末百无聊赖 xff0c 研究一下Arch Linux xff0c 整理此文 xff0c 其他使用笔记陆续补充 一 在Vmware中安装Arch Linux
  • ASP.NET Core MemoryCache 缓存

    ASP NET Core 中的缓存内存 xff08 MemoryCache xff09 ASP NET Core 中的缓存内存 ASP NET Core 中的分布式缓存 xff08 SQL Server 和 Redis 分布式缓存 xff0
  • FFmpeg In Android - 多媒体文件解封装/解码/保存Yuv

    FFMPEG视音频编解码零基础学习方法 100行代码实现最简单的基于FFMPEG 43 SDL的视频播放器 本文例子的源码 demuxing decoding cpp 修改自源码自带的例子ffmpeg源码 doc example demux
  • 【Java篇】多线程详解

    Java 多线程基础详解 文章目录 Java 多线程基础详解线程的相关概念一 创建线程的几种方式1 继承Thread类2 实现Runnable接口3 实现Callable接口4 推荐使用Runnable接口 二 线程安全1 线程安全问题引入
  • NotePad++ XMLTools 插件离线安装

    在使用NotePad 43 43 时 xff0c 在某些情形下 xff0c 需要格式化Xml格式内容 xff0c 可以使用Xml Tools插件 xff0c 注意下载安装包时 xff0c 需下载与NotePad 43 43 像匹配版本的插件
  • 【Windows逆向】【Qt】日志信息打印

    目录 x1f6eb 导读需求开发环境 1 示例程序Demo2 编写功能 xff08 QtCreator版本 xff09 3 编写功能 xff08 VS版本 xff09 x1f6ec 文章小结 x1f4d6 参考资料 x1f6eb 导读 需求
  • Ubuntu 18.04 安装ROS melodic文件错误问题broken packages

    反复多次尝试安装ros melodic xff0c 一直报错 xff0c 有文件损坏或者安装依赖问题 直接进入安装阶段 xff0c 前面的请看其他详细帖子 sudo apt span class token operator span ge
  • 在虚拟机安装Archlinux

    最近花了挺长一段时间练习在虚拟机安装archlinux的 xff0c 在这里跟大家分享一下经验 xff0c 如有错误 xff0c 欢迎大家指出 xff0c 谢谢大家 准备工作 archlinux镜像 43 vmware workstatio
  • Linux系统启动流程及系统裁剪

    一 内核管理简要理论 1 内核的功能 xff08 1 xff09 进程管理 xff08 2 xff09 内存管理 xff08 内核管理代码中代码量最大的部分 xff09 xff08 3 xff09 I O管理 xff1a 中断及中断处理 x
  • UNIX环境高级编程习题——第三章

    第三章习题 3 1 当读 写磁盘文件时 xff0c 本章中描述的函数确实是不带缓冲机制的吗 xff1f 请说明原因 xff1a span class hljs number 1 span 本章中描述的read和write函数都是系统调用 x
  • Ubuntu 16.04 安装Vmware Workstation12

    1 安装Vmware Workstation12 1 从官网上获取http www vmware com products workstation workstation evaluation html 2 如果觉得上面的方法下载得比较慢
  • Idea2017查看Class字节码文件

    Idea查看字节码文件的原理 1 javap命令的使用 在jdk工具包的bin目录下 xff0c 有一个java可执行文件javap xff0c 该工具可以查看java编译后的class文件 使用命令如下命令进行查看 javap span
  • Idea配置Web项目路径以及使用非默认Tomcat启动

    1 Web项目发布路径配置 1 首先点击Run gt Edit Configurations 2 点击左上角绿色的加号 xff0c 选择Tomcat gt Local 3 点击Deployment 4 点击绿色的小铅笔 5 在此处设置Out
  • emacs下org-mode导出pdf时pdflatex无法找到的问题解决方案

    配置环境 Deepin15 6 Linux emacs25 2 发现的问题 系统没有找到pdflatex命令 xff0c org mode无法导出latex的pdf 解决步骤 安装texlive2018 因为pdflatex是texlive
  • 通过Flask框架封装Tushare获取的日线股票数据

    概要介绍 概要介绍 xff08 TuShare id 282782 xff09 当我们需要进行量化交易分析 xff0c 或者通过代码进行股票的数据计算 xff0c 研究金融时 xff0c 我们需要获取最基本的股票价格 xff0c 开盘价收盘
  • IBM Was 打补丁记录

    0 拷贝解压ifph52925升级包 通过FTP工具 xff0c 把压缩包传到服务器 xff0c unzip d test01 9 0 0 0 ws was ifph52925 zip 1 停掉was 服务 ps ef grep was k
  • CoreText --- 段落样子CTParagraphStyle

    在前面一篇文章中 xff0c 介绍了属性文字的基本使用 xff0c 本章节主要针对文字的段落样式展开演示说明 先定义一段演示文字 xff08 文字中有中 xff0c 英文 xff09 cpp view plain copy NSString
  • 将自己的域名解析跳转到博客主页(GitHub中的gitpage跳转)

    最近突然迷上了博客 xff0c 突然又突发奇想 xff0c 将自己几个月前买的现在限制的域名拿来跳转到自己的csdn博客 经过一番研究 xff0c 总结 把自己的购买的域名 比如我买的circleyuan top 跳转到CSDN博客 只需要
  • Python3.4简单爬虫实现之抓取糗事百科段子

    网上的python教程大都是2 X版本的 xff0c python2 X和python3 X相比较改动比较大 xff0c 好多库的用法不太一样 xff0c 我安装的是3 4 1 xff0c 就用3 4 1实现一下网页内容抓取 首先是库 xf

随机推荐

  • 【C++】类和对象的关系

    概念 xff1a 对象 xff1a 将数据和对数据的操作方法放在一起 xff0c 形成一个相对独立的整体 属性和操作是对象的两大要素 类 xff1a 某一类对象所共有的 本质的属性和类行为 类和对象的关系 类是抽象的 xff0c 对象是具体
  • 美团笔试题_20220409

    前言 笔试一共五道编程题 xff08 四 43 一 xff09 xff0c 一为专项编程题 xff0c 估计不同岗位有题目不一样 xff0c 使用的是赛码网 xff0c 允许跳出界面使用自己的IDE 在此感谢筱羊冰冰提供的部分题目及题解 题
  • Android应用管理一 -- APK包的安装、卸载和优化(PackageManagerService)

    Android的应用管理主要是通过PackageManagerService来完成的 PackageManagerService服务负责各种APK包的安装 卸载 优化和查询 PackageManagerService在启动时会扫描所有的AP
  • Android5.1--多用户模式

    Android中的多用户与Windows的多用户类似 xff0c 可以支持多个用户使用系统 通常 xff0c 第一个在系统中注册的用户将默认成为系统管理员 不同用户的设置各不相同 xff0c 并且不同用户安装的应用及应用数据也不相同 但是系
  • Android--应用安装卸载失败问题分析

    1 应用安装失败 xff1a does not include classes dex 08 04 17 15 23 118W dalvikvm 5253 DexOptZ zip archive 39 data app cloneit 1
  • Android5.1--电源管理之省电模式分析

    一 如何开启5 0省电模式 打开安卓5 0设备的设置选项 xff0c 然后前往电池菜单 xff0c 点击菜单键 xff0c 弹出并选择 节电助手 xff0c 随后点击顶部的开关便可 此外 xff0c 要是用户运行的是原生版安卓 xff0c
  • 如何判断一个未安装的APK是Launcher应用

    网上找的大都是已安装应用的判断方法 xff0c 那么如何判断未安装的apk是否是桌面应用呢 xff1f 直接上代码 xff1a private boolean isLauncherApp String dexPath boolean isH
  • oracle 备份表

    一 PL SQL备份 xff08 1 xff09 打开PL SQL xff08 2 xff09 在Tools下选择Export Tables xff08 3 xff09 在列表中找到想要备份的表 xff0c 右键选择Export Data
  • Android 预置应用

    预置应用主要有4种情况 xff1a 1 如何将带源码的应用预置进系统 xff1f 2 如何将无源码的应用预置 xff08 APK xff09 进系统 xff1f 3 如何预置应用使得用户可以卸载 xff0c 恢复出厂设置时不能恢复 xff1
  • Android广播管理三--广播发送(sendBroadcast)流程分析

    前面我们分析了Android应用程序注册广播接收器的过程 xff0c 接下来它还要等待ActivityManagerService将广播分发过来 ActivityManagerService是如何得到广播并把它分发出去的呢 xff1f 广播
  • 避免后台进程被杀死的几种方法

    Android的几种进程 前台进程 即与用户正在交互的Activity或者Activity用到的Service等 xff0c 如果系统内存不足时前台进程是最后被杀死的 可见进程 可以是处于暂停状态 onPause 的Activity或者绑定
  • Android性能优化 -- Systrace工具

    Systrace简介 一般来说 xff0c 我们的机器以60帧 秒显示时 xff0c 用户会感觉机器很流畅 xff0c 如果显示时出现丢帧的情况 xff0c 需要知道当前整个系统所处的状态 xff0c 这个时候Systrace便是最佳的工具
  • Android性能优化 -- 应用启动优化之启动页设计

    上篇博客我们学习了应用启动优化的一些优化思路 xff0c 经过这些优化后 xff0c 如果还不能达到你的要求 xff0c 我们一般会做个启动页 因为启动页一般View数量比较少 xff0c 业务逻辑比较简单 xff0c 因此启动比较快 一
  • Android性能优化 -- 布局优化

    一 前言 根据Google官方出品的Android性能优化典范 xff0c 60帧每秒是目前最合适的图像显示速度 xff0c 事实上绝大多数的Android设备也是按照每秒60帧来刷新的 为了让屏幕的刷新帧率达到60fps xff0c 我们
  • ubuntu server 18.0.4自动免密登录

    参考https zhuanlan zhihu com p 79422682 1 xff09 设置自动登录user sudo vim etc systemd system getty target wants getty 64 tty1 se
  • nginx 反向代理设置中的proxy_redirect

    Nginx做反向代理 xff0c 如果在header设置了Host参数 xff0c 同时如果有协议和二级目录有不一致的情况的时候 xff0c 当后端服务做302 301跳转的时候 需要用proxy redirect将后端设置在respons
  • iOS - OC - ARC中使用MRC(非ARC)文件(草稿)

    设置非arc模式 刚创建的项目是自动管理内存 xff08 arc xff09 的 xff0c 而asi是手动内存管理 xff08 非arc xff09 的 xff0c 可以在创建项目后设置Build Settings的搜索栏里输入gar x
  • 批量识别PDF文件(图片类型)中的文字

    如何批量识别PDF图片中的文字 xff0c 一直是一个效率很低 xff0c 很繁琐的事情 小编为大家提供一款基于tesseract5 0 OCR版本的PDF文件 图片类型 批量识别工具 xff0c 此工具的用途是批量把PDF转换成文本文件
  • 《最重要的事,只有一件》读书笔记

    背景 每天都在忙忙碌碌中度过 xff0c 感觉到很累 xff0c 但仔细思考一下好像也没有收获 仔细想一想 xff0c 在每天之中 xff0c 大脑主动或被动的接受了太多的信息 xff0c 如果没有给信息分出轻重缓急 xff0c 整理归类
  • TS核心知识点总结及项目实战案例分析

    前言 最近工作一直很忙 xff0c 复盘周期也有所拉长 xff0c 不过还是会坚持每周复盘 今天笔者将复盘一下typescript在前端项目中的应用 xff0c 至于为什么要学习typescript xff0c 我想大家也不言自明 xff0