20230516----重返学习-react基础-业务开发思路

news/2024/11/30 1:42:16/

day-071-seventy-one-20230516-react基础-业务开发思路

react基础

  1. MVVM(Vue) 与 MVC(React)

    • MVVM: Model View ViewModel,双向数据驱动。
      • 基本构成:
        • Model:数据层
        • View:视图层
        • ViewModel:视图模型,Vue主要实现的。
    • MVC: Model View Controller,单向数据驱动。
      • 基本构成:
        • Model:数据层。
        • View:视图层。
        • Controller:控制层。
      • 学习这两类框架的基本思路:
        • 要学会如何构建数据与状态,以及修改状态的方法。
          • 例如:setState、useState…
        • 当基于特定的方法修改状态后,要学会通知视图更新。
          • Vue中会对对象的每一项进行get/set劫持
            • Vue2:Object.defineProperty
            • Vue3:Proxy
            • this.age=17 => 修改了对象中的某个属性 => 触发set劫持函数 => 通知视图更新。
            • 所以数据就有了响应式与非响应式数据的区别。
              • 响应式:经过get与set劫持的对象及对象属性。
              • 非响应式:没有经过get与set劫持的对象及对象属性。
          • React 并没有对数据进行特殊的处理。
            • this.state.age=17 => 只是单纯的修改值
            • this.setState({age:18}) => 只有基于特定的方法,进行修改状态值,才会让视图更新。
          • React的MVC框架中,实现了数据驱动视图渲染,也就是M->V。
            • 也就是说基本上要放弃DOM的手动更改,DOM更新需要数据进行修改之后的由框架来完成。
              • 实际操作中,就是返回一个jsx元素。
                • jsx元素就是一个数据。
                • 至于jsx元素如何转变成页面上的DOM结构,就交由React框架来做处理了。
        • 要学会如何构建视图。
          • 主要构建视图的方式:
            • Vue中是基于主要的template标签语法 与 jsx语法构建视图的。
            • React中构建视图的语法是:jsx。
          • 不论是Vue还是React,构建的视图都有一套编译机制:
            • VirtualDOM(虚拟DOM) -> DOM-diff -> 真实DOM。
        • 如果视图中的表单元素内容发生改变:
          • Vue会基于v-model指令,自动监听表单内容的变化,然后把对应的状态值进行自动更改,所以Vue是双向驱动的框架。
            • 具有视图驱动数据更新的机制,即V->M。
            • 也就是说,表单元素数据的更新,是Vue内部实现的。
              • 而vue的双向数据绑定,大多是需要使用表单元素才能驱动数据更新。
          • React默认没有实现视图驱动数据,需要开发者手动对表单元素进行事件绑定和监听,手动去修改对应的状态,所以React被称为单向数据驱动的框架。
            • 这个也就是说,主要通过对表单元素的处理监听,也大多可以双向绑定。只是这一步,需要让开发者自己去完成。
    • 具体到技术选型,主要看团队氛围与编程喜好,以及技术负责人。一般实际开发中的性能都差不多。
      • vue更简单些,招人也更容易。
      • React上限高些,更灵活。
  2. 关于版本问题。

    • Vue框架,涉及现代开发,一般都依赖于脚手架@vue/cli或vite。
      • Vue2 主流版本,目前2023年中国用得最多。
        • 全家桶:
          • @vue/cli – 脚手架。
          • Vue2 – Vue核心。
            • 做双向数据绑定。
          • Vuex3 – 做全局状态管理。
          • VueRouter3 – 做页面路由跳转。
            • 根据路由显示与隐藏某些组件的。
          • UI框架:ElementUI与Antdv1或vant2或iview。
      • Vue3 技术与业务新的趋势。
        • 全家桶:
          • vite – 脚手架。
          • Vue3 – Vue核心。
            • 做双向数据绑定。
          • Pinia 或 Vuex4 – 做全局状态管理。
            • 项目中主要用Pinia。
          • VueRouter4 – 做页面路由跳转。
            • 根据路由显示与隐藏某些组件的。
          • UI框架:ElementPlus或Antdv或vant3。
          • TypeScript – 加强JavaScript语言功能。
    • React框架
      • 原生方案:
        • create-react-app 或 vite — 脚手架。
          • 主要用的create-react-app。
        • React18与React16 — React核心。
          • 15版本已经老了,React16才添加hook语法。
          • React17基本上保持React16的特点。
          • 主要学的是React18,因为React16上有的东西,它基本上都支持。
        • redux 或 mobx 或 zustand – 做全局状态管理。
          • 主要用的redux。
        • react-router-dom5 或 react-router-dom6 — 页面渲染。
          • 与React每个版本都有些兼容,两个都要学。
        • Antd 或 AntdMobile — UI框架组件库。
          • Antd – PC端。
          • AntdMobile – 移动端。
        • TypeScript – 加强JavaScript语言功能。
      • 淘系React方案:
        • umi
        • antdpro
          • 核心:
            • redux或redux-saga。
            • react-router-dom5。
            • dva – 数据流方案。
    • 小程序开发
      • 原生小程序开发。
      • Vue:uni-app。
      • React:taro。
    • NativeApp开发
      • 原生开发。
      • Vue:uni-app。
      • React:react-native。
      • flutter:Dart语言。
    • 项目应用级体系(主流):
      • 全栈工程师体系2023年
        • Node – 语言核心。
        • Express(或Koa2、Egg) — web服务器。
          • 主要用的Express。
        • Mongodb(或MySQL、SQLServer…) — 数据库。
          • 主要用的Mongodb。
        • Linux(Nginx、Docker) — 服务器。
          • Linux是操作系统,学命令行。
          • Nginx是代理服务器,类似于前端的web服务器。
          • Docker是容器管理,不太清楚。
        • nuxt.js/next.js — SSR渲染。
          • nuxt.js 是Vue框架。
          • next.js 是React框架。
      • 微前端
      • 低代码
      • 可视化
        • 2D:canvas(ECharts)
        • 3D:webGL(three.js)
      • Web3(区块链)
      • Electron框架 – PC桌面端
  3. jsx语法

    • jsx:JavaScript and xml (html)
    • 为了让vscode支持jsx语法,让其可以有提示、可以格式化等。
      • 故而把需要构架视图的js文件,其后缀名改为.jsx

        <div>//没有提示`</div>`;
        
        <div></div>//会有`</div>`的提示;
        
      • 可以把每一个.jsx理解为一个单文件组件。

        • 可以构建视图。
      • .jsx的文件,在webpack打包的时候,也是按照js的方式处理。

      • 把所有的视图(内容)编译后,都放在#root的容器中渲染。

        • React18是这样写的。

          import React from 'react'
          import ReactDOM from 'react-dom/client'//想构造web页面,就引入'react-dom/client'。
          // ReactDOM.createRoot()// 创建一个根节点。
          const root = ReactDOM.createRoot(document.getElementById('root'))
          // 通过根节点中的render把jsx中的DOM对象放到根节点中。
          root.render(<div>珠峰培训</div>
          )
          
        • 在React16中,这部分是这样操作的:

          import React from 'react'
          import ReactDOM from 'react-dom/client'//想构造web页面,就引入'react-dom/client'。ReactDOM.render(<div>珠峰培训</div>,document.getElementById('root')
          )
          
    1. 在jsx语法中,我们基于{}大胡子语法绑定JavaScript表达式。

      • {}也简称胡子语法。
      • JavaScript表达式:执行有结果(返回值)的操作。
        • 变量 {title}

        • {"字符串值"}

        • 数学运算 {1+1}

        • 判断操作 {1===1?"ok":"no"}

          • 只能使用三元运算符。

            • if/else、seitch/case不算表达式。
              • 它们算操作语句,但不算JavaScript表达式。
            import React from "react";
            import ReactDOM from "react-dom/client";
            // let isExist = true;
            let isExist = false;
            const root = ReactDOM.createRoot(document.getElementById("root"));
            root.render(<div>{isExist ? <button>按钮</button> : null}</div>
            )
            
        • 循环操作 {arr.map(item=>{return item*10})}

          • 如: {[1,2,3].map(item=>{return item*10})}

            {arr.map((item,index)=>{return <li key={index}> //循环创建的元素,要设置唯一的key属性值{item}</li>})
            }
            
          • 不能直接使用for循环等循环语句。

            • for、while、for-in等循环,不算JavaScript表达式。
          • 一般使用数组中的map语法或filter等方法。

            import React from "react";
            import ReactDOM from "react-dom/client";
            let title = `fang-react-title`;
            let arr = ["选项1", "选项2", "选项3"];
            const root = ReactDOM.createRoot(document.getElementById("root"));
            root.render(<div><h2>{title} {100}{" "}</h2><ul>{//arr:[<li key={0}>{选项1}</li>,...]arr.map((item, index) => {return <li key={index}>{item}</li>; //循环创建的元素,要设置唯一的key属性值。})}<li>选项2</li></ul></div>
            );
            
        • 函数调用

          • 包括自执行函数

            <li>{(() => 15)()}</li>
            
      • 在胡子语法中,嵌入不同数据类型的值,最后渲染的结果是不同的。
        • 原始值类型中:除了数字字符串会直接渲染出来,其余的值,最后渲染的结果都是空-不显示。
        • 对象数据类型:
          • 数组对象:不会转成字符串再渲染,而是内部会把数组中的每一项都单独拿出来渲染。
          • 函数对象:期望我们是基于<Component>组件语法这种方式调用函数组件。
          • 剩下的大部分对象,是不允许直接在胡子语法中渲染的!
            • 排除两种特殊情况:

              • 给元素设置style行内样式!

                let styleObject = { color: "red" };
                <p style={styleObject}>这是一个段落</p>
                
                • 给元素标签设置style属性,只能使用对象语法。

                  <p style="color: red">这是一个段落</p>//会报错。
                  
              • 给元素设置style行内样式,需要使用对象的。

                <p style={{ color: "red" }}>这是一个段落</p>
                
            • 如果对象是jsx元素对象(VirtualDOM),是可以直接渲染的。

              <p >{<a>8888</a>}</p>
              
              <p>{true ? <a>8888</a> : null}</p>
              
    2. 给元素/组件设置属性

      • 如果属性值是一个字符串,直接正常设置即可

        <div name="box"></div>
        
      • 其余情况:非字符串,此时基于{}嵌套绑定即可,即直接用胡子语法包起来。

        let theName = "box"
        <Component name={theName}></Component>
        
        • 例如:
          • 把变量的值作为属性值。

            let theName = "box"
            <Component name={theName}></Component>
            
          • 传递的属性值是其它类型的。

            <Component index={5}></Component>
            
      • 特殊情况:

        1. 给元素设置的class要改为className。

          <div className="the-class-1">the-class-1</div>
          
          • 不必也没关系,依旧会正常渲染,但会报错。

            <div class="the-class-2">the-class-2</div>//报错 Warning: Invalid DOM property `class`.不过依旧可以正常渲染。
            
        2. 给元素设置的style,要求其属性值必须是一个对象。

          let styleObject = { color: "red" }
          <p style={styleObject}>这是一个段落</p>
          
          <p style={{ color: "red" }}>这是一个段落</p>
          
          <p style="color: red">这是一个段落</p>//会报错。
          
      let num = 10
      <Component name="box" x={num} y={0} className="box" style={样式对象}/>
      
    3. 每个视图-无论大视图还是小视图,都只能设置一个根节点。

      • 小视图如果想要设置成多个根节点,则要用数组包起来。

        //数组包起来。<div><div>1</div><div>2</div>{[1,2,3].map(item=><p key={item}>{item}</p>)}//map返回的就是一个数组包起来一群子元素的根节点集合。</div>
        
        //只返回一个根节点。
        let root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<div><div>1</div><div>2</div>{[1, 2, 3].map((item) => {return <p key={item}>{item}</p>; //正常})}</div>
        );
        
      • 基于map循环的时候,每一轮循环产生的上下文,都算是一个小的视图,也不允许出现多个根节点。

        //map中返回多个根节点,报错。
        let root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<div><div>1</div><div>2</div>{[1, 2, 3].map((item) => {return (<p key={item}>{item}</p><i>{item}</i>);//报错})}</div>
        );
        
        //map中返回用一个div包起来的原根节点,此时div才是根节点。
        let root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<div><div>1</div><div>2</div>{[1, 2, 3].map((item) => {return (<div><p key={item}>{item}</p><i>{item}</i></div>);})}</div>
        );
        
      • 如果既不想让其只有一个根节点,也想让包外层盒子不占据层级结构,可以使用<></>–React.Fragment。

        //使用<></>
        let root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<div><div>1</div><div>2</div>{[1, 2, 3].map((item) => {return (<><p key={item}>{item}</p><i>{item}</i></>);})}</div>
        );
        
        //使用<></>就相当于使用<React.Fragment></React.Fragment>
        let root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<div><div>1</div><div>2</div>{[1, 2, 3].map((item) => {return (<React.Fragment><p key={item}>{item}</p><i>{item}</i></React.Fragment>);})}</div>
        );
        
        //使用<></>设置不了key,使用<React.Fragment></React.Fragment>可以设置key。
        let root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(<div><div>1</div><div>2</div>{[1, 2, 3].map((item) => {return (<React.Fragment  key={item}><p>{item}</p><i>{item}</i></React.Fragment>);})}</div>
        );
        
    4. 基于胡子语法渲染的内容,都被当做普通字符串进行渲染,无法识别其内部的HTML标签。

      • 类似于vue中的类似于v-text。

      • 如果需要可以把字符串中的标签自动识别,就需要用到dangerouslySetInnerHTML标签,dangerouslySetInnerHTML={{__html: html标签变量}};

        let str = `我的名字是:哈哈哈! <a href=''>呵呵呵</>`
        <div dangerouslySetInnerHTML={{__html: str
        }}></div>
        
    5. jsx中的事件绑定,是基于React内部的合成事件处理的,以onXxx的形式。

      <div onClick={ev=>{//.....
      }}></div>
      
      let root = ReactDOM.createRoot(document.getElementById("root"));
      root.render(<divonClick={() => {console.log("打印");}}><div>1</div><div>2</div></div>
      );
      
  4. jsx的底层渲染机制

    1. 基于babel-preset-react-app语法包,把jsx编译为React.createElement()这种格式。
      • 凡是HTML标签或组件,都会被编译为React.createElement()这种格式。

        React.createElement(标签名/组件名,属性对象/null,  //->存储了给标签设置的各种各样的属性后续参数都是其子节点
        )
        
        • 未转化之前:

            <divonClick={() => {console.log("打印");}}><div></div><div id="aa" class="theclassname">fang子元素</div></div>
          
        • 转化之后:

          /*#__PURE__*/React.createElement("div", {onClick: function onClick() {console.log("打印");}
          }, /*#__PURE__*/React.createElement("div", null), /*#__PURE__*/React.createElement("div", {id: "aa","class": "theclassname"
          }, "fang\u5B50\u5143\u7D20"));
          
        • 转化清简之后:

          React.createElement("div", {onClick: function onClick() {console.log("打印");}}, React.createElement("div", null), React.createElement("div", {id: "aa","class": "theclassname"}, "fang\u5B50\u5143\u7D20")
          );
          
        • babel转化jsx成虚拟DOM – 网址,需要会勾选选项

      • 虚拟DOM对象:框架自己创建的一个普通对象。

    2. 把createElement方法执行,创建出对应的VirtualDOM(虚拟DOM对象),也被称为:jsx元素对象。
      • 虚拟DOM:框架内部自己构建的一个对象,用来描述和记录元素标签的相关特征。

        VirtualDOM = {$$typeof: Symbol(react.element), //标识type: "div", //标签名或者组件key: "10",ref: "AAA",props: {除key/ref外其它设置的属性,children:子节点集合「可能没有、可能是一个值、可能是一个数组」}
        }
        
      • 真实DOM:交给浏览器渲染的、或者是渲染完毕后看到的元素标签、再或者是基于js获取到的原生DOM对象(有浏览器内置的属性和方法)。

    3. 基于render方法,把创建的VirtualDOM渲染为真实的DOM。
  5. jsx语法<template>模块语法

    • Vue2/Vue3中,既有<template>模块语法,也支持jsx语法。

    • React中只有jsx语法。

    • 对于同一个需求:

      • vue思路-<template>模块语法

        state/data = {flag:true,arr:[...],text:'...',level:2
        }
        <template><div class="box"><button v-if="flag">{{text}}</button><span v-for="item in arr" :key="item.id">{{item.title}}</span><h1 v-if="level===1">我是标题</h1><h2 v-else-if="level===2">我是标题</h2><h3 v-else-if="level===3">我是标题</h3></div>
        </template>
        
      • React思路-jsx语法

        state/data = {flag:true,arr:[...],text:'...',level:2
        }
        <div className="box">{flag?<button>{text}</button>:null}{arr.map(item=>{return <span key={item.id}>{item.title}</span>})}{React.createElement(`h${level}`,null,'我是标题')}
        </div>
        
    • JSX语法比<template>模版语法具备更强的编程性(或者template是弱编程性的语法),构建视图更加的灵活方便!

React视图编译的机制

  • 总结:React视图编译的机制。
    1. 把jsx语法,基于 babel-preset-react-app得到React.createElement()的层级结构,React.createElement() 创建出相应的 VirtualDOM
    2. 如果是第一次渲染视图,直接基于 render() 方法,把 VirtualDOM 变为 真实DOM,并且把本次创建的VirtualDOM缓存起来。
    3. 当视图更新的时候,会重新的按照最新的数据,把 jsx 编译为一个全新的 VirtualDOM,并且用 新的VirtualDOM 和之前 旧的VirtualDOM 进行对比(DOM-diff),计算出差异的部分,最后只把差异的部分进行更新!

业务开发思路

  • 业务开发涉及。
    • 组件式开发 – 增加可复用性和可维护性。
      • 组件间通信。
    • 全局数据管理。
    • 单页面应用。
      • 基于路由更换组件。

进阶参考

  1. 把jsx标签语法转成虚拟DOM – babeljs

http://www.ppmy.cn/news/71991.html

相关文章

【Selenium】解决 Error: LavaMoat 相关报错

解决使用 selenium 调用 metamask 进行 dapp 自动化测试报错问题 author: jwensh date: 20230517 unknown error: Runtime.callFunctionOn threw exception: Error: LavaMoat - property “JSON” of globalThis is inaccessible under scuttling mode. To learn more visit ht…

[C++]22种设计模式的C++实现大纲

前言 最近看遍全网&#xff0c;准备整理一套较好上手的设计模式文章&#xff0c;以便后续复习到处翻找&#xff0c;在此记录一下&#xff0c;如有侵权可以联系删除, 每天更新一篇&#xff0c;直到更新完 1. 代码仓库 https://github.com/TOMO-CAT/CppDesignPattern 2. 前置知…

TCL字符串操作

format命令 因为 TCL 把所有的输入都当作字符串看待&#xff0c;所以 TCL 提供了较强的字符串操作功能&#xff0c;TCL 中与 字符串操作有关的命令有&#xff1a;string、format、regexp、regsub、scan 等。 语法&#xff1a;format formatstring ?vlue value...? format …

图形编程周刊(2023.001)

图形编程周刊(2023.001) key: webgpu webgl 3d webgis three.js cesium.js 这里是力博荣(Libaro)三维可视化带来的 图形编程周刊, 争取每周五发布。 更新源位置: https://gitee.com/lianming/graphics-programming-weekly/blob/master/2023001/2023001.md 发现的代码 1、th…

PMP课堂模拟题目及解析(第10期)

91. 在项目执行阶段&#xff0c;一名项目干系人要求项目经理加入一个新过程的优化。项目经理应该怎么做&#xff1f; A. 执行实施整体变更控制过程。 B. 与过程专家一起审查项目。 C. 将优化项目分配给团队。 D. 拒绝范围蔓延企图。 92. 项目经理要求团队提供对项目应急计…

Web基础 ( 三 ) Bootstrap

3.Bootstarp 3.1.什么是Bootstrap Bootstrap来自 Twitter&#xff0c;是目前最受欢迎的前端UI框架。 Bootstrap 是基于 HTML、CSS、JQuery 的&#xff0c;它简洁灵活&#xff0c;使得 Web 开发更加快捷。 主要特点是 整合HTML和CSS技术,提供了大量应用组件, 简化了响应式布…

最频繁使用的5个 Python 装饰器

装饰器是 Python 中非常强大的功能&#xff0c;可以使我们更加灵活地修改函数的行为和功能。 起初&#xff0c;每个 Python 开发者的目标都是让代码正常运行。慢慢地&#xff0c;我们开始担心可读性和可扩展性。这时候我们开始考虑装饰器。 装饰器是给函数添加额外行为的绝佳…

Sentinel-2数据下载及处理

数据下载网站&#xff1a;欧空局官网&#xff08;需注册并登录&#xff09; https://scihub.copernicus.eu/dhus/#/home 哨兵2 L1C数据波段信息 哨兵2 L1C数据时间&#xff1a;2015-06-23至now 由于数据量大&#xff0c;考虑服务器压力&#xff0c;哨兵2号数据直接下载的时间跨…