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