前端:JavaScript编码原则 | 青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 19 天 1/15
参考文献:
内容
组件
组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
react元素可以是DOM标签
const element = <div />;
也可以是用户自定义标签
const element = <Welcome name="Sara" />;
JSX
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;
root.render(element);
让我们来回顾一下这个例子中发生了什么:
- 我们调用 root.render() 函数,并传入
<Welcome name="Sara" />作为参数。 - React 调用 Welcome 组件,并将
{name: 'Sara'}作为 props 传入。 - Welcome 组件将
<h1>Hello, Sara</h1>元素作为返回值。 - React DOM 将 DOM 高效地更新为
<h1>Hello, Sara</h1>。
注意: 组件名称必须以大写字母开头。
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,
代表 HTML 的 div 标签,而 则代表一个组件,并且需在作用域内使用 Welcome。
组件分两种:类组件和函数组件(二者等效)
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
} //函数组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
} // 类组件
>JSX,JS一种扩展。Babel 会把 JSX 转译成一个名为React.createElement() 函数调用。
>注意点:
>1. JSX只能有一个根元素,所以return(...),括号里也只能有一个根元素
插值
插值 在HTML里面插入JS代码,加入{}引起来即可
class App extends React.Component {
return (
<div>
<ul>
<li>{...}</li>
<li>{...}</li>
<li>{...}</li>
</ul>
</div>
)
状态
React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。但this.state作为私有变量,可以定义各种状态
class App extends React.Component {
constructor() {
super();
this.state = {
pokemons: ["" ,"" ,"" ,]
} //以键值对作为state的属性
}
挂载
- 组件第一次被渲染到 DOM 中的时候,就为其设置一个方法。这在 React 中被称为“挂载(mount)”。
componentDidMount() {} - 同时,当 DOM 中 组件被删除的时候,应该相应内容。这在 React 中被称为“卸载(unmount)”。
componentWillUnmount() {}
状态设置
类组件:
关于 setState() 你应该了解三件事:
- 不要直接修改 State
this.state.comment = 'Hello';
// Wrong
this.setState({comment: 'Hello'});
// Correct
- State的更新可能是异步的
生命周期
- 类组件: 执行顺序:constructor => render => Didmount => render(react生命周期) 每当调用一次setState(),就会重新调用一次render()
- 函数组件:执行顺序:从上往下 注意:使用useState()时,与类组件不同,函数组件会从上到下完全重新执行一次
状态提升
当多个组件需要反应相同的变化数据,可将共享状态提升到最近的共同父元素中去
class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value);
} // 调用父节点类方法
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
... // 调用父节点传入的参数
);
}
}
class Calculator extends React.Component {
return (
<div>
<TemperatureInput
scale="c"//给子节点TemInput传入参数
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
列表&Key
核心:在React中,把
<li>{number}</li>组件当做元素
const listItems = numbers.map((number) => <li>{number}</li> );
key 帮助 React 识别哪些元素改变了,比如被添加或删除,即定位以提高性能
注意事项如下:
- 通常,我们使用数据中的 id 来作为元素的 key:
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
- 一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用数据中的 id 来作为元素的 key
- 当元素没有确定 id 的时候,万不得已你可以使用元素索引 index 作为 key
- 如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为为这样做会导致性能变差,还可能引起组件状态的问题
- 数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而,它们不需要是全局唯一的
CSS
CSS在React中作为变量书写
<div style={{ border: "1px solid darkorange" }}
/>
// 第1个括号:中间的键值对属于JSX里面的逻辑,要用插值表达 第2个:style的值需要传入一个对象
useState
函数组件中,由于没有constructor和render,故用useState设置状态
const [pokemons, setPokemons] = React.useState([]); // 解构赋值命名两个变量,第一个是状态值,第二个是设置状态值的方法
// useState()括号里面的值[]即为pokemons的初值,0、[]、等
useEffect
函数组件中,该组件内部的操作会改变函数以外的状态,称该种现象为副作用
为了防止副作用改变状态而反复调用函数,使用useEffect来消除该种影响
React.useEffect(() => {
//状态更新时,类组件只是重新render,而函数组件会吧组件里面的代码从上到下执行,这
// 不是App函数完全掌握得了的死循环=>副作用
fetch("https://pokeapi.co/api/v2/pokemon")
.then((res) => res.json())
.then((json) => {
json.results.map((result, index) => {
result.id = index + 1;
});
setPokemons(json.results);
setFilteredPokemons(json.results);
});
}, []); // 第一个参数,执行什么内容的函数;
// 第二个参数,数组,决定什么时候执行再去执行第一个参数里的内容
// 若为空,表示只需执行一次
附:如有错误,恳请指正,侵权必删:D