前端模拟面试练习提升题

 

参考:

官方文档

vuex-module-decorators

 

安装  npm install  vuex-module-decorators

 

安装成功后就可以使用啦,先看一个完整案例

 

// store/modules/passenger.ts

import {Module,VuexModule,Mutation,Action,getModule,} from 'vuex-module-decorators';

import store from '@/store';

 

type User = { username: string; password: string; }

 

// dynamic: true: 动态创建动态模块,即new Vuex.Store({})里面不用注册的.空着就行,

// store,当前模块注册到store上.也可以写在getModule上,即getModule(PassengerStore,store)

// namespaced: true, name: 'passenger' 命名空间

@Module({

  name: 'passenger', dynamic: true, namespaced: true, store,

})

export default class PassengerStore extends VuexModule {

  // state => 要public不然外面调用不到

  public loginInfo: User[] = [];

 

  // getter

  get userNumber(): number {

    return this.loginInfo.length;

  }

 

  @Mutation

  USERINFO(user: User): void {

    console.log(user);

    this.loginInfo.push(user);

  }

  // commit的两种调用方式,第一种,Action后面的括号里面添加commit,然后return的结果就是USERINFO的参数

  @Action({ commit: 'USERINFO' })

  getZhangsan(): User {

    return { username: '张三', password: 'zhangsan' };

  }

  // 第二种,直接this.USERINFO调用;

  @Action

  getLisi(): void {

    const user = { username: '李四', password: 'lisi' };

    this.context.commit('USERINFO', user); // commit调用

    // this.USERINFO(user); // 直接调用

  }

}

// 使用getModule: 对类型安全的访问

export const PassengerStoreModule = getModule(PassengerStore);

 

// sotre/index.ts

import Vue from 'vue';

import Vuex from 'vuex';

 

Vue.use(Vuex);

export default new Vuex.Store({ }); // 由于passenger->dynamic: true: 是动态创建动态模块,所以不需要再次注册

index.vue页面使用

 

<script lang="ts">

import { Component, Vue } from 'vue-property-decorator';

import { PassengerStoreModule } from '@/store/modules/passenger';

 

@Component

export default class IndexPage extends Vue {

    created() {

        console.log(PassengerStoreModule.loginInfo); // state

        console.log(PassengerStoreModule.userNumber); // getter

        PassengerStoreModule.getZhangsan(); // actions

        PassengerStoreModule.getLisi(); // actions

    }

}

</script>

上面的案例是一个,使用了动态注册,下面我们详细说下,具体的使用

@Component state getter

 

@Mutations

 

@Actions

 

@MutationsActions

 

getModule

 

动态模块

 

state:

import { Module, VuexModule } from 'vuex-module-decorators'

 

@Module

export default class Vehicle extends VuexModule {

  wheels = 2

}

 

等同于下面的代码

 

export default {

  state: { wheels: 2 }

}

getter

import { Module, VuexModule } from 'vuex-module-decorators'

 

@Module

export default class Vehicle extends VuexModule {

  wheels = 2

  get axles() {

    return this.wheels / 2

  }

}

 

等同于下面的代码

 

export default {

  state: { wheels: 2 },

  getters: {

    axles: (state) => state.wheels / 2

  }

}

@Mutations

import { Module, VuexModule, Mutation } from 'vuex-module-decorators'

 

@Module

export default class Vehicle extends VuexModule {

  wheels = 2

 

  @Mutation

  puncture(n: number) {

    this.wheels = this.wheels - n

  }

}

 

等同于下面的代码

 

export default {

  state: { wheels: 2 },

  mutations: {

    puncture: (state, payload) => {

      state.wheels = state.wheels - payload

    }

  }

}

@Actions

import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'

import { get } from 'request'

 

@Module

export default class Vehicle extends VuexModule {

  wheels = 2

 

  @Mutation

  addWheel(n: number) {

    this.wheels = this.wheels + n

  }

 

  @Action

  async fetchNewWheels(wheelStore: string) {

    const wheels = await get(wheelStore)

    this.context.commit('addWheel', wheels)

  }

}

 

等同于下面的代码

 

const request = require('request')

export default {

  state: { wheels: 2 },

  mutations: {

    addWheel: (state, payload) => {

      state.wheels = state.wheels + payload

    }

  },

  actions: {

    fetchNewWheels: async (context, payload) => {

      const wheels = await request.get(payload)

      context.commit('addWheel', wheels)

    }

  }

}

@MutationAction

在vuex中是要通过commit来更改state中的数据.在vuex-module-decorators中有MutationAction修饰器,可以直接修改state数据.

 

export default class PassengerStore extends VuexModule {

  public username = '';

  public password = '';

 

  //'username'和'password'被返回的对象替换,

