react基础

Posted by アライさん on 2022年09月09日

JSX中,用 {} 大括号包裹javascript代码。使用 { { } } 内联css。

JSX注释实用:{/* */}
JSX 中所有 HTML 属性和事件引用的命名约定都变成了驼峰式。JSX中HTML标签的id,实用className。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//将JSXName渲染到id为idName的节点中
ReactDOM.render(JSXName, document.getElementById('idName'));

ReactDOM.render(<Kitten name='参数'/>, document.getElementById('idName'))
```


## 在JSX中使用内联样式
```jsx
{/* font-size之类需要变成驼峰写法 */}
<div style={{color: "purple", fontSize: 40, border:"2px solid purple"}}>Big Red</div>
```


## 在JSX中使用ifelse
```jsx
<div>
{this.state.display && <h1>Displayed!</h1>}
</div>
{/* 等价 */}
<div>
{this.state.display ? <h1>Displayed!</h1> : null}
</div>

map

1
2
3
4
5
6
7
8
9
['abc','efg','hij'].map((item, index) =>
<li key={index}>{item}</li>
);
```

## filter
```javascript
//过滤掉online=false的数据
[{name:'a',online:false},{name:'a',online:true},].filter(user => user.online);

组件基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const MyComponent = function() {
return (
<div>测试</div>
);
}
//或者
class Kitten extends React.Component {
constructor(props) {
super(props);
this.state = {
count:0
};
//需要使用这种方式绑定,否则render中会找不到handleClick
this.handleClick = this.handleClick.bind(this);
}

handleClick(){
this.setState((state,props)=>({
count:state.count + 1
}));
}

render() {
return (
<button onClick={this.handleClick}>{this.props.name} {this.state.count}</button>
);
}
}
//设置默认参数
Kitten.defaultProps = {
name: 'CamperBot',
};
//设置参数类型
Kitten.propTypes = { name: PropTypes.string.isRequired }
```


## 生命周期
* componentWillMount() 废弃
* componentDidMount() 可在此挂在联网请求,使用setState刷新页面。也可以设置监听器。
* shouldComponentUpdate(nextProps, nextState) 根据nextProps和nextState,返回true/false手动确定是否要刷新。
* componentDidUpdate()
* componentWillUnmount()


## 按键监听
```javascript
componentDidMount() {
document.addEventListener("keydown", this.handleKeyPress);
}
componentWillUnmount() {
document.removeEventListener("keydown", this.handleKeyPress);
}
handleKeyPress(event) {
if (event.keyCode === 13) {
//todo
}
}

Hook

import React, { useState, useEffect } from 'react';

function Example(){
  //count是一个state,setCount代表更新count的函数,0则是初始化值
  const [count,setCount] = useState(0);
  const [timer,setTimer] = useState(null);

  useEffect(()=>{
    //第一次渲染和每次刷新后都会执行
    //[count]可以不传。传入后会对比count的值,不同才执行
  },[count]);

  return(
    <div>
      <p>You clicked {count} times</p>
      <button onClick={()=>setCount(count+1)}>click me</button>
    </div>
  );
}

自定义Hook

import React, { useState, useEffect } from 'react';

//自定义hook
function useFriendStatus( friendID ) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    //绑定监听,ChatAPI会调用handleStatusChange方法设置是否在线
    ChatAPI.subscribeToFriendStatus(friendID,handleStatusChange);

    //销毁时调用取消监听
    return ()=> {
      ChatAPI.unsubscribeToFriendStatus(friendID,handleStatusChange);
    }

  });

  return isOnline;
}

使用上述自定义的useFriendStatus:

function FriendItem(id) {
  const isOnline = userFriendStatus(id);
  return (
    <li style={{ color: isOnlie? 'green':'black'}}>
      id: {id} 
    </li>
  );
}

不同组件中使用相同的自定义Hook并不会共享State(即useState()函数的返回值),它们都是独立的,并且在同一个组件中每次调用Hook都会获取独立的State

useContext hook获取全局属性

const themes = {
  light: {
    foreground: "#000000",
  },
  drak: {
    foreground: "#ffffff",
  },
};

const ThemeContext = React.createContext(themes.light);

function ThemedButton() {
  //useContext的参数是React.createContext出来的context
  const theme = useContext(ThemeContext);
  return (
    <button style={{ color:theme.foreground}}>按钮</button>
  );
}

其他Hook: useReducer(), useCallback(), useMemo(), useImperativeHandle(), useLayoutEffect(), useDebugValue(), 等等