继续上一篇:✋手摸手系列(一/2): vite react typescript reactHook mobx(非脚手架)(从0开始):路由和权限搭建
后台系列目录
-
✋手摸手系列(一/1): vite react typescript reactHook mobx(非脚手架)(从0开始)(包含路由权限控制)
-
✋手摸手系列(一/2): vite react typescript reactHook mobx(非脚手架)(从0开始):路由和权限搭建
-
✋手摸手系列(一/3): vite react typescript reactHook mobx(非脚手架)(从0开始):mobx 接入
参考资料:mobx.js.org/README.html
项目地址:github.com/wowhoonet/v…
安装依赖
yarn add mobx mobx-react
创建文件 store->user.ts 代码如下:
import { IUser } from "@/interface/user";
import { observable } from "mobx";
export const user = observable<{
token: string;
user: IUser
}>({
user: {} as IUser,
token: ''
});
observable是将对象监听,实现proxy代理,如果要将数据双向绑定就需要observable装饰数据,mobx 默认推荐的是 class 装饰器模式@observable写法,但是我们这里用的 hook 所以还是用都用 function写法了
创建 interface-> user.ts 代码如下:
export interface IUser {
name: string,
age: number
}
开始实现登录逻辑
创建 service-> login.ts 代码如下:
import { IUser } from "@/interface/user";
import { user } from "@/store/user";
import { runInAction } from "mobx";
export const loginService = {
logIn({}: { userName: string; password: string }): Promise<IUser> {
// 模拟请求
return new Promise((resolve, reject) => {
const rep = {
token: 'xxx',
user: {
name: 'wowhoo',
age: 24
}
}
// 将两次赋值操作放入一次 action 动作内,避免重复通知
runInAction(() => {
user.token = rep.token;
user.user = rep.user;
})
resolve(rep.user)
})
},
};
需要解释一下,我这里的 service 层是逻辑处理层,主要是通过 api请求改变本地的 store 数据,避免直接在页面引用 store 然后修改,这样无法约定跟踪;
加入登录逻辑
修改 wrapper->auth.tsx
import React from 'react';
import { Redirect } from 'react-router';
import {user} from '@/store/user';
export default function Auth (props: {
children: React.ReactElement
}): React.ReactElement {
const isLogin = !!user.token;
const {children, ...cprops} = props;
if(isLogin) {
return children
}
return <Redirect to="/login"></Redirect>;
}
判断用户的 token 存不存在,根据业务逻辑,此处仅供参考具体可以根据业务逻辑
修改 view-> login-> index.tsx
import React from 'react';
import {loginService} from '@/service/login'
import { useHistory } from 'react-router';
export default function Login (): React.ReactElement {
const history = useHistory();
const onLogin = () => {
loginService.logIn({
userName: 'wowhoo',
password: '123',
}).then(() => {
history.push('/home')
})
}
return <div>
登录页面
<button onClick={onLogin}>登录</button>
</div>;
}
useHistory是 reactRouter 的 hook 写法;这里点击登录的时候调用了 service 层暴露的 logIn 方法
修改 view-> home-> index.tsx
import React from 'react';
import { useObserver } from 'mobx-react';
import {user} from '@/store/user'
export default function Home (): React.ReactElement {
return useObserver(() => {
return <div>
username: {user.user.name}
年龄:${user.user.age}
</div>
});
}
需要注意的是useObserver的用法,useObserver是将包裹的组件动态化,能根据 store 的值来重新 render,这也是 mobx 的一个比较便捷的地方
Run!run 起来
我们先访问http://localhost:3000/#/home 发现会重定向/login,这是我们 auth 拦截器在生效,然后我们点击登录,跳转到/home,这是我们实现了登录逻辑,将 store 里面塞入了 token 信息,auth 拦截器校验通过
总结
- 引入 mobx 系列包,包含 mobx 基础库,和 mobx-react 的 react 版本,后面这个主要是使用 mobx 能够动态改变ui
- 使用 service 层来改变 store,避免在非 service 层改变 store,原则上应该遵守数据追溯
- 使用observable修饰实体,实现监听;如果一个方法中多次改变同一个 store 则需要使用 runInaction 方法包裹;使用useObserver将Ui 根据 store 改变自动刷新;