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

引进的顺序

  1. 先引进中心库react.development.js
  2. 在引进react-dom,用于支撑react操作dom
  3. 最后引进babel,用于将Jsx转换成js,让后创立dom
  4. 假如运用vite等打包脚手架东西,则不需要以上过程

写react的预备

  1. 写react代码要注明

    <script type="text/babel">
    

    在末尾引进,这样浏览器才知道写的是Jsx的代码

  2. 操控台上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

  1. 实质是object类型的目标

  2. 由于虚拟dom在react的内部运用,不需要太多的特点,所以虚拟dom的特点较少,所以比较”轻”,速度更快

  3. 虚拟DOM终究会被react转换成实在DOM,呈现在页面

  4. jsx是resct界说的一品种xml的js扩展语法

    xml语法

<student>
<name>tom</name>
<age>18</age>
</student>

xml语法现在根本被json语法替代

{
 'name':'tom',
 'age':'18'
}

jsx的语法规则

  1. 界说虚拟DOM时不要写写引号

  2. 标签中混入js表达式时要用{}号包裹

  3. 样式的类名指守时不要用class,用className,防止与js语法混搅

  4. jsx中css的内联样式要用style={{key:value}}的双括号方法去写,本来js中要引证css内联样式应写style=”key:value”

  5. 虚拟标签dom只用一个根标签,一个根标签对应一个虚拟DOM,假如有多个同级虚拟DOM,要用一个标签将其包裹

  6. 标签必须闭合,所以像input这种单标签,要写成以下方法

    <input type='text'/>
    
  7. 标签首字母,假如是小写字母,则将标签转成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”

  1. react解析组件标签,找到Component组件
  2. 发现是组件是函数界说,随后调用该函数,将虚拟Dom转为阵势dom
  3. 呈现在页面中

函数式组件的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;