前端框架

206 阅读5分钟

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数据变换追踪的话(时间旅行),确实没必要分mutationaction

Pinia 和 Vuex

mutation:Pinia中去掉了mutation,Vuex中使用mutation主要是方便跟踪数据变换(方便开发调试用具的使用)。但是这样写起来是比较复杂的,所以Pinia中去掉了。Pinia中不管是同步还是异步的操作都是放到了action中修改,可以直接修改state中的值,调试用具也可以直接记录到变换。

moudles:去掉主要是因为在大型的项目中,如果将所有的模块都放到一个大对象下,会使得代码变得臃肿,不方便使用。在Pinia中去掉了,直接使用函数的方式,更符合Vue3中函数式的使用。

单一职责:异步工作和同步工作分开,保证每个功能的单一性,如果多个相同的actions会导致值混乱,方便数据的跟踪和数据回溯。

Vuex为什么使用mutation来修改state

Vuexmutation中修改status的原因:其实最大的原因是方便调试,这样每一个 mutation 执行完成后都可以对应到一个新的状态,如果是有每个mutation的时间线就可以更好的理解。

React

  • React更建议使用不可以变数据,直接替换一个对象 主要是可以更好的追溯历史记录和跟踪数据变换,感觉上是和Vue2差不多的原因
  • ReactsetState更新数据的时候导致render函数被调用两次的问题:主要是在开发情况下使用的严格模式Strict Mode,使得两次更新了,主要是为了去掉一下生命周期的副作用,不懂是什么的副作用详细原因
  • 相较于原生的html来说,react最大的优势是数据更新,可以不通过js来操作对dom元素的更新,只需要对数据进行操作了。
  • 但是VueReact 相比较起来的话,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中的数据渲染到表单元素中详细内容
  • ContextVue中的provide/inject功能上是相同的,但是在使用上来说vue中的方式是更加方便和简单的。

Function Components cannot be given refs

function构建的component不能使用refClass创建的是可以的,函数内可以使用 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的问题 详情

单向数据流和双向数据流

  • 单项数据流:实质上Vue/React中的props就是单项的数据只能允许父组件传递给子组件,不允许子组件来修改父组件的的数据,只能是父组件在自己组件内部修改数据之后重新传输给子组件
  • 双向数据流:实质上vue中的v-model中数据就可以实现数据双向,一向是数据修改之后实现视图的更新,另一向是用户操作input等表单组件的时候,修改了视图之后实现数据的更新。