「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。
什么是React
React 是一个JS库(不是框架),主要的目的是构建用户交互界面
它将复杂的用户交互界面,打破成一个个内嵌并且可复用的组件,然后拼接起来。
React本身不处理路由,样式,数据获取。如果你需要上面功能,可以考虑Nextjs框架
其他框架包括:
React能做什么
上面说过,React的主要作用是构建用户交互界面,从单个按钮到整个app。
除此之外,还有 React Native 可以用来创建Android,iOS App或者 Windows和macOS软件
React团队提供了React开发者工具可以查看网页是否有React开发。如果是,工具栏对应的按钮会点亮。
React开发需要Javascript
React是个JS框架,如果你要使用它,需要掌握Javascript,提供2个网站现代JavaS cript和MDN中文查漏补缺。
React版本Hello World
下面代码描述了如何用React开发Hello World,非常简单,就2行代码。
function Greeting({ name }) {
return <h1>Hello, {name}</h1>;
}
export default function App() {
return <Greeting name="world" />
}
你可以点击这里在线查看和编辑具体的源码
学习React
React构建用户界面通过组件
。一个组件可以是简单的按钮,也可以是复杂的整个页面。
参考一下图片,这是很常见的用户头像列表模块
这个列表,可以拆成3 x 用户头像(Profile)+一个画廊(Gallery)组件(用于包裹3个头像组件和文字)。
用React实现就是如下,具体代码看这里
function Profile() {
return (
<img
src="https://i.imgur.com/MK3eW3As.jpg"
alt="Katherine Johnson"
className="avatar"
/>
);
}
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
这种有点像HTML标记语法的叫做JSX。JSX代表着JS+XML。大部分和HTML语法相同,比如上面的img标签,略微有点区别,比如JSX用className
而不是class
.
上面的数据是静态的,3个头像一模一样,如果要改成下面这样,头像数据由参数传入,展示不同的内容,该如何做呢?
React里面父组件传给子组件的参数统称 Props,因此 Profile组件可以改成下面的
function Profile({ name, imageUrl }) {
return (
<img
className="avatar"
src={imageUrl}
alt={name}
/>
);
}
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile
name="Lin Lanying"
imageUrl="https://i.imgur.com/1bX5QH6.jpg"
/>
<Profile
name="Gregorio Y. Zara"
imageUrl="https://i.imgur.com/7vQD0fPs.jpg"
/>
<Profile
name="Hedy Lamarr"
imageUrl="https://i.imgur.com/yXOvdOSs.jpg"
/>
</section>
);
}
其中src={imageUrl}
里面的{}
花括号用于执行JS代码。
上面实现了 Profile 组件动态取数,但是Gallery里面还是写死了3个。一般来说这种头像列表的数据都是通过接口返回的,数量不确定,为了适应动态列表,我们可以将代码改为如下,完整参考这里
export const people = [{
id: 0,
name: 'Creola Katherine Johnson',
imageId: 'MK3eW3A'
}];
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
{people.map(person => (
<Profile
key={person.id}
name={person.name}
imageId={person.imageId}
/>
))}
</section>
);
}
最终展示如下图
添加交互
上面显示如何展示一个列表,但是缺少交互比如加入购入车,toggle操作,轮播图点击显示下一个张图。
在React里面,用state
变量来记录组件的状态。
如果要使用state涉及useState
函数。这种以useXXX为开头的函数称为Hook,其主要作用就是让函数变成React的组件。useState入参是state变量的初始值,返回state变量和一个设置state变量值的函数。
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);
比如上面调用了useState函数2次,分别返回了index和showMore两个state变量,分别对应setIndex和setShowMore更新函数。
useState(x)里面的x入参可以是基本类型,也可以是对象或者数组,下面看一个todolist的例子,完整版这里
export default function List() {
const [name, setName] = useState("");
const [artists, setArtists] = useState([]);
return (
<section>
<h1>伟大的诗人</h1>
<input value={name} onChange={(e) => setName(e.target.value)}/>
<button
onClick={() => {
//添加到列表
setArtists([...artists, { name: name }]);
//清空
setName("");
}}
>
Add
</button>
<ul>
{/* //遍历 */}
{artists.map((artist) => (
<li>{artist.name}</li>
))}
</ul>
</section>
);
}
- 调用useState 2次分别定义了name和artists两个state变量。其中name用于存储input的值,artists是个数组,循环遍历用来展示取到的值
- 监听input的onChange事件,调用setName函数给name赋值。然后将name用setArtist函数添加到数组里面
- 在ul中,
{}
表示jsx里面执行js语法,遍历输出列表
管理state
state初始值可以是基本类型也可以是对象数组,除了state,我们还有个props。
因此如何更好的管理state,其核心思想是避免重复定义state
需要遵守下面几条原则:
- 如果是常量,不要定义在state里面
- 如果是props里面的值,不要定义在state里面。
- 如果某个值可以通过其他属性计算出来,不要定义在state里面。
- 多个子组件存在排它操作,将state提升到父组件。
前面3条很好理解,主要是第四条排它操作。这种情况一般出现在一个列表需要高亮某一行的情况。为了高亮某一行,我们必须要有一个变量比如activeIndex记录具体哪行被高亮了,这时候,这个activeIndex定义在父组件里面比较合适。
排它操作例子源码