TS入门011ts和react应用

TS和React

  • typescript react

    1
    2
    3
    4
    5
    6
    7
    8
    npm i create-react-app@2.1.3 -g

    // 创建工程
    npx create-react-app my-app --typescript

    # or

    yarn create react-app my-app --typescript
  • 进入目录 cd my-app

  • 运行项目 yarn start
  • 成功

Button组件

  • 修改 src/index.tsx

    1
    2
    3
    4
    5
    6
    7
    8
    import React from 'react';
    import ReactDOM from 'react-dom';
    import Button from './Button';

    ReactDOM.render(<div>
    HelloWorld
    <Button />
    </div>, document.getElementById('root'));
  • src/Button.tsx

    1
    2
    3
    4
    import React from 'react';
    export default function Button(){
    return <div className="button">button</div>;
    }
  • 此时一个最简单的 Button 组件完成了

让 Button 接收 size ,为 Button 添加样式

  • src/Button.tsx 里引入 样式 import './Button.css';
1
2
3
4
5
6
7
8
9
10
import React from 'react';
import './Button.css';

interface iProps {
// ?代表 size 可有可无
size?: string
}
export default function Button(props: iProps) {
return <div className={`button ${props.size}`}>button</div>;
}

src/Button.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.button{
border:1px solid grey;
display: inline-block;
border-radius: 4px;
padding: 4px;
}

.button:hover{
background: black;
box-shadow: 0 0 2px black;
color:white;
}

.button.small{
font-size: 12px;
}

.button.big{
font-size: 30px;
}

src/index.tsx

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import ReactDOM from 'react-dom';
import Button from './Button';

ReactDOM.render(<div>
HelloWorld
<Button size="small"/>
<Button/>
<Button size="big"/>
</div>, document.getElementById('root'));

button 的文案显示如何控制?

  • 传递是字符串
  • 传递是 span
  • 传递多个 span
1
2
3
4
5
6
7
8
9
10
ReactDOM.render(<div>
<Button>
<span>Click ME</span>
</Button>
<Button>
<span>Click ME</span>
<span>Click ME</span>
</Button>
<Button>Click Me</Button>
</div>, document.getElementById('root'));

通过props

1
2
3
4
5
6
7
8
9
10
11
12
13
...

interface iProps {
// ?代表 size 可有可无
size?: string;
// 字符串 | 节点 | 节点数组
children?:string | JSX.Element | JSX.Element[];
}
export default function Button(props: iProps) {
return <div className={`button ${props.size}`}>
{props.children}
</div>;
}

以后我定义组件,难道每次都要写一个 children 属性?

  • react 给你提供了便利,你需要这样

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    interface iProps {
    // ?代表 size 可有可无
    size?: string
    }
    const Button:React.FunctionComponent = function (props) {
    return <div className={`button ${props.size}`}>
    {props.children}
    </div>;
    }

    export default Button;
  • FunctionComponent 是什么 vscode 点进去看看

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement | null;
    propTypes?: WeakValidationMap<P>;
    contextTypes?: ValidationMap<any>;
    defaultProps?: Partial<P>;
    displayName?: string;
    }

    // interface 代表接口 ,那么这个接口满足什么条件呢?
    // 有括号 (props: PropsWithChildren<P>, context?: any) 代表这是一个函数
    interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement | null;
    ... 后四个代表可选属性
    }

    // 这个函数的特征 接收两个参数 必填的 props 和 可选的 context
    // 同时 props 需要 满足 P 这个东西

    // P 是啥?

    意思就是 TS 类型可以接收参数 用 尖括号“<P = {}>”来写这个参数
    如果你不传递 P 那么这个值的参数就是 空的 => "{}"

    // 同时这个函数的返回值是 “ReactElement” 类型否则报错
  • 改写我们的 Button.tsx 给它传递参数 P 为 iProps 这样我们就可以不写 children

    1
    2
    3
    4
    5
    6
    7
    8
    9
    interface iProps {
    // ?代表 size 可有可无
    size?: string
    }
    const Button:React.FunctionComponent<iProps> = function (props) {
    return <div className={`button ${props.size}`}>
    {props.children}
    </div>;
    }

这就是用react提供的函数组件直接声明一个函数组件

添加点击事件

1
2
3
4
5
6
7
8
9
interface iProps {
size?: string;
// 可有可无 ,而且你要的类型 React帮你做了
onClick?:React.MouseEventHandler
}

// React.MouseEventHandler 是什么 点进去看看
// 一脸懵逼!!! 建议是没用三个月就别点进去看
type MouseEventHandler<T = Element> = EventHandler<MouseEvent<T>>;

修改 button.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Children } from 'react';
import './Button.css';

// 第二种方式
interface iProps {
// ?代表 size 可有可无
size?: string;
onClick?:React.MouseEventHandler
}
const Button:React.FunctionComponent<iProps> = function (props) {
return (
<div className={`button ${props.size}`} onClick={props.onClick}
>
{props.children}
</div>);
}

export default Button;

src/index.tsx

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import ReactDOM from 'react-dom';
import Button from './Button';

const fn:React.MouseEventHandler = function(e){
console.log(e);
}

ReactDOM.render(<div>
<Button onClick={fn}>Click Me</Button>
</div>, document.getElementById('root'));

参考代码 ts011