【React】学习笔记

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文为react学习笔记,自用。


一、React入门介绍

1.React是什么

     React是用于构建用户界面的 JavaScript 库;是一个将数据渲染为HTML视图的开源 JavaScript 库。

2.React特点

    声明式编码、组件化编码、React Native编写原生应用、高效(优秀的 Diffing 算法)。

3.React 高效的原因

    (1)使用了虚拟(virtual)DOM,不总是直接操作页面真实 DOM。(而且在操作真是dom之前,会比较两个不同的虚拟dom,比较出有差异的那一部分再去更新页面)

    (2)DOM Diffing 算法,最小化页面重绘。


二、配置环境

1.安装react.js(npm)

    (1)国内使用 npm 速度很慢,菜鸟建议我们使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:

    打开“命令提示符”,输入 :

npm install -g cnpm --registry=https://registry.npmmirror.com

    这样是安装成功。

    (2)接下来切换到镜像:

npm config set registry https://registry.npmmirror.com

    切换成功。

2.搭建react框架

    (1)安装 create-react-app 

    Create React App是React 提供的一个官方工具,用于快速搭建 React 项目;create-react-app 自动创建的项目是基于 Webpack + ES6。

    打开“命令提示符”,输入 :

cnpm install -g create-react-app

    这样create-react-app就安装成功了。

    (2)新建react项目

    在你喜欢的位置新建一个文件夹,我的文件夹名字叫react_start,在文件夹内右键,以管理员身份运行,输入:

create-react-app my-app

    创建成功。

    打开刚刚创建好的项目:

cd my-app/

    打开成功。

    运行项目:

npm start

    是否要在另一个端口上运行应用程序?    选-y

    运行成功。

  3.用vsCode打开react项目

    找到项目所在的文件夹,右键点击“通过Code打开”。(前提是电脑要有vsCode)

    4.下载插件(个人喜好)

    Code Spell Checker:检查是否有拼写错误

    Fitten Code : AI 编程助手,它可以自动生成代码,提升开发效率,调试 Bug。

    Simple React Snippets:可以通过缩写来触发代码片段,该插件会自动帮你补全,用于快速生成React组件结构。

插件根据自己需要进行安装,网上也有很多好用便捷的。


三、基本使用

    1.hello react

    打开文件,App.js是主组件文件,定义了一个基础的 React 组件。

    在App.js写入下面代码:

import "./App.css";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <p>hello react.</p>
      </header>
    </div>
  );
}

export default App;

    查看刚刚在浏览器运行的页面:

    2.State响应式

    State即组件要用的数据,react和vue的这类框架的核心就是把请求的来的数据展示在页面上,数据更新后也需要响应式的展示新数据。

    React中的state就类似于vue的data,用来做响应式的数据。

    新建在src 目录中新建一个文件夹components,在components文件夹里新建test1.jsx和test2.jsx文件。(写js的话 .js文件也没问题)

    test1:

//函数组件(组件的首字母必须大写)
import  { react ,useState } from "react";
function Test1(){
    let [ objA , setA ]= useState({
        a: 123
    })
    let b= "我是b";
    return(
        <div>
        <p>{objA.a}</p>
        <p>{b}</p>
    </div>
    )
}
//暴露 Test1
export default Test1;

    test2:

//class组件(要继承React的components)
import React from "react";//引入React
class Test2 extends React.Component {
    //写一个构造函数
    constructor(prop){
        super(prop)
        this.state = {
            //响应式数据
            a: 111,
            arr: [1,2,3,4,5]
        } 
    }
    render(){
        return(
            <div>
                <h1>Test2</h1>
                <p>{this.state.a}</p>
            </div>
        )
    }
}
export default Test2;

    App.js:

import Test1 from "./components/test1"; //引入Test1
import Test2 from "./components/test2"; //引入Test2
import "./App.css";

function App() {
  return (
    <div className="App">
      {/* 在页面上注册Test1、Test2组件 */}
      <Test1></Test1>
      <hr></hr>
      <Test2></Test2>
    </div>
  );
}

export default App;

    页面展示:

3.State的特点

    直接修改数据是无效的,必须通过对应的方法修改state才能触发视图更新;
    State得修改是一个浅合并得过程,是与原state对象合并的过程。

    test1 修改方式:

