前言
🥬🐔最近忙着准备面试,恶补基础原理好久都没敲代码,项目的BUG也好久没修了噗。然后项目组又有的一个新的需求涉及到小程序,所以就打算开始弄一个平台的小程序端,前期定位的话是作为一个辅助支撑教学的方式吧,如果后续有时间和需求会继续完善。
好久没有写Taro了,有啥地方写的不对的欢迎大家指出来!还有 TS 😂用的还不是很熟练....
现在来记录一下搭建(踩 坑)过程吧
目前暂时计划实现如下功能:
- 账号
- 比赛报名、进度查询
- 课程、课堂
- 题库
- 讨论
- ...
WEB项目线上地址: oj.bnuz.edu.cn
项目技术栈
- Taro Next (当踩坑了)
- DvaJs (用习惯了)
- TypeScript (大势所趋)
- Taro-UI (方便😂)
啥也不说了 开踩
项目搭建
新建项目
首先安装新的 Taro-cli
需要使用 npm 或者 yarn 全局安装 @tarojs/cli,或者直接使用 npx:
# 使用 npm 安装 CLI
$ npm install -g @tarojs/cli@next
# OR 使用 yarn 安装 CLI
$ yarn global add @tarojs/cli@next
# OR 安装了 cnpm,使用 cnpm 安装 CLI
$ cnpm install -g @tarojs/cli@next
在这里我踩了个坑,如果之前是有安装过 Taro-Cli 的 这里建议使用 cnpm 去安装 taro cli@next,我用 npm 安装后,虽然成功了,但是实际上 cli 的版本还是 2.0,在 issue 找到说可以使用 cnpm 解决,试了后果然可以...... 还有一些具体的迁移问题可以看这里Taro Next 迁移指南
PS:一开始没好好看文档,没看到@taro-redux
不会再维护,哎...这里卡了贼久,所以这里需要安装react-redux
的依赖。
安装好后运行 taro init xxxxxx
xxxxxx 为项目名。
在这里的话会通过 git 拉取模版啥的,还是挺慢的。
配置方面的话,这里的话就按照个人习惯去选择就好了,我的话就选择 Ts + Sass + 默认模版,然后再等个几分钟就好了。
依赖安装
在终端的项目根目录下安装如下依赖:
-
DVA
npm install --save dva-core dva-loading
-
Redux
npm install --save redux @tarojs/redux @tarojs/redux-h5 redux-thunk redux-logger
-
Taro-UI
npm install taro-ui
配置项目文件
项目结构
src
目录下
assets
:静态资源components
:通用组件pages
:页面文件目录constants
:一些常量models
:DVA的 modelsservices
:utils
:基础工具类
配置完之后
src
├── app.config.ts
├── app.scss
├── app.ts
├── assets
├── constants
├── index.html
├── mock
├── models
├── pages
│ └── index
│ ├── index.config.ts
│ ├── index.scss
│ └── index.tsx
├── services
└── utils
DVA
在 src/utils
下创建dva.ts
import { create } from "dva-core";
import { createLogger } from "redux-logger";
import createLoading from "dva-loading";
let app
let store
let dispatch
let registered
function createApp(opt) {
// redux 的日志
opt.onAction = [createLogger()]
app = create(opt)
app.use(createLoading({}))
if (!registered) {
opt.models.forEach(model => app.model(model));
}
registered = true;
app.start()
store = app._store;
app.getStore = () => store;
app.use({
onError(err){
console.log(err);
}
})
dispatch = store.dispatch;
app.dispatch = dispatch;
return app;
}
export default{
createApp,
getDispatch(){
return app.dispatch
}
}
在 src/models
下创建 index.ts
用来导出所有的 model
这里我是把 model 全部集中到 models 里面,也可以把 model 放在页面文件夹下,根据个人习惯。
import global from './global';
export default [
// 放导出的models
global,
]
根据你的习惯定义好 model
,这里是 src/models/global.ts
import { Subscription, Effect } from 'dva';
import { Reducer} from "redux";
export interface GlobalModelState {
// 定义state
}
export interface GlobalModelType {
namespace: 'global',
state: GlobalModelState,
effects: {
// xxxxx: Effect xxxx是effect的名字
},
reducers: {
// xxxx: Reducer<GlobalModelState>
};
subscriptions: {
//xxx: Subscription
}
}
const GlobalModel: GlobalModelType = {
namespace: 'global',
state: {
},
effects: {
// effect函数
},
subscriptions: {
// 订阅
},
reducers: {
// reducer
}
};
export default GlobalModel;
在入口文件 app.tsx
(这里将 app.ts
改成 app.tsx
)导入 DVA
import React, { Component } from 'react'
import { Provider} from "@tarojs/redux";
import dva from './utils/dva';
import models from './models';
import './app.scss'
const dvaApp = dva.createApp({
initialState: {},
models: models,
});
const store = dvaApp.getStore();
class App extends Component {
componentDidMount () {}
componentDidShow () {}
componentDidHide () {}
componentDidCatchError () {}
// 在Taro Next中 config改为外部文件配置 在.config.ts
// this.props.children 是将要会渲染的页面
render () {
return (
// 注入dva
<Provider store={store}>
{this.props.children}
</Provider>
)
}
}
export default App
然后就可以愉快的npm run dev:weapp
试试了
简单的例子
但也感知不到 dva 的存在,现在我们写一个简单的例子
首先在 models/global
export interface GlobalModelState {
name: string, // 增加name定义
}
export interface GlobalModelType {
namespace: 'global',
state: GlobalModelState,
effects: {
changeName: Effect, // 增加changeName的Effect
},
reducers: {
saveName: Reducer, // 增加saveName的Reducer
};
subscriptions: {
//xxx: Subscription
}
}
effects: {
*changeName({ payload }, { put, call }) {
const response = yield call(fakeGlobalChangeName, payload); // 这里调用services层
yield put({
type: 'saveName',
payload: {
name: payload.name,
}
})
}
},
reducers: {
// reducer
saveName(state, { payload }) {
return {
...state,
name: payload.name
}
}
}
然后在 services
下创建global.ts
export interface ChangeNameParamsType {
name: string | number,
}
export async function fakeGlobalChangeName(params: ChangeNameParamsType) {
return Promise.resolve(params.name + '' + Math.random() * 1000 )
// 请异步API请求
}
回到index.tsx
就应该
import React, { useEffect } from 'react';
import {Button, View} from "@tarojs/components";
import { connect } from 'react-redux';
import './index.scss'
import {ConnectState, GlobalModelState} from "../../models/connect";
import {Dispatch,AnyAction} from "redux";
interface IndexPropsType {
global: GlobalModelState,
dispatch: Dispatch<AnyAction>,
}
const Index: React.FC<IndexPropsType> = props => {
const { dispatch, global} = props;
useEffect(() => {
// componentDidMount
}, []);
const handleChangeName = () => {
dispatch({
type: 'global/changeName',
payload: {
name: 'hei',
}
})
};
return <View>
{global.name}
<Button onClick={handleChangeName}>点击</Button>
</View>
}
export default connect(({ global }: ConnectState) => ({
global
}))(Index);
打开console
就可以看到整个的 Dva 是怎么走的
这样就测试了一个简单的 dva 数据流的流程
这个例子只是为了走个流程,实际上肯定不是啥都要走 DVA(HOOKS不香吗)
到这里的话基本上雏形已经出来了,但是一些还缺少了各种基础的工具类、路径的别名、request的封装,logger、常量、项目config、mock、基本组件封装.......一堆东西。
但上面那些的东西话 100 个人有 100 种写法 ... 嗯 ... 对 (肯定不是我懒得写下去了)
一些常用的基本库啥的下次再记录吧~
踩坑合集
首先真的要去看一下
Taro Next 的迁移指南!!Taro Next 的迁移指南!!Taro Next 的迁移指南!!
去过一遍的话真的能少踩很多坑😢
- redux 等第三方 React 库的依赖变了
- 属于框架本身的 API 由框架的包引入
- TaroCli 和 Taro 要注意版本
- 会有一个新的文件:.config.js , 代表你页面/项目文件的文件名,config 文件必须和页面/项目文件在同一文件夹
- 路由的获取方式变了
- 注意依赖的更新!!
- 生命周期改名
- 有自带的HOOKS
- 多看文档 多看文档 多看文档
Taro-UI
关于Taro-UI 在引入全局 scss 的时候会报路径找不到,关于这个问题issue里面也有,这个属于还没适配Taro Next吧。然后 Taro 的交流群也给出了解决方案
来自Taro开发交流群@Goodman
taro next的taro-ui 问题,临时修复方法
package.json更新依赖:taro-ui: NervJS/taro-ui#next
{
"dependencies": { "taro-ui": "NervJS/taro-ui#next" }
}
复制 cp -r ./node_modules/taro-ui/src ./src/taro-ui
修改 config/index.js
const path = require('path')
const config = {
alias: {
"taro-ui": path.resolve(__dirname, '../src/taro-ui'),
"nervjs": path.resolve(__dirname, '../node_modules/react')
},
}
我试了一下,确实是可以用的,不过AtCalendar这个组件报
Module not found: Can't resolve 'dayjs' in 'src/taro-ui/components/calendar'
暂时先注释掉了这个组件
执行 npm i dayjs 就可以了
上面是社区的解决方案,我自己的话就没有把taro-ui搬出来采用的是以下
package.json更新依赖:taro-ui: NervJS/taro-ui#next
config/index.js
const config = {
alias: {
"taro-ui": path.resolve(__dirname, '../node_modules/taro-ui/src'),
"nervjs": path.resolve(__dirname, '../node_modules/react')
},
...
}
因为我用了自定义的主题
所以定义了custom-theme.scss
/* Custom Theme */
$color-brand: #52c41a !default;
$color-brand-light: #7dd353 !default;
$color-brand-dark: #429d15 !default;
/*Taro UI 默认样式*/
@import 'taro-ui/style/index.scss';
然后再app.tsx引入scss就好了
TaroUi的组件还是import from 'taro-ui'
上面就是一个临时的解决办法,希望官方大大早点适配吧!!
溜了溜了 还要去复习
剩下的下次再记录吧
哪里写的不妥的希望各位大佬们指出!!