本文的示例代码参考hello-taro
目录
准备
安装
node -v
# v12.14.1
cnpm i -g @tarojs/cli
taro -v
# 3.0.17
初始化
taro init hello-taro
# ? 请输入项目介绍!
# ? 请选择框架 React
# ? 是否需要使用 TypeScript ? No
# ? 请选择 CSS 预处理器(Sass/Less/Stylus) Sass
# ? 请选择模板源 Gitee(最快)
# ✔ 拉取远程模板仓库成功!
# ? 请选择模板 taro-ui
cd hello-taro
cnpm run dev:h5
小程序
- 下载并安装微信开发者工具
cnpm run dev:weapp
- 微信开发者工具 => 导入项目 => hello-taro/dist
登录页
mkdir src/pages/login/
vim src/pages/login/index.jsx
import React, { Component } from 'react'
import { View, Text } from '@tarojs/components'
export default class Index extends Component {
render() {
return (
<View className='index'>
<Text>登录页面</Text>
</View>
)
}
}
vim src/pages/login/index.config.js
export default {
navigationBarTitleText: '登录'
}
vim src/app.config.js
export default {
pages: [
'pages/index/index',
'pages/login/index'
],
// 省略未修改代码
}
vim src/pages/index/index.jsx
import React from 'react'
import { View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { AtButton } from 'taro-ui'
import "taro-ui/dist/style/components/button.scss" // 按需引入
export default function Index() {
return (
<View className='index'>
<AtButton type='primary' onClick={() => {
Taro.navigateTo({
url: '/pages/login/index'
})
}}>登录</AtButton>
</View>
)
}
状态管理
vim src/pages/login/index.jsx
import React, { useState } from 'react'
import { View, Text } from '@tarojs/components'
import { AtButton, AtInput } from 'taro-ui'
import "taro-ui/dist/style/components/input.scss"
import "taro-ui/dist/style/components/button.scss"
export default function Login() {
const [username, setUsername] = useState()
const [password, setPassword] = useState()
const handleUsernameChange = (value) => {
setUsername(value)
}
const handlePasswordChange = (value) => {
setPassword(value)
}
const handleLogin = () => {
console.log('login onclick')
}
return (
<View className='index'>
<AtInput
name='username'
title='用户名'
type='text'
placeholder='请输入用户名'
value={username}
onChange={handleUsernameChange}
/>
<AtInput
name='password'
title='密码'
type='password'
placeholder='请输入密码'
value={password}
onChange={handlePasswordChange}
/>
<AtButton
type='primary'
size='normal'
onClick={handleLogin}
>
登录
</AtButton>
<Text>{username} | {password}</Text>
</View >
)
}
cnpm i --save dva-core dva-loading redux react-redux redux-logger
mdkir src/utils src/models
vim src/utils/dva.js
import { create } from 'dva-core'
import createLoading from 'dva-loading'
import { createLogger } from 'redux-logger'
let app, store, dispatch, registered
function createApp(options) {
options.onAction = [createLogger()]
app = create(options)
app.use(createLoading({}))
if (!global.registered) {
options.models.forEach(model => app.model(model))
}
registered = true
app.start()
store = app._store
app.getStore = () => store
dispatch = store.dispatch
app.getDispatch = () => dispatch
return app
}
export default { createApp }
vim src/models/login.js
const namespace = 'login'
export default {
namespace,
state: {
count: 0
},
reducers: {
overrideStateProps(state, { payload }) {
return {
...state,
...payload
}
}
},
}
vim src/models/index.js
import login from './login'
export default [login]
vim src/app.js
import React, { Component } from 'react'
import { Provider } from 'react-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 {
render() {
return <Provider store={store}>{this.props.children}</Provider>
}
}
export default App
vim src/pages/login/index.jsx
// 省略未修改代码
import { useDispatch, useSelector } from 'react-redux'
export default function Login() {
const dispatch = useDispatch()
const { count } = useSelector(store => store.login)
// 省略未修改代码
const handleLogin = () => {
dispatch({
type: 'login/overrideStateProps',
payload: {
count: count + 1
}
})
}
return (
<View className='index'>
// 省略未修改代码
<Text>{username} | {password} | {count}</Text>
</View >
)
}
请求接口
vim src/utils/request.js
import Taro from '@tarojs/taro'
export default (options = { method: 'GET', data: {}, url: '' }) => {
return Taro.request({
url: options.url,
data: {
...options.data
},
header: {
'Content-Type': 'application/json'
},
method: options.method.toUpperCase()
}).then(res => res.data)
}
mkdir src/services
vim src/services/login.js
import request from '../utils/request'
export default class Login {
static login(params) {
return request({
url: 'http://test.nuozhilin.site/demo/login',
method: 'POST',
data: {
...params
}
})
}
}
vim src/models/login.js
import Login from '../services/login'
import Taro from '@tarojs/taro'
// 省略未修改代码
export default {
// 省略未修改代码
effects: {
*login({ payload }, { call }) {
const { username, password } = payload
const response = yield call(Login.login, { username, password })
if (response.code === 0) {
Taro.showToast({
title: '登录成功',
icon: 'none'
})
} else {
Taro.showToast({
title: '密码错误',
icon: 'none'
})
}
}
}
}
vim src/pages/login/index.jsx
// 省略未修改代码
export default function Login() {
// 省略未修改代码
const handleLogin = () => {
dispatch({
type: 'login/overrideStateProps',
payload: {
count: count + 1
}
})
dispatch({
type: 'login/login',
payload: {
username,
password
}
})
}
// 省略未修改代码
}