React学习小笔记(更新中)

01.create-react-app的基础操作

安装脚手架

npm i create-react-app -g

create-react-app --version 检查版本

创建React工程化项目

create-react-app 项目名称

命名规范:使用数字、小写字母、下划线

react和react-dom和react-native和react-scripts

react:React框架的核心

react-dom:React视图渲染的核心(基于React构建WebApp----HTML页面)

react-native:构建和渲染App的

react-scripts:把webpack打包的规则及相关插件或loader都隐藏到node_modules目录下,react-scripts就是脚手架的中自己对打包命令的一种封装,会调用node_modules中给的webpack等进行处理

02.脚手架进阶应用

处理跨域

  1. 在src目录中新建setupProxy.js文件

  2. const { createProxyMiddleware } = require('http-proxy-middleware')
    module.exports = function (app) {
        app.use(
            createProxyMiddleware("/jian", {
                target: "https://www.jianshu.com/asimov",
                changeOrigin: true,
                ws: true,
                pathRewrite: { "^/jian": "" }
            })
        )
        app.use(
            createProxyMiddleware("/zhi", {
                target: "https://www.news-at.zhihu.com/api/4",
                changeOrigin: true,
                ws: true,
                pathRewrite: { "^/zhi": "" }
            })
        )
    }
    

03.jsx语法细节

vscode支持jsx语法

后缀名改为jsx

构建视图

获取页面中#root的容器,作为根容器(不能用body或html):

const root = ReactDOM.createRoot(document.getElementById('root'));

基于render方法渲染我们编辑的视图,渲染后的内容全部插入到#root中进行渲染

root.render(
  <div>fjl学习react</div>
);

每一个构建的视图,只能有一个根节点!!!

可以用<></>作为根节点,减少层级---->React.Fragment空文档标记标签,类似于vue的template

胡子语法

number / string:值是啥就渲染啥

boolean / null / undefined / Symbol / BigInt:渲染的内容为空

不支持渲染:普通对象

数组对象:把数组的每一项都分别拿出来渲染(不是变为字符串,没有逗号)

函数对象:不支持在{ }中渲染,但是可以作为函数组件

虚拟DOM对象(用React.createElement创建的)可以

给元素设置样式

行内样式要用对象写(驼峰命名),不能直接写字符串

<div style={{
      color: 'red',
      fontSize: '18px'
    }}>fjl学习react</div>

let styObj = {
	color:'red',
    fontSize:'16px'
}
<h2 className="title" style={styObj}></h2>

给元素设置class

要用className,不能直接用class

条件渲染

{flag ? <button>按钮2</button> : null}

列表渲染

没有类似于v-for的语法,使用数组的map进行列表渲染,key一定要写!

let data = [
  {
    id: 1,
    title: "列表渲染",
  },
  {
    id: 2,
    title: "列表渲染2",
  },
  {
    id: 3,
    title: "列表渲染3",
  },
];
root.render(
  <>
    <h2 className="title">今日新闻</h2>
    <ul className="news-box">
      {data.map((item, index) => {
        return (
          <li key={item.id}>
            <em>{item.id}</em>
            &nbsp;&nbsp;
            <span>{item.title}</span>
          </li>
        );
      })}
        
      {/* 单独渲染5次 */}
      {new Array(5).fill(null).map((_, index) => {
        return <button key={index}>按钮{index + 1}</button>;
      })}
    </ul>
  </>
);

04.jsx底层渲染机制

步骤

  1. 把编写的jsx语法编译为虚拟DOM对象

    1. 基于babel-preset-react-app,把jsx编译为React.createElement(ele,props,…children)这种格式(ele:标签,props:标签内的属性,…children:子元素)
    2. 把React.createElement方法执行,返回虚拟DOM(或称为JSX元素、JSX对象)
  2. 把构建的虚拟DOM渲染为真实DOM(基于ReactDOM中的render方法处理)

    重写render方法(v16):

    // 封装对象迭代方法
    // 如果基于传统的forin循环(性能较差,只能迭代可枚举、非symbol类型的属性)
    // 解决思路:获取对象所有的私有属性(私有的、不论是否可枚举、不论属性)
    // Object.getOwnPropertyNames(arr) -> 获取对象的非Symbol类型的私有属性
    // Object.getOwnPropertySymbols(arr) -> 获取Symbol类型的私有属性
    // 还可以用ES6中给的Reflect.ownKeys代替上述操作
    const each = function each(obj, callback) {
      if (obj === null || typeof obj !== "object") {
        throw new TypeError("obj is not a object");
      }
      if (typeof callback !== "function") {
        throw new TypeError("callback is not a function");
      }
      let keys = Reflect.ownKeys(obj);
      keys.forEach((key) => {
        let value = obj[key];
        // 每一次迭代都把回调函数执行
        callback(value, key);
      });
    };
    
    // render方法:把虚拟DOM渲染为真实DOM
    // V16
    export function render(virtualDOM, container) {
      let { type, props } = virtualDOM;
      // 存储的是标签名(动态创建标签)
      if (typeof type === "string") {
        let ele = document.createElement(type);
        // 为标签设置相关的属性 & 子节点
        each(props, (value, key) => {
          // className处理:value存储的是类名
          if (key === "className") {
            ele.className = value;
            return;
          }
          //  style处理:value存储的是样式对象
          if (key === "style") {
            each(value, (value, key) => {
              ele.style[key] = value;
            });
            return;
          }
          // children处理:
          if (key === "children") {
            let children = value;
            if (!Array.isArray(children)) {
              children = [children];
            }
            children.forEach((child) => {
              // 子节点是文本节点:直接插入即可
              if (typeof child === "string") {
                ele.appendChild(document.createTextNode(child));
                return;
              }
              // 子节点是虚拟DOM:递归处理
              render(child, ele);
            });
            return;
          }
          ele.setAttribute(key, value);
        });
        // 把新增的标签,增加到指定容器container中
        container.appendChild(ele);
      }
    }
    

视图更新时

第一次渲染完毕后,会把创建的虚拟DOM缓存起来,当数据改变时,JSX创建全新的虚拟DOM,使用diff算法,与之前缓存的虚拟DOM进行比对,生成Patch补丁包(不同的部分),最后只渲染补丁包

05.函数组件

使用方法

在src目录中,创建一个xxx.jsx的文件,就是要创建一个组件

在文件中创建一个函数,让函数返回JSX视图(虚拟DOM对象)

组件名首字母大写!!!!

// 参数props是一个对象,是接受的属性
const DemoOne = function DemoOne(props) {
  console.log(props);
  return (
    <div className="demo-box">
      我是DEMO-ONE
      <div className="title">{props.title}</div>
    </div>
  );
};
export default DemoOne;

调用:

import DemoOne from "./views/DemoOne";
root.render(
  <>
    <DemoOne title='这是title'></DemoOne>  // 双闭合(可以放子节点)
    <DemoOne/>	// 单闭合
  </>
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值