function Test1(){
    let [ objA , setA ]= useState({
        a: 123
    })
    let b= "我是b";
    setTimeout(() => {
        setA({
            a: 44225456434  //修改objA的值
        })
    }, 3000);
    return(
        <div>
        <p>{objA.a}</p>
        <p>{b}</p>
    </div>
    )
}

    test2 修改方式:(修改单个数据、数组、对象)

//class组件(要继承React的components)
import React from "react";//引入React
class Test2 extends React.Component {
    //写一个构造函数
    constructor(prop){
        super(prop)
        this.state = {
            a: 111, //单个数据
            arr: [1,2,3,4,5],  //数组数据
            obj: {name: "张三", age: 25}  //对象数据
        } 
    }
    render(){
        setTimeout(() => {
            let brr = this.state.arr;
            brr.push(9);
            let _obj = this.state.obj;
            _obj.age = 66;
            this.setState({
                a: 222,   //异步更新单个数据
                //arr: [6,7,8,9,10,11],  //创建了一个新的数组给它覆盖了
                arr: brr,  //在原数组上新增,注意每隔三秒都会新增一个元素
                obj:_obj //更新了对象中的age属性
            })
        }, 3000)
        return(
            <div>
                <h1>Test2</h1>
                <p>{this.state.a}</p>
                <p>{this.state.arr.join(",")}</p>
                <p>姓名:{this.state.obj.name}</p>
                <p>年龄:{this.state.obj.age}</p>
            </div>
        )
    }
}
export default Test2;

    3秒后页面变化: 修改成功

    4.循环渲染 

    (1)forEach: 全部在 test2中修改

        this.state = {
            arr: [
                 {title: "标题1", content: "内容1"},
                 {title: "标题2", content: "内容2"},
                 {title: "标题3", content: "内容3"},
                 {title: "标题4", content: "内容4"},
                 {title: "标题5", content: "内容5"},]
        } //存入数组对象

    render(){
            let arr = [];
            this.state.arr.forEach((item, index) => {    //forEach遍历数组,但要把结果存起来
               let _item =  <div key={index}>
                <h2  style={{color: "red"}}>{item.title}</h2>
                <p style={{color: "red"}}>{item.content}</p>
                </div>
                arr.push (_item);
            })  
        return(
            <div>
                { arr }
            </div>
        )
    }

​

    (2)map:


    render(){
        return(
            <div>
                {
                    //map会把数组中的每一项映射成一个新的数组
                    this.state.arr.map((item, index) => {
                        return (
                            <div key={index}>
                                <h2  style={{color: "red"}}>{item.title}</h2>
                                <p style={{color: "red"}}>{item.content}</p>
                            </div>
                        )
                    })      
                }
            </div>
        )
    }

    (3)函数:

    createArrList(){
        let arr = [];
        this.state.arr.forEach((item, index) => {    //forEach遍历数组,但要把结果存起来
           let _item =  <div key={index}>
            <h2  style={{color: "red"}}>{item.title}</h2>
            <p style={{color: "red"}}>{item.content}</p>
            </div>
            arr.push (_item);
        })  
        return arr;
    }
    render(){
        return(
            <div>
                {this.createArrList()}
            </div>
        )
    }

    页面展示:

    5.条件渲染

    在test1中修改:(这样写是整个<div>板块被换掉)

//函数组件(组件的首字母必须大写)
import  { react ,useState } from "react";
function Test1(){
    let [ objA , setA ]= useState({
        a: 123
    })
    let[show,changeShow]=useState(0);
    function showType(){
        if(show===0){
            return  <div color="blue" >我是showType,show=0</div>
        }else if(show===1){
            return  <div color="blue" >我是showType,show=1</div>
        }else{
            return  <div color="blue" >{show}</div>
        }
    }
    let b= "我是b";
    setTimeout(() => {
        setA({
            a: 44225456434  //修改objA的值
        })
    }, 3000);
    return(
        <div>
        <p>{objA.a}</p>
        <p>{b}</p>
        {showType()}
        <button onClick={()=>changeShow(show+1)}>点击切换</button>
    </div>
    )
}
//暴露 Test1
export default Test1;

    页面展示:

    6.事件绑定

    其实上面带了一个click事件了,就是click={  },注意一定要写花括号。

    事件传参的话用.bind(this,   ); 传参的过程中会把事件本身带回去,也就是下面代码中的“e”。

    let[show,changeShow]=useState(0);
    function changeDiv(num,e){
        console.log(num);
        console.log(e);
        let _show = !show;
        changeShow(_show);
    }

    function showType(){
        if(show){
            return  <div color="blue" >show存在</div>
        }
    }
 return(
        <div>
        {showType()}
                <button onClick={changeDiv.bind(this,111)}>{show? "隐藏":"显示"}</button> 
        </div>
    )

     页面展示:

  

    我这里遇到了一些问题,我想查看输出内容时,浏览器显示Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools。

    我用的谷歌,查了一下是需要下载react-devtools调试工具。

     下载方法:点击链接React Developer Tools - Chrome 应用商店-Chrome插件下载-收藏猫插件 (pictureknow.com)

     点击“下载插件手动安装”。下载好后解压,按照下图步骤添加扩展。

            

    这样点击按钮后就能在控制台看到传过去的参数和打印出来的e

    7.综合制作列表效果

    代码如下:综合上述所学。在components文件夹下新建tableList.jsx

