Vuex中为什么要区分异步(actions)和同步(mutation)两个操作呢?详细
- 保证每个方法的单一职能(mutation负责state状态变换,action负责业务逻辑或后端交互等操作)
- 方便devtool记录state数据变换
- commit提交数据的时候,devtool会对数据变换记录
- 但是如果mutation中调用了异步方法同时在会回调函数中修改state数据,由于回调函数执行时间是不确定的,那么devtool就没办法确定在某个时间里到底是哪个mutation方法更新了state数据,数据变的难以记录。
// 这种情况的时候 数据变的难以记录
... mutations: {
storeData (state, payload) {
mockFeatchData().then((res) => {
console.log(res)
state.data = state.data.concat(res)
})
}
},
Pinia中去掉了mutation,那么它是如何解决这个数据记录困难的问题的呢?
- 【暂未找到合适的答案】如果是不考虑devtool数据变换追踪的话(时间旅行),确实没必要分mutation和action
Pinia 和 Vuex
mutation:Pinia中去掉了mutation,Vuex中使用mutation主要是方便跟踪数据变换(方便开发调试用具的使用)。但是这样写起来是比较复杂的,所以Pinia中去掉了。Pinia中不管是同步还是异步的操作都是放到了action中修改,可以直接修改state中的值,调试用具也可以直接记录到变换。
moudles:去掉主要是因为在大型的项目中,如果将所有的模块都放到一个大对象下,会使得代码变得臃肿,不方便使用。在Pinia中去掉了,直接使用函数的方式,更符合Vue3中函数式的使用。
单一职责:异步工作和同步工作分开,保证每个功能的单一性,如果多个相同的actions会导致值混乱,方便数据的跟踪和数据回溯。
Vuex在mutation中修改status的原因:其实最大的原因是方便调试,这样每一个 mutation 执行完成后都可以对应到一个新的状态,如果是有每个mutation的时间线就可以更好的理解。
React
React更建议使用不可以变数据,直接替换一个对象 主要是可以更好的追溯历史记录和跟踪数据变换,感觉上是和Vue2差不多的原因React中setState更新数据的时候导致render函数被调用两次的问题:主要是在开发情况下使用的严格模式Strict Mode,使得两次更新了,主要是为了去掉一下生命周期的副作用,不懂是什么的副作用。详细原因- 相较于原生的html来说,react最大的优势是数据更新,可以不通过js来操作对dom元素的更新,只需要对数据进行操作了。
- 但是
Vue和React相比较起来的话,Vue组件化更好,尤其是在多个子组件间需要数据通讯和父子间需要进行通讯的时候,React中推荐的是将数据都提升到父组件中,这样在父组件中实现数据的操作和计算之后再传递给子组件,也就是说所有的逻辑就都会放到父组件中,这样父组件中代码量也越来越大了,但是在Vue中子组件可以通过emit的方式来触发对父组件中数据的更新和操作,这样将父子组件的功能更独立和模块化。(这个操作起来react和vue其实没什么大致的不同,父子组件数据的通讯emit和this.props.onChange这两个操作其实大差不差的,没有感觉上有什么) props的不可变性(只读性),在React中不能直接在当前组件中修改组件的props,vue也是一样的,只能是在父组件中修改了之后重新render了之后,子组件重新渲染。- 纯函数:是不会对传入的参数进行修改和数据改变的
- react主要是通过setState来实现render被调用,实现dom更新 。感觉
React的数据更新要比Vue更可控,逻辑更清晰。 - 为了减少页面渲染,提高性能。
React中会对多个setState进行合并和批量更新,同时setState可能是同步也可能是异步的,主要也是因为这个合并和批量更新的原因。详细原因 - 受控组件 和 非受控组件:不需要和受控组件一样维护一个状态state ref直接拿取数据因为在受控组件中,表单数据由React组件负责处理;当然如果选择受受控组件的话,表单数据就由DOM本身处理。表单元素和react state达成关联,表单数据变更之后onchange触发从而修改react state中的数据,调用render之后 又将state中的数据渲染到表单元素中详细内容
- Context和Vue中的provide/inject功能上是相同的,但是在使用上来说vue中的方式是更加方便和简单的。
Function Components cannot be given refs
由function构建的component不能使用ref,Class创建的是可以的,函数内可以使用 useRef
React.lazy vs webpack dynamic import
React.lazy:返回了一个Promise 或则是返回一个可以被渲染组件 webpack dynamic import: 返回了一个加载使解析到的Promise,不能直接渲染使用 Detail
// dynamic import
class SomeComponent extends React.Component {
state = {LazyComponent: null};
async componentDidMount() {
const LazyComponent = await import('./path/to/LazyComponent');
this.setState({LazyComponent});
}
render() {
const {LazyComponent} = this.state;
return LazyComponent ? <LazyComponent {...props} /> : null;
}
}
// React.lazy
const ThemedButton = React.lazy(() => import('./ThemedButton.tsx'));
export default class App extends React.Component<any, any> {
render() {
return <ThemedButton/>;
}
}
未解决问题
-
Argument of type 'AsyncThunkAction<number, number, AsyncThunkConfig>' is not assignable to parameter of type 'AnyAction'dispatch不接受异步Tunk的问题 详情
单向数据流和双向数据流