# 前端培训资料 - 小程序 ## 前期准备 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 注入全局状态,获取全局状态数据