react学习前置预备
榜首步安装vite
在项目中初始化vite
在命令行中全局安装vite
npm i -g vite
npm create vite
在vite中选择react的根底装备
依据提示选择对应的框架即可
在跳转到建立的项目文件夹中
cd ***(创立的项目文件夹的姓名)
装备vite的依赖包
npm i
履行对应的vite命令即可
npm dev
React的根本知识
(在vite东西的协助下,不需要留意这些)
根本的React了解
名称 | 介绍 |
---|---|
babel.min.js | 主要将Jsx转换成js格局 |
react.development.js | React中心库 |
React-Dom.delelopment.js | 用于支撑React操作Dom |
引进的顺序
- 先引进中心库react.development.js
- 在引进react-dom,用于支撑react操作dom
- 最后引进babel,用于将Jsx转换成js,让后创立dom
- 假如运用vite等打包脚手架东西,则不需要以上过程
写react的预备
-
写react代码要注明
<script type="text/babel">
在末尾引进,这样浏览器才知道写的是Jsx的代码
-
操控台上favicon.ico 的警告提示,在项目文件的根目录中放一张ico偏爱图标即可,图标姓名一定要为favicon.ico,否则浏览器查询不到
了解react的简略运用办法
开端预备容器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
//引证react
<script type="text/javascript" scr="../js/react.development.js"></script>
<script type="text/javascript" scr="../js/react-dom.development.js"></script>
<script type="text/javascript" scr="../js/babel.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="test"></div>
//预备容器,用于放置react烘托的dom
</body>
</html>
创立虚拟Dom,并烘托到界面上
<script type="text/babel">
//创立虚拟dom
const vm=<h1>hello,react</h1>
//也能够写成括号包裹方法,便于观看,如下
const vm=(
<h1>hello,react</h1>
)
//经过js创立虚拟dom,这样不用引进babel.min.js
const vm= react.createElement('h1',{id:'test'},'hello,react')
//烘托虚拟dom到页面
ReactDom.render(vm,document.getElentById"test")
</script>
jsx终究在浏览器中呈现的格局都是js方法,如上方格局,不过常用的是其语法糖方法
假如用js创立虚拟dom,榜首部分写标签名,第二部分写标签特点,以目标的方法写,可在内写多个特点,第三部分写标签内容
标签内容中可嵌套
const vm= react.createElement('h1',{id:'test'},react.createElement('span',{id:test1},'你好'))
关于虚拟DOM
-
实质是object类型的目标
-
由于虚拟dom在react的内部运用,不需要太多的特点,所以虚拟dom的特点较少,所以比较”轻”,速度更快
-
虚拟DOM终究会被react转换成实在DOM,呈现在页面
-
jsx是resct界说的一品种xml的js扩展语法
xml语法
<student>
<name>tom</name>
<age>18</age>
</student>
xml语法现在根本被json语法替代
{
'name':'tom',
'age':'18'
}
jsx的语法规则
-
界说虚拟DOM时不要写写引号
-
标签中混入js表达式时要用{}号包裹
-
样式的类名指守时不要用class,用className,防止与js语法混搅
-
jsx中css的内联样式要用style={{key:value}}的双括号方法去写,本来js中要引证css内联样式应写style=”key:value”
-
虚拟标签dom只用一个根标签,一个根标签对应一个虚拟DOM,假如有多个同级虚拟DOM,要用一个标签将其包裹
-
标签必须闭合,所以像input这种单标签,要写成以下方法
<input type='text'/>
-
标签首字母,假如是小写字母,则将标签转成html的同名标签元素;假如是大写字母最初,则将其烘托成react组件
小比如
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
//引证react
<script type="text/javascript" scr="../js/react.development.js"></script>
<script type="text/javascript" scr="../js/react-dom.development.js"></script>
<script type="text/javascript" scr="../js/babel.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="test"></div>
//预备容器,用于放置react烘托的dom
</body>
<script type="text/babel">
const myId='zs'
const myData='hello'
//创立虚拟dom
const vm=(
<div>
//假定title为假定外联式的css
<h2 className='title' id={myId.tolowerCare()}>
<span style={{color:'white',font:'29px'}}>{myData.tolowerCare()}</span>
</h2>
<input type='text'/>
</div>
)
</script>
</html>
简略理解:
- 表明固定的字符串就用正常的 ‘ ‘ 和 ” ” 的引号,如 className=’title’
- css内联式用{{ }}号
- 自界说的js表达式就用{ }号
- 类名用className
- 原因解析:原js语法中标签都是’ ‘方法,都是字符串,没有变量的概念;所以jsx语法中用js表达式(实质上是变量赋值)时用的是{ }号;而css内联式是键值对的方法,便不能够用单括号,便用{{ }}双括号来表明
小比如 动态将数组中的名称建立到列表标签中
<script type="text/babel">
const data=['zs','ls','ww']
const vm=(
<div>
<ul>
{data.map((item,index)=>{
return <li key={index}>{item}</li>
//react为了diff算法,其中的标签中都要赋予唯一的key值
//比如中的key值赋予的有问题,在进行数组拼接时会呈现key值重复
}
)}
</ul>
</div> )
</script>
函数式组件
<script type="text/babel">
function Dome(){
return <h2>函数式组件</h2>
}
//烘托虚拟dom到页面
ReactDom.render(<Dome/>,document.getElentById"test")
</script>
该自界说函数this本应指向window,可是经过babel翻译后,敞开了严厉方法,进制来this指向window指向window,所以查看时,该this为undefined
严厉方法敞开 “use strict”
- react解析组件标签,找到Component组件
- 发现是组件是函数界说,随后调用该函数,将虚拟Dom转为阵势dom
- 呈现在页面中
函数式组件的props
props
传递过来的特点是只读的,假如想修正能够弄一个值接受一下,可是不能直接操作props
Object.freeze(obj)冻住,不能修正,不能增删,不能绑架
Object.seal(obj)密封,能修正,不能增删,不能绑架
Object.preventExtensions(obj)不行扩展,能修正,不能新增
import React from "react";
import PropTypes from 'prop-types';
Person.propTypes={
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number
}
//对函数组件的props做约束,由于不是类,所以不能用类的静态办法,只能运用函数Person中办法
//假如运用ts,该插件能够不再运用
Person.defaultProps = {
sex: "男",
age: 18,
};
//与上同理
function Person(props){
//创立函数并接受props
const {name,sex,age}=props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age 1}</li>
</ul>
);
}
export default Person;
props.children
子组件中假如不存在内容,props.children,就为null
子组件中假如存在一个标签,props.children,就为该标签的目标,能够在大胡子语法中直接烘托
props一般是用来传值,而props.children
是 React 中的一个特别特点。它允许你在组件标签内传递子元素。例如:
<MyComponent>
<p>Hello, world!</p>
</MyComponent>
在 MyComponent
组件内部,能够经过 props.children
特点来访问子元素 <p>Hello, world!</p>
。这样,MyComponent
组件就会将子元素 <p>Hello, world!</p>
显现在自己的内容区域中。
function MyComponent(props) {
return (
<div>
{props.children}
</div>
);
}
子组件中假如存在多个标签,props.children,就为该标签的目标数组,能够在大胡子语法中选择性烘托,以及调整烘托方位
<MyComponent>
<p>Hello, world!</p>
<p>你好,国际</p>
</MyComponent>
function MyComponent(props) {
return (
<div>
{props.children[1]}//你好,国际
{props.children[0]}//Hello, world!
</div>
);
}
子组件中存在多个标签,还能够给组件子元素加上一个slot=’???’的特点作为姓名,props.children,就为该标签的目标数组,能够在大胡子语法中选择性烘托,以及调整烘托方位
<>
<Hello>
<p slot="0">123</p>
<p slot="1">234</p>
</Hello>
</>
<>
<div>
{props.children.map((item) => {
if(item.props.slot==="1"){
//留意item.props,是props.children.props不是props
return item
}
})}
{props.children.map((item) => {
if(item.props.slot==="0"){
//留意item.props,是props.children.props不是props
return item
}
})}
//这么写也行
<>
<div>
{props.children.map((item) => {
return item.props.slot==="1"&&item
})}
</div>
</>
</div>
</>
子组件被多次调用,还能够给组件加上一个slots=’???’的特点作为组件姓名,props.children就为该标签的目标数组,能够在大胡子语法中选择性烘托,以及调整烘托方位
一般是弄个变量在上面接纳好,再在下面运用,防止下面的代码太长
<>
<Hello>
<p slot="0">123</p>
<p slot="1">234</p>
</Hello>
<Hello slots="3">
<p >456</p>
</Hello>
</>
<>
<div>
{
props.slots=='3'&&props.children
}
{
props.slots==null&&props.children
}
</div>
</>
props.render
在React中,一个组件的props是经过props特点传递给它的,能够运用props来获取组件传递的数据。而render函数是一种用来创立组件的办法,它能够将组件烘托到页面上。能够将render函数作为组件的一个特点传递给组件,并在组件的render办法中调用该特点。这样,能够完成动态生成DOM元素或者履行一些逻辑的功用。
例如,能够界说一个MyComponent组件,并将一个带有render函数的props传递给它,如下所示:
<MyComponent render={() => <span>Hello World</span>} />
function MyComponent(props) {
return <div>{props.render()}</div>;
}
在上面的比如中,MyComponent组件接纳一个名为render的props,它是一个函数,回来一个带有Hello World文本的span元素。在MyComponent组件的render办法中,调用了props.render函数,并将其回来的元素烘托到了页面上。
经过这种方法,能够在组件内部动态生成DOM元素,而且能够依据需要完成更为复杂的功用。
两者的区别
props.render
是一个函数,它接纳一些参数并回来一个组件。一般用于在父组件中动态地烘托子组件。例如:
function Parent(props) {
return (
<div>
{props.render()}
</div>
)
}
function Child() {
return (
<h1>Hello, world!</h1>
)
}
function App() {
return (
//在标签内特点界说一个回调
<Parent render={() => <Child />} />
)
}
props.children
表明组件的子元素。它能够是一个组件,也能够是多个组件。React会将children作为props传递给父组件,然后允许我们在组件内部运用组件。例如:
function Parent(props) {
return (
<div>
{props.children}
</div>
)
}
function Child1() {
return (
<h1>Hello, world!</h1>
)
}
function Child2() {
return (
<p>This is a paragraph</p>
)
}
function App() {
return (
//在标签内容界说组件
<Parent>
<Child1 />
<Child2 />
</Parent>
)
}
因而,props.render
用于动态地烘托子组件,而props.children
用于将现已存在的组件作为父组件的子元素。
函数式组件的useState
useState的运用
import React from 'react'
function Index () {
//类式组件改动状况的样式,和下面函数式组件比照学习
// state={count:0}
//add=() => {
//this.setState({count:count 1})
//}
//对状况的数组进行解构赋值,数组榜首个参数是状况名;第二个参数是改动状况的函数。相当于setState
const [count,setCount]=React.useState(0)
const [name,setName]=React.useState('jack')
function add() {
//在事情回调的函数中触发对应状况的函数
setCount((count) => {
return count 1}
)
}
function changeName() {
//像这种简略的改动,直接向set***中传入参数即可
setName('tom')
}
return (
<div>
<h1>当时求和为{count}</h1>
<h1>{name}</h1>
<button onClick={add}>点击加一</button>
<button onClick={changeName}>点击换名</button>
</div>
)
}
export default Index
闭包和音讯队列的打扰
import { useState } from "react";
function Hello() {
const [count, setCount] = useState(0);
const [name, setName] = useState("jack");
// 函数式组件每次烘托,都是函数的从头创立,所以就产生了闭包问题
//useState,只要榜首次设的初始值会生效,后续的值都是setState函数的回来值
//也是由于useState只要榜首次会履行,所以像对初始数据处理的行为,能够直接在useState里写个回调处理
//从头创立的组件函数拿到setState函数的回来值,完成界面上数值的更新
//由于新值是新创立的组件函数拿到的,所以在这里不经过处理拿到的都是没修正前的旧值
function add0() {
console.log("由于闭包只能显现旧值,会比界面上现实的值小一:",count);
setCount(count 1);
}
function add1() {
for (let i = 0; i < 10; i ) {
setCount(count 1);
}
}
//结果并不会加十,由于这里每次只能读到旧值
//所以虽然履行了10次,可是每次读取都是0,进行了十次0 1,结果就为1
function add2() {
for (let i = 0; i < 10; i ) {
setCount((count) => {
return count 1;
});
}
}
//结果会加十,由于这里每里用了回调函数完成了闭包,使值在回调函数中被记录了下来
//所以结果就为11
function changeName() {
setName("tom");
}
return (
<div>
<h1>当时求和为{count}</h1>
<h1>{name}</h1>
<button onClick={add0}>闭包,点击加一</button>
<button onClick={add1}>过错的点击加十</button>
<button onClick={add2}>正确的点击加十</button>
<button onClick={changeName}>点击换名</button>
</div>
);
}
export default Hello;
结论
state简略的修正就用直接用
涉及到对值重复修正就要考虑闭包问题,最好运用回调函数进行闭包记值
setStata修正呈现的问题
import { useState } from "react";
function Hello() {
const [count, setCount] = useState({
boyNum: 100,
girlNum: 100,
});
function addBoy() {
setCount({
...count,
//setState,每次都是将值从头赋值给新烘托的组件函数,所以不能独自烘托某一个值
//要将本来的值悉数展开,再修正某一个值,否则那些值就会丢掉
//假如一开端就想只修正特定的值,主张直接那些值拆开,不要放在一个目标
boyNum: count.boyNum 1
})
}
function addGirl() {
setCount({
...count,
girlNum: count.girlNum 1
})
}
return (
<div>
<h2>当时人数为{count.boyNum count.girlNum}</h2>
<h3>男生人数为{count.boyNum}</h3>
<h3>女生人数为{count.girlNum}</h3>
<button onClick={addBoy}>男生加1</button>
<button onClick={addGirl}>女生加1</button>
</div>
);
}
export default Hello;