typescript初级

本文介绍了TypeScript的tsconfig.json配置,包括strictNullChecks、moduleResolution和jsx等选项的作用。接着讲解了泛型的概念,如泛型接口、泛型类和泛型约束,并讨论了在实际应用中的安全性与复用性。此外,还详细阐述了React DOM的render、unmountComponentAtNode、findDomNode和createPortal方法,特别是Fiber渲染机制的优势。最后提到了Modal弹框的alert实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tsconfig.json(ts配置)

“strictNullChecks”: true

ts有undefined和null两个空类型的设计 ,使用上不方便,开启此项进行严格校验空值类型,让代码更安全。

“moduleResolution”: “node/classic”

node: 引用模块时,会从node_modules文件中检查模块是否存在
classic: 引用模块时先从项目中查找模块是否存在,若不存在再查找node_modules文件。

“jsx”: “preserve | react | react-native”,

ts中使用react需要使用上面配置开启jsx功能,否则编译报错, react文件的扩展名为.tsx
在这里插入图片描述

“esModuleInterop”: true

import导入,export导出模块时检查导出模块是否添加了default属性,若未设置会自动进行设置
如:module. exports = {name: ‘lmh’} 开启后会设置为:module.exports.default = {name: ‘lmh’}

“noImplicitAny”: false,

不进行隐式any类型处理

const key = 'name'
student[key] = 'lmh'			// 会报错,key被设置为隐式的any类型,若关闭此项设置便会解决此情况

“target”: “es6”

将代码编译为es6版本

泛型

泛型提高了类型的安全性和复用性

function add<T>(arg1: T, arg2: T) { 
	return arg1 + arg2
})

add<number>(1, 0)		// 1
add<string>('1', '0')			// 10

泛型接口

function add<T>(arg1: T, arg2: T) { 
	return arg1 + arg2
})

// 等价于
let addFun: <T>(arg1: T, arg2: T) => <T>
let addFun: {<T>(arg1: T, arg2: T): T}

// 切换为泛型接口定义
interface GenAdder {<T>(arg1:  T, arg2: T): T}
let addFun: GenAdder
addFun<number>(1, 0)
addFun<string>('1', '0')

// 泛型2
interface GenAdder<T> {<T>(arg1: T, arg2: T): T}
let addFun: GenAdder<number>
addFun(1, 2)

泛型类

class Adder<T> {
	add: (arg1: T, arg2: T) => T;
}

function add(arg1, arg2) {
	return arg1 + arg2
}

const adder = new Adder<number>()
adder.add = add

const stringAdder = new Adder<string>()
stringAdder = add

adder.add(1,2)
stringAdder.add('1', '2')

泛型约束

function getLength<T>(arg: T): T {
	return arg.length
}

这样写是错误的,原因是T类型不定,其类型上可能不存在length属性,应改写为:

interface Ilength {
	length: number
}

function getLength<T extends Ilength>(arg: T): T {
	return arg.length
}

getLength<boolean>(false)		// 会报错,因为boolean上没有length属性
getLength<string>('lmh')			// 3

keyof 取对象的所有属性值

const people = {name: 'lmh', age: 18}
let keys: keyof typeof people			// name | age

// keyof T,取出T中的所有属性生成一个联合属性
// K extends 联合属性,即K继承了T的所有属性
function getProperty<T, K extends keyof T>(obj: T, key: K) {
	return obj[key]
}

getProperty(people, 'names')	// 报错,names不在people属性中

react-dom

render

ReactDom.render(<App />, document.getElementById('root'), () => {
	console.log('当<App>组件挂载到'root‘元素后执行的回调函数,故这是个异步函数')
});

react渲染机制有2种:
Stack: 16前的渲染机制

react更新数据前会使用diff算法来比对新的节点和旧的节点,导出需要更新的部分,当dom元素比较复杂时,比较时比较耗时,在stack机制中,未比较完毕前,视图是不会更新的,会一直处于等待的状态,会造成界面的卡顿效果

Fiber:16后的渲染机制

Fiber在新旧节点对比时,会将任务拆分,拆分成很多小任务,每做完一个小任务就会及时的更新视图,所以更新的频率会比较频繁,但每次更新并不会更新整个视图,而是只更新一个小局部

unmountComponentAtNode

const root = document.getElementById('root') as HTMLElement
ReactDom.render(<App />, root, () => {
	// 3s后移除root下的元素
	setTimeout(() => {
		// 两行代码结果一样,但unmountComponentAtNode方式会执行App组件中的componentWillUnmount,但remove不会
		// (root.firstChild as HTMLElement).remove()
		ReactDom.unmountComponentAtNode(document.getElementById('root'))
	}, 3000)
});

findDomNode

let app: any

ReactDom.render(
	<App ref={node => app = node} />, 
	document.getElementById('root'),
	 () => {
	 	console.log(app)   // 输出App组件对象
	 	app.componentWillunmount 			// 调用App组件中的componentWillunmount方法
	 	console.log(ReactDom.findDOMNode(app))		// 获取App的真实dom节点
	 }r
)

createProtal

将子组件渲染到父组件层级之外,但子组件的虚拟dom树结构依然挂载到父组件中。

import React from 'react'
import ReactDom from 'react-dom'

export default class Demo extends React.Component {
    public state = {counter: 0}

    handleClick() {
        this.setState((prevState: any) => ({
            counter: prevState.counter + 1
        }))
    }

    render() {
        return (
            <div className="father" onClick={this.handleClick.bind(this)}>
                <div>counter: {this.state.counter}</div>
                // button被挂载到body下,但仍然会执行父级的onClick事件
                {ReactDom.createPortal(<button>Click</button>, document.body)}
            </div>
        )
    }
}

Modal弹框的alert弹框

import React from 'react'
import ReactDOM from 'react-dom'
import  Modal  from 'antd-mobile/lib/modal/index'
import {Action} from 'antd-mobild/lib/modal/PropsType'

// 声时阻止滚动的监听器
const stopMove = (e: any) => e.preventDefault()

export default function alret (
	title: React.ReactNode,
	message: React.ReactNode,
	actions= [{text: '知道了'}]			// 为actions赋默认值
) {
	const el = document.createElement('div‘)
	document.body.appendChild(div)
	
	// 关闭事件
	const close = () => {
		ReactDOM.unmountComponentAtNode(div)
		div.remove()
		// 弹框关闭时恢复滚动条滚动
		document.body.removeEventListener('touchmove', stopMove)
	}
	// 处理footer按钮
	const footer = actions.map((button: Action<React.CSSProperties>) => {
		const oldOnPress = button.onPress || (() => {})
		button.onPress = () => {
			const res = oldOnPress()
			// 按钮的点击可能是个异步函数
			if (res && res.then) {
				res.then(close())
					.catch(() => {})
			} else {
				close()
			}
		}
		return button
	})
	
	// 通过监听touchmove禁止滚动操作来解决弹框滚动的穿透bug
	document.body.addEventListener(
		'touchmove',
		stopMove,
		 {passive: false}		// 为true时, e.preventDefault不会被执行,所以应该设为fasle
	)

	ReactDOM.render(
		<Modal
			visible={true}
			transparent={true}
			title={title}
			closable={false}
			maskClosable={false}
			footer={footer}
		>
			<div>{message}</div>
		</Modal>,
		el
	)
}e
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值