  //格式必须为`{username:...,password:...}`

  @MutationAction({ mutate: ['username', 'password'] })

  async setPassenger(name: string) {

    const response: any = await request(name); // 接口返回 [{name:'张三',password:'123456'}]

    // 此处返回值必须和上面mutate后面的名称保持一致;

    return {

      username: response[0].name,

      password: response[0].password,

    };

  }

}

 

 

// index.vue中使用

<template>

    <div class="">

        用户名:{{PassengerStoreModule.username}}<br/>

        密码:{{PassengerStoreModule.password}}<br/>

        <button @click="getPassenger()">getPassenger</button>

    </div>

</template>

 

...

@Component

export default class IndexPage extends Vue {

    private PassengerStoreModule: any = PassengerStoreModule;

 

    getPassenger() {

        PassengerStoreModule.setPassenger('西施');

    }

}

 

// 运行过后,点击getPassenger按钮,用户名和密码会发生变化哦

getModule:创建类型安全的访问

传统是需要注册到的new Vuex.Store上,然后通过this$store访问,使用getModule访问类型更加安全,

可以再module上使用store模块,然后getModule(模块名)

也可以getModule(模块名,this.$store)的形式

 

import { Module, VuexModule, getModule } from 'vuex-module-decorators'

import store from '@/store'

 

// 1. module上使用store

@Module({ dynamic: true, store, name: 'mymod' })

class MyModule extends VuexModule {

  someField: number = 10

}

const myMod = getModule(MyModule)

myMod.someField //works

myMod.someOtherField //Typescript will error, as field doesn't exist

 

 

// 2. module上不使用store,  getModule使用store

@Module({ dynamic: true, name: 'mymod' })

class MyModule extends VuexModule {

  someField: number = 10

}

const myMod = getModule(MyModule,store)

...

动态模块

动态模块:使用getModule获取数据,页面调用的时候,store.state里面才会显示改模块的信息

非动态模块:页面初始的时候,手动添加到new Vuex.Store({ modules: {  user: PassengerStore } }),页面刷新state里面可以直接看到当前模块的变量以及方法。

 

我们将上面的passenger.ts改写才非动态模块

 

import {Module,VuexModule,Mutation,Action,getModule,} from 'vuex-module-decorators';

// import store from '@/store'; // 去掉store

 

type User = { username: string; password: string; }

 

@Module({name: 'user', namespaced: true,})

export default class PassengerStore extends VuexModule {

  // ...同上方案例一模一样

}

 

// 因为getModule是要对应store的.上面去掉了store,所以也要去掉 getModule,

// export const PassengerStoreModule = getModule(PassengerStore);

 

// store/index.ts

import Vue from 'vue';

import Vuex from 'vuex';

import PassengerStore from './modules/passenger';

 

Vue.use(Vuex);

export default new Vuex.Store({

    modules: {

        user: PassengerStore

    },

});

 

//index.vue 使用

import PassengerStore from '@/store/modules/passenger';

import { getModule } from 'vuex-module-decorators';

 

...

created() {

  const PassengerStoreModule = getModule(PassengerStore, this.$store);

 

  console.log(PassengerStoreModule.loginInfo);

  PassengerStoreModule.getZhangsan();

  PassengerStoreModule.getLisi();

  console.log(PassengerStoreModule.userNumber);

  }

...

再试运行,发现跟之前的结果没差别.

 

命名空间

const moduleA1 = {

    namespaced: true,

    ...

};

const moduleA = {

    namespaced: true,

    modules: {

        a1: moduleA1,

    },

};

const moduleB = {

    // no namespaced

    ...

  };

export default new Vuex.Store({

    ...

    modules: {

        a: moduleA,

        b: moduleB,

    },

});

上面的例子,store包含了两个模块,a和b,a模块里面包含了a1,

打个比方a,a1和b的actions里面分别有个getMsgA(),getMsgB(),getMsgA1()方法,

在页面上用this.$store.dispatch调用这些方法.

a和a1都有命名空间,所以

this.$store.dispatch('a/getMsgA');

this.$store.dispatch('a/a1/getMsgA1');

由于b没有命名空间,所以this.$store.dispatch('b/getMsgB');是会报错的.

 

那么如果再a1里面如果查看root的state呢,vux提供了rootState, rootGetters.

 

actions: {

      someAction ({ dispatch, commit, getters, rootGetters }) {

        getters.someGetter // -> 'a/someGetter'

        rootGetters.someGetter // -> 'someGetter'

 

        dispatch('someOtherAction') // -> 'a/someOtherAction'

        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

 

        commit('someMutation') // -> 'a/someMutation'

        commit('someMutation', null, { root: true }) // -> 'someMutation'

      }

 

 
 
————————————————