开源软件名称(OpenSource Name):imageslr/taro-library开源软件地址(OpenSource Url):https://github.com/imageslr/taro-library开源编程语言(OpenSource Language):JavaScript 59.4%开源软件介绍(OpenSource Introduction):项目简介本项目是在线借书平台小程序使用 Taro 重构后的版本,仅包含三个示例页面,非常简单。面向人群主要是 Taro/React/Redux 的初学者,目的是提供一个简单的实践项目,帮助理解 Taro 与 Redux 的配合方式与 Taro 的基本使用。本项目还提供了一个快速搭建本地 mock 服务的解决方案。 因为我也是刚接触 Taro/React,所以只是分享一些开发经验,绕开一些小坑。如果觉得不错的话,请点右上角“ 技术栈Taro + Taro UI + Redux + Webpack + ES6 + Mock 项目截图目录运行项目本项目在以下环境中编译通过:taro v1.2.20、nodejs v8.11.2、微信开发者工具最新版。 首先需要安装必要的环境:
克隆项目:
启动小程序:
启动 mock 服务 (新建一个终端,在项目根目录下执行):
之后在微信开发者工具中导入项目,即可预览。 开始学习Taro 简介Taro 是一个遵循 React 语法规范的多端开发解决方案。最近想学习 React,于是就想到使用 Taro 重构很早之前开发的在线借书平台小程序。虽然 Taro 上手有一定难度,但是其 React 框架比小程序原生更为灵活与规范,给我带来了非凡的开发体验。 在正式开始之前,您必须对 Taro 框架、 React 语法与小程序框架有一定的了解。此外,我建议您阅读以下文档,会更容易上手:
开发工具开发工具:VS Code VS Code 对 JSX 与 TypeScript 有天然的支持,使用 VS Code 开发 Taro,不需要配置任何插件就能实现 Taro 组件的自动 import 与 props 提示,非常方便。 代码格式化插件我选择 Prettier,它屏蔽了很多配置项,强制遵循约定的规范。与之类似的格式化插件还有 Beautify,不过我更喜欢 Prettier 对 JSX 属性强制自动换行的风格。 ES Lint 是 JavaScript 与 JSX 的静态检测工具,安装 ES Lint 插件后在代码编写阶段就可以检测到不易发现的错误(如为常量赋值、变量未使用、变量未定义等等)。Taro 已经定义了一套 ES Lint 规则集,使用 taro-cli 生成的 Taro 项目基本不需要再作额外配置。 样式规范CSS 预处理器Taro UI 定义了很多变量与可复用的 mixins。为了与 Taro UI 样式风格保持一致,本项目采用 Taro UI 所使用的 Sass 作为 CSS 预处理器。 布局优先使用 Flex 布局。学习 Flex 布局可以参考这两篇文章: Taro UI 封装了一些常用的 Flex 样式类,包括:
不过 Taro UI 并没有为 BEM 命名规范关于 BEM,网上有很多的教程,就不再细说了。 .block {
//...
&__element {
//...
&--modifier {
//...
}
}
} 组件样式对于 组件可以使用 如果希望能够在组件的 // index.jsx
<MyComponent className='custom-class' style={/* ... */}> Taro 默认并不支持这一写法。我们可以将 // my-component.jsx
export default MyComponent extends Component {
static options = {
addGlobalClass: true
}
static defaultProps = {
className: '',
customStyle: {}
}
render () {
const { className, customStyle } = this.props
return <View
className={'my-class ' + className}
style={customStyle}
>
组件内容
</View>
}
} 尺寸单位Taro 的尺寸单位是
Taro 会将有大写字母的
项目初始化
安装项目依赖:
引入 ReduxRedux 文件设置在初始化的时候,我们选择了 Redux 模板。打开文件夹,可以看到 Taro 创建了一个示例页面,redux 相关的文件夹为:
这种方式是按照 Redux 的组成部分来划分的, 另一种划分方式是将同一份数据的所有文件组合在同一个文件夹里:
本项目采用第二种方式管理 Redux 数据。Taro 生成的 Redux 模板中已经添加了 代码见 dev-redux-init 分支。 connect 方法推荐先阅读 Redux 文档。 使用 Redux 之后,我们可以将数据存储在 从原理上来讲, 参数
mapStateToProps
举个例子: const mapStateToProps = (state) => {
return {
count: state.count
}
} 这段代码的功能是将 我们还可以使用 ES6 的对象解构赋值、属性简写和箭头函数等语法,进一步简化上面的代码: const mapStateToProps = ({ count }) => ({
count
}); 有时候我们需要根据组件自身的 mapDispatchToProps
举个例子: import { add, minus, asyncAdd } from "@store/counter/action";
const mapDispatchToProps = (dispatch) => {
return {
add() {
dispatch(add());
},
dec() {
dispatch(minus());
},
asyncAdd() {
dispatch(asyncAdd());
}
}
} 当我们调用 使用 connect 方法使用 import { add, minus, asyncAdd } from "@store/counter/action";
// 首先定义组件
class MyComponent extends Component {
render() {
return;
<View>
<Button onClick={this.props.add}>点击 + 1</Button>
<View>计数:{this.props.count}次</View>
</View>;
}
}
// 定义 mapStateToProps
const mapStateToProps = ({ count }) => ({
count
});
// 定义 mapDispatchToProps
const mapDispatchToProps = dispatch => {
return {
add() {
dispatch(add());
}
};
};
// 使用 connect 方法,export 包装后的新组件
export connect(mapStateToProps, mapDispatchToProps)(MyComponent); 这种分散的写法不利于我们查看组件从 Redux 中引入了多少 import { add, minus, asyncAdd } from "@store/counter/action";
@connect(
({ counter }) => ({
counter
}),
dispatch => ({
add() {
dispatch(add());
}
})
)
class MyComponent extends Component {
render() {
return;
<View>
<Button onClick={this.props.add}>点击 + 1</Button>
<View>计数:{this.props.count}次</View>
</View>;
}
}
export default MyComponent; 我们甚至可以使用对象形式来传递 @connect(
({ counter }) => ({
counter
}),
{
// 调用 this.props.dispatchAdd() 相当于
// 调用 dispatch(add())
dispatchAdd: add,
dispatchMinus: minus,
// ...
}
) 这就是 Taro 组件与 Redux 结合的最终形式。 异步 Action异步 Action 返回的是一个参数为 Taro Redux 模板提供了一个异步 Action 的简单示例: /* /store/counter/action.js */
export function asyncAdd() {
return dispatch => {
setTimeout(() => {
dispatch(add());
}, 2000);
};
}
// 组件中
@connect(
({ counter }) => ({
counter
}),
dispatch => ({
asyncAdd() {
dispatch(asyncAdd());
}
})
)
class MyComponent extends Component {
render () {
return <Button onClick={this.props.asyncAdd}>点击 + 1</Button>
}
} 可以看到,异步 Action 和常规 Action 在使用上并没有任何区别。 API 封装Taro 已经封装了网络请求,支持 Promise 化使用。本项目对 域名切换生产环境使用线上接口,开发环境使用本地接口。新建 export default BASE_URL =
process.env.NODE_ENV === "development"
? "http://localhost:3000" // 开发环境,需要开启mock server(执行:gulp mock)
: "TODO"; // 生产环境,线上服务器 封装请求代码见 /src/service/api.js,代码非常简单。访问后台所需要的认证信息(token)可以添加在 添加拦截器Taro 支持添加拦截器,可以使用拦截器在请求发出前后做一些额外操作。 为什么要用拦截器呢?设想一下网络请求的场景。我们的目的是发出一个网络请求并接收响应,但是在发出请求之前,我们可能需要检查数据、添加用户的权限信息;如果项目大一些,我们可能还需要在发出请求之前先上报统计数据。这一系列流程之后才能真正执行我们的目标操作:网络请求。而获取到服务器响应后,我们还需要根据状态码执行不同的操作:401/403 跳转到登录页面,404 跳转到空白页面,500 展示错误信息... 可以看到,如果将这些流程的代码都写到一起,那么代码将又长又乱,十分复杂。 我们可以使用拦截器来解决这个问题。拦截器就是中间件,可以帮助我们优雅地分离业务逻辑。我们将每一个业务逻辑写成一个拦截器,在每个拦截器中,只需要关注当前阶段的代码实现。 中间件的处理流程又称为洋葱模型,其执行过程是:先从最外层中间件从外到内依次执行到核心程序,再从核心程序从内到外依次执行到最外层中间件,每一个中间件的执行参数均是前一个中间件的返回值。如下图所示: 下面是一个简单的中间件/拦截器示例代码: /**
* @param {object} req request对象
* @param {function} next 调用下一个中间件的函数
*/
function interceptor(req, next) {
// 在下一个中间件执行之前做一些操作...
// 比如添加一个参数
req.token = 'token'
// 执行下一个中间件...
// 保存其返回值
var res = next(req)
// 在下一个中间件返回结果之后做一些操作...
// 比如判断服务器返回的状态码
if(res.status == 401){
// ...
}
return res
} 而 全部评论
专题导读
上一篇:SmartReceipts/SmartReceiptsLibrary: A customizable, easy-to-use receipt scanner ...发布时间:2022-08-15下一篇:yaozeliang/Library: Django发布时间:2022-08-15热门推荐
热门话题
阅读排行榜
|
请发表评论