目录
安装浏览器扩展
用Chrome的去极简插件下载。
React创建项目有多种方式
- 传统方式使用 create-react-app
- 也可以使用vite
create-react-app
npx create-react-app my-app
vite
npm create vite@latest 项目名 -- --template react
或者直接
npm create vite@latest 项目
React组件
react组件分为两种组件,一种叫类组件,一种叫函数式组件,函数式组件速度更快,性能更好,但是有先天的缺陷,最开始react开发,使用的类组件+函数式组件的开发方式。在React16.8之后推出hooks,弥补了函数式组件的缺陷,所以新的开发方式变成了函数式组件+hooks的开发方式。这个东西就像Vue2到Vue3转变一样。
JSX
是一个 JavaScript 的语法扩展。我们建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模板语言,但它具有 JavaScript 的全部功能。
可以借助Vue对JSX的介绍了解和vue模板的区别
h('div', {
id: "box",
className: "container"
}, "内容")
转换为JSX
<div id="box" className="container">内容</div>
这个不是一个字符串,也不是html标签,这个语法叫jsx
h('div', {}, [
h('span', '内容'),
h('span', '内容'),
h('span', '内容')
])
h('div', {}, [
h('span', '内容'),
h('span', '内容'),
h('span', '内容')
])
插值
如果想要插值,使用 {} 变量需要在当前函数中
function App () {
let msg = "Hello React"
return (
<div>{msg}</div>
)
}
虽然这种方式可以插值,但是如果我们想要值能够被更改,就需要使用第一个hookuseState
import { useState } from 'react'
function App () {
let [msg] = useState("Hello React")
return (
<div>{msg}</div>
)
}
useState就像是Vue3中的ref,用来声明一个具有数据响应式的变量。只不过useState返回的是一个数组,这个数组的两个值分别是
1. 初始值
2. 设置这个值的函数
列表渲染
如果我们有一个数组,我们想要渲染成一个列表,需要借助`map`生成一个jsx数组,例如
[1, 2, 3] 需要转换成 [<li>1</li>, <li>2</li>, <li>3</li>]
function App() {
let stus = ["张三", "李四", "王五"]
return (
<div>
<h1>学生列表</h1>
<ul>
{
stus.map((stu, index) => <li key={index}>{stu}</li>)
}
</ul>
</div>
)
}
export default App;
如果是复杂的数据呢???假如我们的数组中包含的是对象
let stus = [
{
name: "张三",
age: 18,
sex: "男"
},
{
name: "李四",
age: 20,
sex: "男"
},
{
name: "王五",
age: 18,
sex: "男"
}
]
function App() {
let stus = [
{
name: "张三",
age: 18,
sex: "男"
},
{
name: "李四",
age: 20,
sex: "男"
},
{
name: "王五",
age: 18,
sex: "男"
}
]
return (
<div>
<h1>学生列表</h1>
<ul>
{
stus.map((stu, index) =>
(
<li key={index}>
<span>{stu.name}</span>
<span>{stu.age}</span>
<span>{stu.sex}</span>
</li>
)
)
}
</ul>
</div>
)
}
export default App;
条件渲染
jsx中不支持if else操作,但是支持三元运算,所以可以在对应的位置上展示相关的操作
function App() {
let status = true
return (
<div>
{
status ? <div>status为true时显示</div> : <div>status为false时显示</div>
}
</div>
)
}
export default App;
如果组件只是需要返回一个简单的结构,我们可以使用return操作来解决问题
function App() {
let status = false
if (status) {
return <div>status为true时显示</div>
}
return <div>status为false时显示</div>
}
export default App;
事件
react的事件绑定很好理解
<标签 on事件类型={函数体}>
比如我们要触发一个点击事件
function App (){
let clickHandler = () => {}
return (
<button onClick={clickHandler}></button>
)
}
如果我们需要给事件函数中传递参数,那么需要在函数体外包裹箭头函数
function App (){
let clickHandler = (num) => {}
return (
<button onClick={() => clickHandler(2)}></button>
)
}
建议大家养成习惯,传不传参都放在箭头函数中
<标签 on事件类型={() => 要调用的函数}>
在React事件中,如何传递事件对象
let 事件函数 = (形参1, 形参2, 事件对象形参) => {}
<button onClick={(e) => 事件函数(参数1, 参数2, e)}>
如果需要获取到我们输入框中的值,可以使用`e.target.value`
<input type="text" onChange={(e) => console.log(e.target.value)}/>
绑定动态属性
如果想要在标签上的属性中绑定动态值
let 变量名 = "值"
<标签 属性名={变量名}>
如果要去设置样式,我们在jsx中必须以下方的写法去定义样式
<标签 style={{属性名: 属性值, 属性名2: 属性2}}>
两个大括号并非双大括号写法,而是一个大括号中包了一个对象。在这个对象中,我们可以直接使用动态值
let color = "blue"
<标签 style={{属性名: 属性值, 属性名2: 属性2, color: color}}>
如果是动态设置class,react中不支持向vue一样`:class="['box1', boxname, {active: isActive}]"`的写法,如果我们想要实现这种写法,需要借助`classnames`库
npm i classnames
import classnames from 'classnames';
// 用法和vue的class绑定类似
let btnClassName = "btn4" // 表示可以直接被修改的变量
<button className={classnames('btn', 'btn2', 'btn3', btnClassName, {'btnactive': false})}>按钮</button>
组件
React的组件和Vue的思想一样,只不过结构不同,React组件是一个函数
function 组件函数名() {
return (
<div></div>
)
}
export default 组件函数名
如果想要使用组件
import 组件名 from 'path'
<div>
<组件名></组件名>
</div>
props
React中如何获取到组件标签上的属性值
<组件标签 属性名="属性值"></组件标签>
在子组件中
function 子组件(props) {
return (
<div>
{props.属性名}
</div>
)
}
我们也可以直接解构
function 子组件({属性名}) {
return (
<div>
{属性名}
</div>
)
}
注意!!!!!props中有一个关键的属性名为children,这个表示,我们直接写在组件标签中的内容,就是我们的vue中的slot
<子组件标签>内容</子组件标签>
在子组件中
function 子组件(props) {
return (
<div>
{props.children}
</div>
)
}
也可以直接解构
function 子组件({children}) {
return (
<div>
{children}
</div>
)
}
封装一个房子组件,组件中包含了一个卧室组件,一个卫生间组件,卧室组件中包含一个床组件,床上有个dog组件
房子
卧室
床
狗
卫生间
状态提升
本该在组件Child的状态,因为有其他组件需要使用,我们就需要把这个状态提升到共同祖先组件上
在React不存在向vue一样的通信方式,数据的传递从父组件到子组件都是通过props。但是从子组件到父组件,两者的思想不同
- Vue 父组件需要什么值,在子组件通过调用emit传递过去,父组件创建好接收的函数,绑定对应的自定义事件即可。
- React 父组件需要什么值或者什么操作,父组件准备好修改这个值方法,然后通过props将方法传递给子组件,子组件调用即可。
// Child.vue
<template>
<button @click="clickHandler">点击传递一个1到父元素</button>
</template>
<script setup>
let clickHandler = () => {
emit('自定义事件', 1)
}
</script>
// Parent.vue
<template>
<Child @自定义事件="getNumber"></Child>
</template>
<script setup>
let getNumber = (num) => {
// num就是1
}
</script>
React
let Child = ({父组件传来的函数}) => {
return (
<button onClick={() => 父组件传来的函数(1)}>点击传递一个1到父元素</button>
)
}
let Parent = () => {
let getNumber= (num) => {
console.log(num)
}
return (
<Child 父组件传来的函数={getNumber}></Child>
)
}
如果子组件在封装时,想要实现某个功能,我们就可以去触发一个函数,但是触发前需要确定函数是否存在
//函数名 && 函数名()
<button
disabled={disabled}
className={className}
onClick={(e) => {
e.stopPropagation()
onClick && onClick(e)
// 别人用我的组件时,可以给我传递一个名字为onClick的属性,属性值是一个函数
}}
>
{children}
</button>