1. MVVM(Vue) VS MVC(React)
MVVM:Model View viewModel 双向数据驱动
MVC:Model View Controller 单向数据驱动
Model:数据层
View:视图层
Controller:控制层
+ 我们要学会如何构建数据/状态,以及修改状态的方法「例如:setState、useState...」
+ 当我们基于特定的方法修改状态后,会通知视图更新
-----> React的MVC框架中,实现了 “数据驱动视图渲染「M->V」”
+ 我们要学会如何构建视图
Vue中是基于 <template>(主) / jsx 语法构建视图的
React中构建视图的语法是:jsx
-----> 不论是Vue还是React,构建的视图都有一套编译机制:VirtualDOM(虚拟DOM)-> DOM-DIFF -> 真实DOM
+ 如果视图中的表单元素内容发生改变
Vue基于v-model指令自动监听表单内容的变化,而后把对应的状态值进行自动更改,所以Vue是双向驱动的框架,“视图驱动数据更新「V->M」”
React默认没有实现视图驱动数据,需要开发者手动对表单元素进行事件绑定和监听,手动去修改对应的状态,所以React被称为单向数据驱动的框架
2. 关于版本问题
Vue框架「@vue/cli、vite」
+ Vue2、Vuex3、VueRouter3、ElementUI或Antdv1或vant2或iview 「用的最多」
+ Vue3、Vuex4(Pinia)、VueRouter4、ElementPlus或者Antdv或vant3、TypeScript 「新的趋势」
React框架
+ create-react-app(vite)、React16/18、redux(或mobx、zustand)、react-router-dom5/6、Antd或AntdMobile、TypeScript
+ 淘系React方案:umi、antdpro「核心 redux/redux-saga、react-router-dom5、dva」
小程序开发
+ 原生小程序开发
+ Vue:uni-app
+ React:taro
NativeApp开发
+ Vue:uni-app
+ React:react-native
+ flutter「Dart语言」
项目应用级体系
+ Node、Express(或Koa2、Egg)、Mongodb(或MySQl、SQLServer...)、Linux(Nginx、Docker)、nuxt.js/next.js「SSR渲染」...
+ 微前端
+ 低代码
+ 可视化「canvas、webGL(three.js)...」
+ Web3(区块链)
+ ...
3. jsx语法
jsx:javascript and xml(html)
为了让vscode支持jsx语法「有提示、可以格式化等」,我们把需要构建视图的js文件,其后缀名改为 .jsx
+ 我们可以把每一个 .jsx 理解为一个单文件组件(可以构建视图)
+ .jsx 的文件,在webpack打包的时候,也是按照js的方式处理
----
把所有的视图(内容)编译后,都放在#root的容器中渲染「React18」
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<div>
珠峰培训
</div>
)
在React16中,这部分是这样操作的
ReactDOM.render(
<div>
珠峰培训
</div>,
document.getElementById('root')
)
-------
@1 在JSX语法中,我们基于 “{}” (大)胡子语法绑定JS表达式
JS表达式:执行有结果(返回值)的操作
+ 变量 {title}
+ 值 {'哈哈哈'}
+ 数学运算 {1+1}
+ 判断操作 {1===1?'ok':'no'} 只能使用三元运算符「if/else、switch/case不算表达式」
+ 循环操作 for、while、for in等循环,不算JS表达式
{
arr.map((item,index)=>{
return <li key={index}> //循环创建的元素,要设置唯一的key属性值
{item}
</li>
})
}
+ ...
在胡子语法中,嵌入不同数据类型的值,最后渲染的结果是不同的
+ 原始值类型中:除了 数字、字符串 会直接渲染出来,其余的值,最后渲染的结果都是空
+ 对象数据类型:
数组对象:不会转字符串,而是内部,会把数组中的每一项都单独拿出来渲染
函数对象:期望我们是基于 <Component> 这种方式调用函数组件
剩下的大部分对象,是不允许直接在 胡子语法 中渲染的!「排除:给元素设置style行内样式;如果对象是JSX元素对象(VirtualDOM),是可以直接渲染的」
@2 给元素/组件设置属性
+ 如果属性值是一个字符串,直接正常设置即可
+ 其余情况(例如:把变量的值作为属性值、或者传递的属性值是其它类型的),此时基于 “{}” 嵌套绑定即可
+ 特殊1:给元素设置的class要改为className
+ 特殊2:给元素设置的style,要求其属性值必须是一个对象
let num = 10
<Component name="box" x={num} y={0} className="box" style={样式对象}/>
@3 每个视图(无论大或者小),都只能设置一个根节点
+ 基于map循环的时候,每一轮循环产生的上下文,算是一个小的视图,也不允许出现多个根节点
+ 如果即想让其只有一个根节点,也想让包起来的外层盒子不占据层级结构,可以使用 <></> 「React.Fragment」
@4 基于胡子语法渲染的内容,都被当做普通字符串进行渲染,无法识别其内部的HTML标签(类似于v-text);现如今我们期望可以把字符串中的标签自动识别,就需要用到:
<div dangerouslySetInnerHTML={{
__html: str
}}></div>
@5 JSX中的事件绑定,是基于React内部的合成事件处理的「onXxx」
<div onClick={ev=>{
//.....
}}></div>
.....
=================================
4. jsx的底层渲染机制
@1 基于 babel-preset-react-app 语法包,把jsx编译为 React.createElement 这种格式
凡是HTML标签(或组件),都会被编译为createElement这种格式!!
React.createElement(
标签名/组件名,
属性对象/null, //->存储了给标签设置的各种各样的属性
后续参数都是其子节点
)
@2 把 createElement 方法执行,创建出对应的 VirtualDOM(虚拟DOM对象) 「也被成为:JSX元素对象」
虚拟DOM:框架内部自己构建的一个对象,用来描述和记录元素标签的相关特征
真实DOM:交给浏览器渲染的、或者是渲染完毕后看到的元素标签、再或者是基于JS获取到的原生DOM对象(有浏览器内置的属性和方法)
VirtualDOM = {
$$typeof: Symbol(react.element), //标识
type: "div", //标签名或者组件
key: "10",
ref: "AAA",
props: {
除key/ref外其它设置的属性,
children:子节点集合「可能没有、可能是一个值、可能是一个数组」
}
}
@3 基于 render 方法,把创建的 VirtualDOM 渲染为真实的DOM
总结:React视图编译的机制
@1 把 jsx 语法,基于 babel-preset-react-app & React.createElement 创建出相应的 VirtualDOM
@2 如果是第一次渲染视图,直接基于 render 方法,把 VirtualDOM 变为 真实DOM「并且把本次创建的VirtualDOM缓存起来」
@3 当视图更新的时候,会重新的按照最新的数据,把 jsx 编译为一个全新的 VirtualDOM,并且用 新的VirtualDOM 和之前 旧的VirtualDOM 进行对比(DOM-DIFF),计算出差异的部分,最后只把差异的部分进行更新!
5. jsx VS <template>
Vue2/Vue3中,既有 <template> 语法,也支持 jsx 语法
React中只有 jsx 语法
-----
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>
<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是弱编程性的语法),构建视图更加的灵活方便!!