import React from "react";

class TableList extends React.Component {
  constructor(prop) {
    super(prop);
    this.state = {
      type: 0,
      equipment: [
        { name: "电视", price: 10000 },
        { name: "空调", price: 20000 },
        { name: "冰箱", price: 30000 }
      ],
      trappings: [
        { name: "牛仔裤", price: 500 },
        { name: "连衣裙", price: 1500 }
      ]
    };
  }
  changeTap(item) {
    this.setState({ type: item });
  }
  showZero() {
    let _equipment = (
      <div>
        {this.state.equipment.map((item) => {
          return (
            <div>
              <span key={item.name}>{item.name}:</span>
              <span key={item.price}>{item.price}</span>
              <button
                style={{ marginLeft: 10, backgroundColor: "pink" }}
                onClick={this.deleteItem.bind(this, item.name)}
              >
                删除
              </button>
            </div>
          );
        })}
      </div>
    );
    return _equipment;
  }
  showOne() {
    let _trappings = (
      <div>
        {this.state.trappings.map((item) => {
          return (
            <div>
              <span key={item.name}>{item.name}:</span>
              <span key={item.price}>{item.price}</span>
            </div>
          );
        })}
      </div>
    );
    return _trappings;
  }

  deleteItem(name) {
    // let _equipment = this.state.equipment.filter((item) => item.name !== name);
    let _equipment = [];
    this.state.equipment.forEach((item) => {
      if (item.name !== name) {
        _equipment.push(item);
      }
    });
    this.setState({ equipment: _equipment });
  }

  showContent() {
    return this.state.type === 0 ? this.showZero() : this.showOne();
  }

  render() {
    return (
      <div>
        <button onClick={this.changeTap.bind(this, 0)}>设备列表</button>
        <button onClick={this.changeTap.bind(this, 1)}>服饰列表</button>
        {this.showContent()}
      </div>
    );
  }
}

export default TableList;

    8.样式操作

    (1)在标签中加className = "  "  ,可以直接在App.css里面写样式。

    (2)外联样式,一经加载将全局有效,所以类名在命名的时候要特别注意,避免全局污染,在components文件夹下新建tableList.css:

    tableList.jsx:

  import "./tableList.css";

<div className="table-list">
        <button onClick={this.changeTap.bind(this, 0)}>设备列表</button>
        <button onClick={this.changeTap.bind(this, 1)}>服饰列表</button>
        {this.showContent()}
      </div>

    tableList.css:

.table-list {
    position: absolute;
    margin-top: 5%;
    margin-left: 30%;
    box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
    background-color: #fff; /* 背景颜色 */
    border-radius: 8px; /* 圆角 */
    padding: 20px; /* 内边距 */
    width: 80%; /* 宽度 */
    max-width: 600px; /* 最大宽度 */
    overflow: hidden; /* 隐藏溢出内容 */
    transition: transform 0.3s; /* 添加过渡效果 */
  }

    页面展示:

    (3)CSS Modules模块化

    这种方式是webpack的方案,所有css只作用于当前组件,不会影响当前组件的后代组件,样式之间不会有冲突。

    如果要用这个方式,那么tableList.css的命名要写成tableList.module.css,且.css文件要与对应的.js文件放在同一个文件夹里。tableList.js修改的代码如下:

import style from "./tableList.module.css";

 <div className={style["table-list"]}>

    9.生命周期

引用一下B站大佬的图:

    (1)Mounting(挂载):已插入真实 DOM

    (2)Updating(更新):正在被重新渲染

    (3)Unmounting(卸载):已移出真实 DOM


总结

未完待续,持续更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值