- 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被称为单向数据驱动的框架
- 关于版本问题
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(区块链)
-
...
- 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>
.....
=================================
- 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 \
Vue2/Vue3中,既有 \ 语法,也支持 jsx 语法
React中只有 jsx 语法
-----
state/data = {
flag:true,
arr:\[...\],
text:'...',
level:2
}
\
\我是标题\
\我是标题\
\我是标题\
\