trads
1.template vue,jsx react
2.响应式reaction
双向绑定vue,Object.defineproperty 同层两端向中间全量对比。proxy增量对比,添加标记、最长递增子序列算法优化了对比流程
React 则是基于状态,单向数据流,数据不可变,需要手动 setState 来更新,而且当数据改变时会以组件根为目录,默认全部重新渲染整个组件树,只能额外用 pureComponent/shouldComponentUpdate/useMemo/useCallback 等方法来进行控制
3.api Vue API 多,React API 少
3.1vue指令v-if v-else v-for、修饰符v-model:lazy、number、trim,@click.right,@keup.enter等。
3.2生命周期
https://juejin.cn/post/7238199999733088313
4.Diff
vue2 是同层比较,双指针头对尾两端对比的方式,全量diff,然后移动节点时通过 splice 进行数组操作
vue3 增量对比,编译前静态标记,最长递增子序列算法优化了对比流程
react 同层比较,从左到右遍历,通过 key 判断是否相同,相同只修改props,不同就删除重新创建dom数。shouldComponentUpdate()
5.slot Vue 可以用插槽,React 是万物皆可 props
vue2和react的区别,细节篇
react是函数式编程,immutable.js(状态持久库)+redux
vue是大部分是面向对象编程,object.freeze
VUE中函数式编程-filter和reduce函数用法
vue自动挡、react手动挡。有shouldComponentUpdate控制是否render、setState是否修改state
shouldComponentUpdate(nextProps,nextState) {
if (nextProps.m1 === this.props.m1 && nextState.m2 === this.state.m2) {
// if (nextProps.m1 === nextState.m1) {
return false;
} else {
return true;
}
}
0.reactjs与vue相比较,默认目录结构没有webpack相关配置,也没有路由组件。
1.vue插值表达式,用双花括号
2.vue用 template模板
react用js,class里面,然后render函数, jsx语法
render(){
console.log(111)
return <>
<div>这里是number{this.state.number}</div>
<button onClick={this.changeState}>点我改变number</button>
</>
}
3.vue state data数据可以双向绑定v-model
react不能双向绑定,用setState设置,组件用
onChange={this.onInputChange }
onInputChange = (e) => {
this.setState({
name: e.target.value
})
}
4.vue用v-if v-show
react用
if(condition){
return
}else {
return
}
或者三元运算符
return
{this.state.theme === ‘black’ ? blackBtn : whiteBtn}
5.vue用v-for in 遍历对象
react用map:
import React from 'react'
const listData = [
{
id: 1,
text: '我是第一条数据'
},
{
id: 2,
text: '我是第二条数据'
},
{
id: 3,
text: '我是第三条数据'
}
]
export default function ForRender() {
return (
<div>
<ul>
{
listData.map(item => {
if (item.id === 2) return
return <li key={item.id}>{item.text}</li>
})
}
</ul>
</div>
)
}
import React from 'react'
const objData = {
1: '我是第一条数据',
2: '我是第二条数据',
3: '我是第三条数据',
}
export default function ForRender() {
return (
<div>
<ul>
{
Object.entries(objData).map(([id, text]) => {
return <li key={id}>{id + '、' + text}</li>
})
}
</ul>
</div>
)
}
6.事件
vue不用bind,
@click @input
react需要bind(this)或者用箭头函数 (如果函数体大,箭头函数性能不如bind)
event对象在vue中是原生的,如MouseEvent;
在react中不是原生的,可以用console.log(event.nativeEvent),所有事件都挂载document上:
// 1. event 是 SyntheticEvent ,模拟出来 DOM 事件所有能力
// 2. event.nativeEvent 是原生事件对象
// 3. 所有的事件,都被挂载到 document 上
// 4. 和 DOM 事件不一样,和 Vue 事件也不一样
react为了解决跨平台,兼容性问题,自己封装了一套事件机制,代理了原生的事件,像在jsx中常见的onClick、onChange这些都是合成事件。
7.父子组件传值、爷孙跨级组件
vue:父->子 props
子传值给父:this.$emit(‘add’,this.title)
react:传值,父子兄弟,都可以用props
// 透传所有props,vue用$props v-bind,react用<Component {…this.props} />
爷孙跨级组件
vue:provider inject
react函数式:useContext
react类组件:export const globalContext = React.createContext();
// 导出仓库里面存放一些普通数据,跟vuex的含义差不多
export const globalData = {
num: 0,
sum: [‘a’,‘b’,‘c’]
}
https://blog.csdn.net/weixin_48255917/article/details/119764377
8.propTypes 类型检查
9.nextTick
setState 假异步,直接console.log是取不到数据变化,需要加setTimeout或者事件:
setState并不是真正意义上的异步操作,它只是模拟了异步的行为。判断是直接更新还是先暂存state进队列。setTimeout以及原生事件都会直接去更新state,因此可以立即得到最新state。
setState传入对象,就会合并:
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
传入函数,不会合并
this.setState((prevState, props) => {
return {
count: prevState.count + 1
}
})
this.setState((prevState, props) => {
return {
count: prevState.count + 1
}
})
a.可能是异步
b.可能会合并,state里面是对象会合并,如果是函数return对象就不合并。
10.$ref,useR获取dom元素
vue:
react:creatRef类组件和useRef函数式组件
constructor里面创建对象:this.myRef = React.creatRef()
useRef是use hooks的一种,一般用于function组件,而createRef一般用于class组件;
由useRef创建的ref对象在组件的整个生命周期内都不会改变,但是由createRef创建的ref对象,组件每更新一次,ref对象就会被重新创建。
useRef改变不会刷新dom render
11.slot和portals、vue3的teleport
一个 portal 的典型用例是当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框。常见的情况是创建一个包含全屏模式的组件。
vue用slot插槽
react的portals,当父组件overflow:hidden或者z-index值太小
可以用portals
return ReactDOM.createPortal(
document.body // DOM 节点
)
或者用props传递子组件
通过解构赋值的方式获取到传递过来的props值,因为不再需要注意使用的顺序,所以推荐使用这种方式。
vue3用teleport
//子组件
render() {
const {leftSlot, centerSlot, rightSlot} = this.props;
return (
<div className="nav-item nav-bar">
<div className="nav-left">
{leftSlot}
</div>
<div className="nav-item nav-center">
{centerSlot}
</div>
<div className="nav-item nav-right">
{rightSlot}
</div>
</div>
)
}
//子组件
render() {
const {leftSlot, centerSlot, rightSlot} = this.props;
return (
<div className="nav-item nav-bar">
<div className="nav-left">
{leftSlot}
</div>
<div className="nav-item nav-center">
{centerSlot}
</div>
<div className="nav-item nav-right">
{rightSlot}
</div>
</div>
)
}
12.context
react的context用法,比如最外层定义的语言或者主题,逻辑不复杂:
const ThemeContext = React.createContext(‘light’)
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
static contextType = ThemeContext // 这是es6写法,也可以用 ThemedButton.contextType = ThemeContext
render() {
const theme = this.context // React 会往上找到最近的 theme Provider,然后使用它的值。
return
button’s theme is {theme}
}
}
13.父组件数据更新,子组件变化
vue,只有关联数据的子组件变化,其他子组件不会变化
react,所有自组件都更新,所以要用SCU钩子函数,pureComponent,memo优化.
14.protals 传送门
vue2没有 vue3 transport
react有,当父组件有overflow,z-index样式的时候,但是你需要子组件在视觉上能够跳出容器,
也就是说能显示出来。比如对话框,提示框等。
15.mixin vs HOC
vue有mixin,管理共享组件数据,数据之间互不干扰
react废弃了,用高阶组件HOC
16.hook
vue的hook是给第三方组件,添加生命周期。或者集中管理函数加载删除。
在模板中通过@hooks:created这种形式;
vm.$on('hooks:created', cb)或者 vm.$once('hooks:created', cb)。
react的hook是给无状态组件(函数组件)添加生命周期。
17.无状态组件,函数组件
vue: <template functional>
react:
function HelloComponent(props) {
return
}
ReactDOM.render(, mountNode)
18.vue用scope限制css作用域
react用CSS Modules,webpack cssloader让编译后的css名称增加hash值。
- 修改antd组件样式
vue: /deep/ 穿透
react: :global{ }
20.keep-alive
react没有,需要用第三方插件react-activation
参考:https://blog.csdn.net/Carol246/article/details/118201278
21.路由渲染
vue route-view
react
<Route
path=
/layout/demo1
component={Demo1}
>
<Route
path=
/layout/demo2
component={Demo2}
>
22.computed
useMemo(() => {
return `${province}省${city}市`
}, [province, city]);
watch
useEffect(() => {
console.log('province或city发生了变化: ', province, city);
}, [province, city]);
mounted:
useEffect(() => {
console.log('province或city发生了变化: ', province, city);
}, []);
useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
const timer = setInterval(() => {
setCount(count + 1)
}, 1000)
// useEffect方法的第一个参数是一个函数,函数可以return一个方法,这个方法就是在组件销毁的时候会被调用
useEffect(() => {
return () => {
clearInterval(timer)
}
}, [])
23.craco&vite、vue
module.exports = {
style: {
postcss: {
mode: 'extends',
loaderOptions: {
postcssOptions: {
ident: 'postcss',
plugins: [
[
'postcss-pxtorem',
{
rootValue: 375 / 10, // 根元素字体大小
propList: ['*']
},
],
],
},
},
},
},
};
- react 16 引入fiber
参考:https://zhuanlan.zhihu.com/p/613451517?utm_id=0
React Fiber 虚拟 DOM 实现
Fiber是react执行渲染时的一种新的调度策略,是虚拟DOM的一种实现方式,帮助我们管理DOM更新的优先级。
fiber是个链表,有type,props,return,child 和 sibing 属性,指向第一个子节点和相邻的兄弟节点,从而构成 fiber tree;return 属性指向其父节点。
因为JavaScript是单线程的,一旦组件开始更新,主线程就一直被React控制,当js在处理大型计算的时候会导致页面出现卡帧的现象,更严重的会出现页面“假死”;而 Fiber 能将大型的计算拆分成一个个小型计算,然后按照执行顺序异步调用,这样就不会长时间霸占线程,UI也能在俩次小型计算的执行间隙进行更新,从而给与用户及时的反馈。
React借鉴了操作系统分片的概念,引入了Fiber架构,将整个DOM树变为链表,然后利用浏览器的空闲时间来计算Diff,一旦浏览器有需求,再将主线程还给浏览器。
左侧是以前用的树形结构,但是树形结构通常遍历是用递归,但是递归是很难中断的。而Fiber树则是将树结构改造为了链表,遍历严格按照子元素→兄弟元素→父元素的逻辑,随时可以中断和恢复Diff的计算过程
const fiber = {
stateNode,// dom节点实例
child,// 当前节点所关联的子节点
sibling,// 当前节点所关联的兄弟节点
return// 当前节点所关联的父节点
}
-
代理proxy配置
vue: config.js
react:setupProxy.js -
error检测
react: error boundary,static getDerivedStateFromError
vue: errorCaptured