Title

一、react认识

用于构建用户界面的 JavaScript 库

二、创建react项目:react脚手架

  1. 创建react项目,创建新的react应用

npx create-react-app my-app
cd my-app
npm start
  1. 分析react项目

    node_modules:依赖包

    public:公共文件

    src:核心代码

    App.css:根组件的样式

    App.js:更组件

    App.text:根组件的测试文件

    index.css:全局样式

    index.js:入口文件,特点是这个文件中写的代码,都会被执行,在这个项目启动的时候

     reportWebVitals:兼容浏览器

     setTests.js:做测试

  1. 分析index.js 入口文件

//入口文件
import React from 'react';  //引入react=》获取到react 提供api
import ReactDOM from 'react-dom/client'; //将 虚拟dom => 真实dom
import './index.css'; //全局样式
import App from './App';  //引入根组件

console.log(ReactDOM);
//将 虚拟dom => 真实dom =挂载到对应的位置
const root = ReactDOM.createRoot(document.getElementById('root'));  //挂载到对应的位置
root.render( //虚拟dom => 真实dom
 
    <App />

);

三、jsx

  1. 什么是jsx

    就是JavaScript和html的结合

  1. 特点:

    1. 可以js:就是vue指令,

    2. 更加的安全

  1. 相对于html的区别

    1. 类名:className

    2. 事件处理:on事件类型

四、指令

1:动态数据

  语法:{ }

  在{ }内可以写:1. 动态值,2. 四则运算,3. 三元运算符,4. js语法

  在react函数体中定义的的数据是不可变数据:

function App(){
  //函数体 => vue3 script  setup
  //定义数据 =》可变  ,不可变
  let name = '张三'
  let age = 30
  let num = 61

  function add(){
    return 1+1
  }
    return(
        <div>
            <h2>你好{name}同学</h2>
            <h2>{age+1}</h2>
            <h2>{num>60?'及格':'不及格'}</h2>
            <h2>{add()}</h2>  
        </div>
    )
}

export default App
2:条件渲染
  1. 单个条件判断:语法:{ } + 三元运算符

  2. 多个条件判断:语法:{ } + 定义方法

//   条件判断  
 
/* 
        条件判断 => 如果不显示 => 元素是不创建的(相当于v-if)
        单个:  => 语法  => {} +  三元运算符
        多个:   => 语法 =>  {} + 定义方法

    JavaScript 
        条件渲染
*/

//  条件渲染 在react当中 处理条件渲染,单个
/// 语法: {}结合 三元运算符

// function App(){
//     let num=62;

//     return(
//         <div>
//             {/* 处理单个条件判断 */}
//             {
//                 num>=60?<Children>及格</Children>:<div>不及格</div>
//             }
//         </div>
        
//     );

//     function Children(){
//         return (
//             <div>及格</div>
//         )
//     }
// }


// 多个
// 语法 => {}+处理方法
// 大于60 到 70 => 及格     大于85 优秀

function App(){
    console.log('created');
    // 本质 => 函数体 => 默认组件的声明周期 => created  => 初始化属性
    
    let num=68;
    
    function changeNum(){
        if(num>=60 && num<=70){
            return (
                <div>及格</div>
            )
        }
        else  if(num>70&&num<85){
            return (
                <div>良好</div>
            )
        }
        else if(num>=85){
            return(
                <div>优秀</div>
            )
        }
        else{
            return (
                <div>不及格</div>
            )
        }
    }

    return(
  
            <div>
                {/* 处理多个条件判断 */}
                {changeNum()}
            </div>
    )
}

// 导出export
export default App
3、列表渲染
  1. 作用:当布局有相同时候,如果有多个,我们可以使用列表渲染

  2. 语法:{ } +map

  3. map:数组循环,返回一个新的数据

  4. 注意:使用循环需要添加key,为什么需要添加key?因为底层更新(列队的数据)通过key 来判断是否是相同的元素,如果是就复用,如果不是就 重新创建,底层diff算法

function App(){
    let list=['🍉','🍇','🍍','🍌','🍈']; 

    // let arr=list.map((item,index)=>{
    //     return item
    // })
    return(
        <div>
            {/* 旧的写法 */}
            {/* <h2>🍉</h2>
            <h2>🍇</h2>
            <h2>🍍</h2> */}

            {
                list.map((item,index)=>{
                    return (
                        <h2 key={index}>{item}</h2>
                    )
                })

            }            
        </div>
    );
}

export default App
4、动态属性
  1. 动态样式

  1. 语法:就是元素上的属性 className={}

                        data-num={num} 是自定义属性,自定义属性以data- 开头

import './App.css'

