现在这个 /posts 页面上显示的数据,是直接在 post-list 组件里获取到的,组件被创建以后,请求服务端应用的内容列表接口,然后把请求回来的数据交给数组的 posts 这个数据。
在组件的模板里循环 posts 这个数据,把每次循环的内容项目交给 post-list-item 组件的 item 属性。在 post-list-item 组件的模板里会绑定输出组件的 item 属性里的一些东西。
Store 模块类型
下面我们可以把内容列表组件需要的数据转换到应用的 store 里,通过 store 里的动作去获取组件需要的数据。可以先新建一个 store 模块。
放在 src/post/index 的下面,名字叫 post-index.store.ts。
先定义并导出一个 interface,名字是 PostIndexStoreState ,这个 store 模块里的数据,有一个 loading ,类型是 boolean,还有一个 posts ,类型是一个 Array,数组项目的类型可以单独再去定义一下。
先把它放在 post.store 这个模块里,定义并导出一个 interface ,名字叫 PostItem ,里面可以描述一下每个内容项目是什么样的,暂时先添加几个属性,有一个 id ,类型是 nubmer,一个 title 类型是 string,还有一个 content ,类型是 string。
回到 post-index 这个 store 模块,设置一下 posts 这个属性的类型, Array 里的项目的类型设置成 PostItem 。 这个类型来自 post.store 。
定义 Store 模块
下面可以定义并导出一个 store 模块,起个名字叫 postIndexStoreModule,它的类型是 Module,这个 Module 来自 vuex, 两个参数,一个是这个 store 模块里的 state 类型,这里就是 PostIndexStoreState,还有一个 是 store 的 RootState 类型。
这个 store 模块是一个对象,里面先把 namespaced 设置成 true ,表示要使用命名空间。
然后定义一个 state,它是这个 store 模块里的数据,里面有一个 loading 默认让它等于 false,还有一个 posts,默认让它等于一个空白的数组。
断言这个 state 类型是 PostIndexStoreState。
获取这个 store 模块里的数据,可以通过 getters , 先添加一个 loading ,接收一个 state 参数,返回的值就是 loading 这个 state。
再添加一个 posts,接收一个 state 参数,返回的是 posts 这个 state。
定义 mutations
修改 store 里的 state 用的是 mutations, 添加一个 setLoading ,接收一个 state 参数,还有一个 data 参数,这个 mutation 修改的是 loading 这个 state 的值。
下面再添加一个 setPosts ,用这个 mutation 修改 posts 这个 state 的值。
定义动作 actions
下面再去定义一个获取内容列表数据用的动作,放在 store 模块的 actions 里面,用 async 标记一下这个动作,动作的名字是 getPosts, 动作里需要 commit 修改,可以直接把它从动作的 context 参数里解构出来。
在这个动作里先 commit 一个 setLoading, 用这个 mutation 把这个 store 模块里的 loading 这个 state 的值设置成 true。
我们可以在组件里使用这个 loading 数据,执行 getPosts 这个动作的时候 loading 会先变成 true,等成功获取到数据,或者请求出了问题以后,再把这个 loading 改成 false。
在这个动作里,用一组 try,catch 。 先处理一下发生的问题,可以 commit 一个 setLoading ,把 loading 改成 false 。 然后可以再 throw error.resposne。
这样在组件里使用这个动作的时候,如果出了问题,catch 到的错误就是这个请求的响应。
在 try 这个区块里,添加一个 resonse ,等于 await, 用一下 apiHttpClient ,这个东西来自我们之前创建的 app.service。
用一下它上面的 get 方法,发送一个 get 类型的 http 请求。请求的接口地址是 /posts 。 请求以后 commit 一个 setLoading,把 loading 改成 false。 因为这时候请求已经成功了。
再 commit 一个 setPosts,把 response 里的 data 交给 posts 这个数据。 响应里的 data 就是服务端响应回来的具体的数据。
最后可以再 return 这个 response。
使用 Store 模块
打开 post.store ,在这个 store 模块里,添加一个 index 模块,对应的就是刚才我们定义的 postIndexStoreModule 。
然后打开 post-list 组件, 删除掉 created 里的直接请求接口的代码,组件的数据也可以删除掉,去掉导入的 apiHttpClient,在上面导入 vuex 里的 mapGetters 还有 mapActions,它们都来自 vuex。
在组件里面可以添加一个 computed,里面是组件的计算属性,把执行 mapGetters 返回的东西放进来。 一个对象参数,让 loading 对应 post/index 里的 loading 这个获取器。 再让 posts ,对应 post/index/posts 这个获取器。
因为在 store 模块里使用的命名空间,所以使用在它们里面定义的 getters ,mutations 还有 action 的时候要加上模块的名字。
这里的意思就是 post 模块里的 index 这个模块里的 posts 这个获取器。前面这个 posts 是我们给这个获取器返回的数据在当前这个组件里起的一个名字。
在组件里再添加一个 methods ,把执行 mapActions 返回的结果放进来。一个对象,动作在当前组件里可以叫 getPosts ,对应的就是 post/index/getPosts 这个动作。
这样我们就可以直接在这个组件里使用 getPosts 这个方法了。 在 created 里面,用一下 getPosts, 实际上执行的就是 post/index 这个 store 模块里的 getPosts 这个动作。
这个动作会去请求服务端的内容列表接口,通过这个 store 模块里的 posts 获取器可以得到应用接口响应回来的内容列表数据。
在组件模板里可以再添加一个 div, 在元素上用 v-if 判断一下,loading, 如果它的值是 true 的话,可以在界面上显示一个 加载中...
预览
最后再回到浏览器预览一下,现在界面上仍然会显示一组内容列表。现在这组内容列表数据是通过 post-index 这个 store 模块里的 getPosts 动作获取到的。