# 前端培训资料 - 小程序
## 前期准备
1.node 环境配置在 14 及以上,可以使用 nvm 进行 node 环境管理
2.下载微信开发者工具
3.同步项目仓库
## 启动
1.命令行运行 `npm install` 或 `yarn` 安装依赖
2.因为患者端小程序里面包含多个项目,所以一定要使用 `yarn replace:by` 命令,把项目配置切换到白云(其他项目同理,具体命令看 `package.json`)
3.命令行运行 `npm run dev:weapp-by` 或 `yarn dev:weapp-by` 运行项目(其他项目同理,具体命令看 `package.json`)
4.运行后,在项目根目录 `dist_by/weapp` 下会生成打包产物(其他项目同理,打包产物以 `dist_` 开头,加以特殊的项目名称后缀)
5.微信开发者工具导入打包产物 `dist_by/weapp`,即可预览项目
## 上传
1.1.使用 `yarn build-qa:weapp-by` 打包编译白云小程序 QA 环境(其他项目同理,具体命令看 `package.json`)
1.2.使用 `yarn build:weapp-by` 打包编译白云小程序生产环境(其他项目同理,具体命令看 `package.json`)
2.打包后,在项目根目录 `dist_by/weapp` 下会生成打包产物(其他项目同理,打包产物以 `dist_` 开头,加以特殊的项目名称后缀)
3.点击微信开发者工具右上方上传按钮,填写新版本好和基本信息,即可把打包产物上传到体验版(需微信后台管理员设置上传权限)
## react 项目与 taro
### 项目结构
```js
├── dist 编译结果目录
|
├── config 项目编译配置目录
| ├── index.js 默认配置
| ├── dev.js 开发环境配置
| └── prod.js 生产环境配置
|
├── src 源码目录
| ├── pages 页面文件目录
| | └── index index 页面目录
| | ├── index.js index 页面逻辑
| | ├── index.css index 页面样式
| | └── index.config.js index 页面配置
| |
| ├── app.js 项目入口文件
| ├── app.css 项目总通用样式
| └── app.config.js 项目入口配置
|
├── project.config.json 微信小程序项目配置 project.config.json
|
├── babel.config.js Babel 配置
├── tsconfig.json TypeScript 配置
├── .eslintrc ESLint 配置
|
└── package.json
```
### 生命周期
入口组件生命周期,项目入口使用,针对全局的请求或设置可在此阶段运行
```js
class App extends Component {
// 对应 onLaunch
// 在小程序环境中对应 app 的 onLaunch
// 在此生命周期中通过访问 options 参数或调用 getCurrentInstance().router,可以访问到程序初始化参数
onLaunch() {}
// 可以使用所有的 React 生命周期方法
componentDidMount() {}
// 对应 onShow,程序启动,或切前台时触发。
componentDidShow() {}
// 对应 onHide
// 程序切后台时触发。
componentDidHide() {}
render() {
// 在入口组件不会渲染任何内容,但我们可以在这里做类似于状态管理的事情
return (
{/* this.props.children 是将要被渲染的页面 */}
{this.props.children}
);
}
}
```
页面组件生命周期,页面中使用
```js
class Index extends Component {
// 可以使用所有的 React 生命周期方法
componentDidMount() {} // 一般接口请求会放在此阶段进行
// onLoad
onLoad() {}
// onReady
onReady() {}
// 对应 onShow
componentDidShow() {}
// 对应 onHide
componentDidHide() {}
render() {
return ;
}
}
```
---
### 全局状态管理
小程序使用 mobx 进行全局状态管理(如个人信息,授权信息等),以下以简化后的个人信息为例:
#### 设置初始值
在项目目录 `src/store/index.js` 中,设置初始值
```JS
import { observable } from "mobx";
const userInfo = observable({ // 此对象就是可以监听的对象
nickname: "",
initData(res) { // 初始化时调用
this.nickname = res.nickname;
},
bindUser(res) { // 变更状态时调用
this.nickname = res.nickname;
}
});
export default userInfo;
```
#### 全局设置
必须在项目目录入口文件 `src/app.js` 中设置全局 store
```JS
import userInfo from "./store/index.js";
import { Provider } from "mobx-react";
const store = {
userInfo,
};
class App extends Component {
render() {
return {this.props.children};
}
}
```
#### 局部监听
在需要监听的页面或者组件中,将 Provider 中设置的 store 提取到组件的 props 中,下面以白云小程序个人中心页面为例:
在 `src/pages/users/userPage` 中:
```js
import { observer, inject } from "mobx-react";
@inject("userInfo")
@observer
class ByUser extends Component {
render() {
const { nickname } = this.props.userInfo || {};
return {nickname};
}
}
```
#### 更新状态
在 `src/pages/users/userPage` 中,使用已经经过初始化的 `bindUser` 函数进行状态变更,重新渲染页面
```js
import { observer, inject } from "mobx-react";
@inject("userInfo")
@observer
class ByUser extends Component {
handleChangeName = () => {
const userInfo = this.props.userInfo || {};
userInfo.bindUser({ nickname: "xxx" });
};
render() {
const { nickname } = this.props.userInfo || {};
return handleChangeName()}>{nickname};
}
}
```
### 标准页面结构
```js
import { observer, inject } from "mobx-react";
@inject("userInfo") // 注入需要监听的全局状态
@observer
class ByUser extends Component {
//初始化页面所需的变量
state = {
name: ''
}
// 在此生命周期中获取接口数据,设置初始值
componentDidMount(){
this.initData()
}
initData = async () => {
const result = await getName()
this.setState({
name: result.name
})
}
// 修改state
handleChangeNickName = () => {
this.setState({
name: 'yyy'
})
}
// 修改全局状态
handleChangeName = () => {
const userInfo = this.props.userInfo || {};
userInfo.bindUser({ nickname: "xxx" });
};
render() {
const { nickname } = this.props.userInfo || {};
const { name } = this.state
return (
handleChangeNickName()}>{nickname}
handleChangeName()}>{name}
;
)
}
}
```
## 项目运行流程
1. 入口文件 `src/app.js`,统一入口,注入全局状态 store
2. `src/index/index`,微信小程序的唯一入口,在此获取 token/鉴权/路由判断/二维码判断,跳转到指定的路由
- 2.1 通过 `handleToken` 获取 token 和个人信息
- 2.2 通过判断路由参数 `q` 和 `pathname`,加上解析参数 `query`,跳转到具体业务页面,适用于固定链接(不需要关注或通过公众号),如 `https://m-qa.ywtinfo.com/thnethospwe/prescriptionOrder?bizNo=P201811011958115320228626&orderId=20991`
- 2.3 通过判断路由参数 `entry`,跳转到具体业务页面,使用于动态链接(从公众号通过链接跳转到小程序的某个页面),如 `pages/index/index?entry=by/medical_record_mailing/newborn?mailingOrderId=mailingOrderId`
- 2.4 跳转到默认首页 `/pages/index/home`
3. 具体页面渲染
- 3.1 生命周期,接口获取数据
- 3.2 注入全局状态,获取全局状态数据