//动态样式
//语法=》就是我们的元素   上的属性={}
// data-num={num} 是自定义属性
function App(){
   let num = 11
    return(
        <div>
            <h2 className={num>10?'itemActions':''} data-num={num}>张三</h2>    
        </div>
    )
}
export default App
5、事件处理
  1. 语法: on事件类型={嵌套函数},

  2. 给元素添加事件:语法:on事件类型 = {()=>事件处理函数() },onClick={ ()=>事件处理函数() }

  3. 为什么要写一个嵌套函数:因为 react 将模板内容(jsx语法) 变成 虚拟dom(React.createElement()); 如果发现有事件处理,将所有事件 合成 一个事件,自动执行第一层

  1. 事件传递参数:本质就是一个 函数的声明和函数的调用

  2. 事件对象:事件的嵌套函数第一层,事件的第一个参数,就是事件对象(e)

  3. 事件冒泡:阻止事件冒泡,方法:事件对象.stopPropagetion()

//  事件处理
// 语法: on事件类型={嵌套函数}

// 给元素添加事件
// 语法:on事件类型 = {()=>事件处理函数}

// 1 为什么要写一个嵌套函数
// 因为 react => 将模板内容(jsx语法) =>  变成 虚拟dom(React.createElement())

// 如果发现有事件处理,将所有事件 合成 一个事件,自动执行第一层

// function App() {
//   let changeAdd = () => {
//     console.log("触发事件");
//   };
//   return (
//     <div>
//       <h2>你好 同学</h2>
//       <button onClick={()=>changeAdd()}>点击触发</button>
//     </div>
//   );
// }
// export default App

// 事件传递参数 =>  本质就是一个 函数的声明和函数的调用

// function App(){
//     let changeAdd=(...a)=>{
//         console.log("事件触发",a);
//     }
//     return(
//         <div>
//             <h2>你好同学</h2>
//             <button onClick={()=>changeAdd('100','200',
//             '300')}>点击传参</button>
//         </div>
//     )
// }


// 3 事件传参 => 事件的嵌套函数第一层,事件的第一个参数,就是事件对象
// function App() {
//   let changeAdd = (e) => {
//     console.log("事件对象", e);
//   };
//   return (
//     <div>
//       <h2>你好 玲儿</h2>
//       <button onClick={(e)=>{changeAdd(e)}}>点击传递事件对象</button>
//     </div>
//   );
// }


// 事件冒泡
    // 方法:事件对象.stopPropagetion()
    function App(){
        let changeAdd=(e)=>{
            e.stopPropagation();    // 阻止事件冒泡
            console.log('子组件事件对象',e);
        }
        let fatherC=()=>{
            console.log('father')
        }

        return(
            <div onClick={()=>{fatherC()}}>
                <h2>你好 玲儿</h2>
                <button onClick={(e)=>changeAdd(e)}>点击看看有没有冒泡</button>
            </div>
        )
    }

export default App;
6、双向数据绑定:受控组件
  1. 双向数据绑定:可以在逻辑层获取到视图层数据,又可以将这个数据传递视图层

  2. 工作中使用的场景? 获取到用户的数据=》from 表单系列的

  3. 受控组件:就是用户可以修改js层的数据,这样的组件就叫做受控组件

// 处理动态数据 => useState
import { useState } from "react";
// useState()=> 返回值 => [数据,修改数据的方法]

// 实现双向数据绑定
// 1 input 元素的动态属性
// 2 给input元素绑定事件  input
// 3 获取input 事件触发输入内容 => 通过事件对象
function App() {
  // 逻辑层
  let [name, setState] = useState("");

  // 接收视图层输入的值
  const changeInput = (e) => {
    console.log(e.target.value); //获取到用户输入的内容

    // 4 需要把获取到用户的内容再赋值给动态数据   => name
    setState(e.target.value);
  };

  return (
    <div>
      用户名称:<input value={name} onInput={(e) => changeInput(e)}></input>
    </div>
  );
}
export default App;

 

五、组件

1、组件的创建:两种方式,函数的方式创建组件,class创建组件

函数组件

  1. 函数式组件就是函数

  2. 函数名称必须首字母大写:自己创建的组件

  3. 有return:就是自己写的页面布局(template)

  4. 这个函数体,第一层定义的属性,就是这个函数的属性、方法、动态数据

function App() {
  return (
    <div className="App">
       <h2>你好通信</h2>
    </div>
  );
}

export default App;

class组件

注意: class 这种方式创建组件不推荐,旧的方式

 

2、组件之间的数据传递

父组件给子组件传递数据

  1. 在父组件中通过属性方式传递数据 ,

  1. 子组件中props 接收这个数据

  2. 本质:元素(组件)添加属性,这个属性被react 底层自动处理成这个函数的参数=> { }类型

// 组件的数据传递
/* 
    1) 父组件给子组件传递数据
          方法 => 通过属性的方式
*/

import "../App.js";

function App() {
  let money = 100;
  const change = () => {};
  return (
    <div>
      这里是父组件
      {/* 父组件给子组件传递数据通过属性方式 */}
      {/* 本质 => 元素(组件)=> 添加属性 
        这个属性会react 底层自动处理成 这个函数的参数 => {}类型
      */}
      <Children money={money} data="5000" change={change}></Children>
    </div>
  );
}

function Children(props) {
  console.log(props); // object{change:()=>{},data:"5000",money:100}
  return <div>这是子组件 Children get father {props.data}</div>;
}

export default App;

 

子组件给父组件传递数据

  1. 在父组件中定义方法,

  2. 在父组件中通过属性方式传递这个方法,

  3. 在子组件中用props接收这个方法并调用,给这个方法并传入实参即为给父组件传递的数据

  4. 本质:函数的声明和函数的调用

// 组件的数据传递
/* 
    1) 子组件给父组件传递数据
        解决 方法 => 通过自定义方法
        本质  => 函数的声明和函数调用
*/

function App() {
  
  // 1. 在父组件中声明方法
  const getChildren = (value) => {
    console.log("获取到子组件的数据",value)
  };
  return (
    <div>
      这里是父组件
      {/*  2 再把这个方法传递给子组件 */}
      <Children getChildren={getChildren}></Children>
    </div>
  );
}

function Children(props) {
  console.log(props); // object{getChildren:()=>{}}
   const getFather=()=>{
    // 3 在子组件中调用父组件声明的方法
      props.getChildren(10000);
   }

  return (<div>
    <button onClick={()=>getFather()}>给父组件传递的数据</button>
  </div>);
}

export default App;

本地存放数据传递参数

sessionStorage、localStorage、cookies

3、组件的组合
  1. 组件的组合,相当于vue中的模块化处理

  2. 在react 只要有自己功能模块 => 进行抽离(模块化划分)

function App() {
  return (
    <div>
      {/* 页面级组件继承组合 */}
      <Swiper></Swiper>
      <CommentS></CommentS>
      <HotPlay></HotPlay>
      <LisBooks></LisBooks>
      <NewSong></NewSong>
    </div>
  );
}

 

六、react的更新机制:组件的重新创建

react的更新机制:重新创建组件(只要有数据更新,组件就会重新创建)

问题:就是在项目中,只要有数据更新,组件就会重新创建,会造成性能损耗

react组件更新机制:组件的重新创建,只要数据发生改变,组件就会重新创建,会造成性能问题

组件的渲染:先渲染父组件,在渲染子组件

问题1:在子组件中更新数据,如果没有将子组件进行模块化划分,那么父组件也会重新创建,会导致性能问题

解决方法:

  1. 模块化开发:组件的模块化划分,将子组件进行抽离(一个功能一个模块),此时:(子组件数据更新,该子组件会重新创建,其父组件与兄弟组件不会重新创建)

问题2:如果我们在父组件中更新数据 => 会重新渲染组件 => 这个父组件的嵌套组件(子组件),也会被重新渲染 => 会导致性能问题

解决方法:

   1. 缓存组件:React.mome(需要被缓存的组件); 缓存组件,不管父组件是否重新创建,这个子组件创建一次,如果子组件的数据没有改变,就不需要重新创建

// react 更新机制 => 组件重新创建
import React, { useState } from "react";

// // 组件模块化划分
// function App() {
//   console.log("father 组件重新创建了");

//   return (
//     <div>
//       {/* 模块化划分 */}
//       <Children2></Children2>
//       <Children1></Children1>
//     </div>
//   );
// }

// function Children2() {
//   console.log("children2222222222 组件重新创建");
//   let [salary, setSalary] = useState(1800);
//   const changeSalary = () => {
//     setSalary(salary + 200);
//   };
//   return (
//     <div>
//       月入{salary}
//       <button onClick={() => changeSalary()}>更新数据+200</button>
//     </div>
//   );
// }

// function Children1() {
//   console.log("children111111 组件重新创建");
//   return <div>children</div>;
// }



function App() {
  console.log("father 组件重新创建了");
  let [salary, setSalary] = useState(1800);
  const changeSalary = () => {
    setSalary(salary + 200);
  };
  return (
    <div>
      月入{salary}
      <button onClick={() => changeSalary()}>更新数据+200</button>
      {/* 
        不管父组件是否重新创建,这个子组件创建一次,如果子组件的数据没有改变,就不需要重新创建
      */}
      <Keepchildren1></Keepchildren1>
    </div>
  );
}

/* 
    React.memo()=> 缓存组件
    语法: React.memo(需要缓存的组件) => 缓存组件

    特点:
        缓存组件  如果这个组件属性值没有变化就不会创建,反之,就会重新创建
*/

function Children1() {
  console.log("children111111 组件重新创建");
  return (<div>children</div>)
}
let Keepchildren1=React.memo(Children1)
export default App;

// 1 组件的渲染 => 先渲染父组件,再渲染子组件
// 2 如果我们在父组件中更新数据 => 会重新渲染组件 => 这个父组件的嵌套组件(子组件),也会被重新渲染   => 会导致性能问题

// 解决方法(子组件数据更新,该子组件会重新创建,其父组件与兄弟组件不会重新创建)
    // 1 模块化开发 => 一个功能一个模块

 

posted on 2023-02-18 01:05  chccee  阅读(109)  评论(0编辑  收藏  举报