React + TypeScript + Taro前端开发小结
前言
项目到一段落,先来记录一下,本文以前端新手的角度记录React、TypeScript、Taro相关技术的开发体验以及遇到的问题和解决方法。
之前总说要学React(这篇博客:代码使我头疼之React初学习),这次项目需要做H5前端+小程序,我终于能用上React了~
使用React的开发框架之前就听过京东的Taro,所以就这个了,直接开码。
关于React
不错,感觉比Vue的模板写法自由很多,我看Taro文档的例子都是class组件,但一开始「前端带师」就推荐我用function组件,现在我全都是用function组件,react就该这么写,真香~
因为之前写了一段时间的Flutter,所以react对我来说很亲切,至少可以无缝上手声明式UI的写法。
不过我感觉React的生态太大,更新太快了,有点碎片化,很多第三方库官方文档都跟不上更新速度(批评一下mobx,害人不浅)
话说一开始我看了某位知乎大V的那本React和Redux的书,应该是我太菜的原因,感觉不是很容易理解,果然技术厉害的大佬不一定教书也厉害吗~
参考资料
- React 入门 - 从js的角度理解 react:https://github.com/coppyC/blog/issues/16
关于TypeScript
第一次用TypeScript,不过作为日常用C#写后端的人,又处处是熟悉的感觉~
反正比JS好用一万倍就是了,类型提示真是太棒了
目前用得不深,后续有什么相关的我再写写博客记录一下。
参考资料
- 探索 TypeScript 类型注解 - 自定义类型:https://github.com/WowBar/blog/issues/9
Taro框架使用感受
框架是个好框架,不过文档方面感觉还不是很完善,有些地方写得不是很清楚,感觉很多文档都是复制了微信小程序的文档来的,对于没开发过微信小程序且没读过微信官方文档的人来说,不是很友好。(不过官方文档还是要看,不看的话遇到很多问题都查不到的)
然后Taro官方提供了一个UI库,叫 TaroUI,用的话还是能用的,就是更新太慢了,它的github项目主页 显示上次更新时间还是去年(2021年)6月份,到现在近一年时间没动过了。最新稳定版本还在2.x,而Taro框架已经更新到3版本了。
因为我用的Taro框架是3.x版本,所以只能硬着头皮上TaroUI 3的beta版本,导致遇到了一些奇奇怪怪的问题,头大。
除了TaroUI这个界面库,Taro官方还提供另一个叫 NutUI 的库,不过是基于Vue的,我这个项目没法用,这个库就更新挺勤快的,github上最近更新还是6小时前,Star也有4.2k,比TaroUI的3.9k多。~~(看来React在京东不受待见呀)~。
我还看到有一个叫 Taroify 的UI库,看起来好像不错,更新也很勤快,不过GitHub Stars只有300多,不敢用~ 下次来试试看
用的同时我还参考了这些项目/代码/文档:
- https://github.com/NervJS/taro-v2ex/blob/react/src/pages/thread_detail/thread_detail.tsx
- https://github.com/wuba/Taro-Mortgage-Calculator
- https://github.com/NervJS/awesome-taro
接下来进入正题,总体说说遇到的一些问题/坑,以及解决方案。
页面路由问题
Taro封装了路由相关的方法,我是做完了项目有时间去翻一下 微信小程序文档 才发现这玩意跟小程序的路由特别像。
PS:我讨厌这种路由设计,不知道小程序这样是哪个人才想出来的,页面多了的话不太好维护啊~
在 app.config.ts
文件里把路由配置好,类似这样:
export default defineAppConfig({
pages: [
'pages/index/index',
'pages/info/place',
'pages/supply/index',
'pages/user/login',
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
},
})
然后要跳转的地方就用 Taro.navigateTo({url: 'pages/user/login'})
就行了
这里有个很坑的地方!Taro的热更新不完善,添加了新页面后热更新是不生效的,必须 yarn dev:h5
重启才能看到效果,一开始我被坑得嗷嗷叫~
地址参数问题
这个问题在我之前的博客:Django + Taro 前后端分离项目实现企业微信登录 有提到,Taro本身提供了 useRouter()
来给我们读取地址里的参数
比如上面那个路由跳转的地方我们加上了参数: Taro.navigateTo({url: 'pages/user/login?title=hello'})
那我们在 pages/user/login
页面里要获取参数就是这样
import {useEffect} from "react"
import {useRouter} from "@tarojs/taro"
export default function () {
const router = useRouter()
useEffect(() => {
console.log(router.params.title)
}, [])
}
但当在读取微信登录服务器回调参数的时候,就不行,就取不出来,得自己拿完整链接 window.location.href
去匹配。详见我这篇博客:Django + Taro 前后端分离项目实现企业微信登录
Taro.relaunch不会清除URL
这看起来不是什么大问题,不过也导致了一个小bug,就是我在使用微信登录后,注销登录的时候不会清除地址里的code,这样没关闭页面的情况下,再次使用微信登录,那个code还是旧的,就直接报错了~
TaroUI form的bug
说实话我不知道这是哪里的问题
只有一个页面出现了这个问题,在最后一个输入框按回车,表现是form提交,但其实也没提交,并且页面变成重新刷新了
百思不得其解
我只好在最后面再加了一个隐藏的input
<AtInput
name='hide'
onChange={() => {
}}
disabled={true}
border={false}
style={{display: 'none'}}/>
网络请求封装
Taro框架自带了 Taro.request
可以用来请求,不过我用的时候很奇怪一直提示跨域,因为前期时间很赶,我就没去深入,直接换成我之前vue项目封装好的axios,果然还是axios好用~
(不过之后做成小程序的话,应该还是得重构一下,据说小程序不支持formdata)
封装useState
感谢「前端带师 coppy」提供的代码~
import {useState} from 'react'
export default function useYourState<T extends {}>(state: T): [T, (state: Partial<T>) => void] {
const [_state, _setState] = useState(state);
return [
_state,
(state: Partial<T>) => {
_setState((_state) => {
return {
..._state,
...state
};
});
}
];
}
这样就不需要每次setState都需要加...state
了
使用前:
import {useState} from 'react'
export const LoginPage = observer(() => {
const [state, setState] = useState({
username: '',
password: '',
})
setState({
...state,
username: '', password: ''
})
}
使用后:
import useYourState from "@/utils/coppy_state";
export const LoginPage = observer(() => {
const [state, setState] = useYourState({
username: '',
password: '',
})
setState({
username: '', password: ''
})
}
生产力获得了提高~
全局状态管理
没去用大名鼎鼎的redux,转而使用比较简单的mobx
但是找到的例子文档都不太行(举例,官方中文文档:https://cn.mobx.js.org/)
最终还是寻求「前端带师」的帮助,搞定了
坑点:
- store现在没法用装饰器了,用这个
makeAutoObservable
- 不需要全局provider
- Taro官网和例子可以说是史上最坑,千万别被骗了,地址:https://taro-docs.jd.com/taro/docs/mobx/
- 请用最新版的mobx和
mobx-react-lite
,别用Taro官网那个4.8版本,太老了没用
代码
不需要全局provider包装了,直接用全局变量,当然也可以用React Context
store定义
import {makeAutoObservable} from "mobx";
import {User} from "@/models/user";
import * as auth from '@/utils/auth'
export class UserStore {
isLogin = false
user: User | null = null
token = ''
constructor() {
makeAutoObservable(this)
}
login(user: User, token: string) {
this.user = user
this.token = token
this.isLogin = true
// 保存登录数据到本地
auth.login(token, user.username)
}
logout() {
this.isLogin = false
this.user = null
this.token = ''
auth.logout()
}
}
export const myUserStore = new UserStore()
组件使用
import {View} from "@tarojs/components"
import {AtButton} from "taro-ui";
import {observer} from "mobx-react-lite";
import {myUserStore} from "@/store/user";
import Taro from "@tarojs/taro";
import {useEffect} from "react";
export const UserPage = observer(() => {
useEffect(() => {
if (!myUserStore.isLogin) {
Taro.redirectTo({url: '/pages/user/login'})
}
}, [])
return (
<View className='py-3 px-2'>
<View className='at-article__h1'>用户中心</View>
<View className='at-article__h3 mt-1'>用户名:{myUserStore.user?.first_name}</View>
<AtButton className='mt-3' onClick={logout}>退出登录</AtButton>
</View>
)
function logout() {
myUserStore.logout()
Taro.reLaunch({url: '/pages/index/index'})
}
})
export default UserPage
参考资料
- 官网文档:https://mobx.js.org/react-integration.html
- 项目地址:https://github.com/mobxjs/mobx/tree/main/packages/mobx-react
- Mobx React 初学者入门指南(掘金):https://juejin.cn/post/6844903831726211079
- mobx 在 react 中的 类组件、函数组件、配合 hooks 的使用:https://juejin.cn/post/6873794258743066632#heading-2
JSON反序列化class
使用这个库:https://github.com/typestack/class-transformer
model定义,这个定义可以用JSON来生成,有很多在线工具,比如:https://apihelper.jccore.cn/jsontool
export class User {
username: string
first_name: string
last_name: string
email: string
date_joined: string
}
注意项目主页上的文档也是过期了的,plainToClass
方法已过期,得用这个方法:plainToInstance
import {plainToInstance} from "class-transformer";
const user = plainToInstance(User, res.data.user)
myUserStore.login(user, res.data.token)
React + TypeScript + Taro前端开发小结的更多相关文章
- 实例讲解基于 React+Redux 的前端开发流程
原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s ...
- TypeScript作为前端开发你必须学习的技能(一)
2019年,TypeScript已经开始渐渐的崭露头角,各大框架都说要使用TypeScript,虽然现在还没有完美,但是TypeScript很有可能会成为下一个主流技术. 废话就不多说了,直接开始吧. ...
- web前端开发小结
1.浏览器内核 IE-----Trident Edge-----EdgeHTML Firefox-----Gecko Safari-----Webkit Chrome-----Blink(Webkit ...
- TypeScript作为前端开发你必须学习的技能(三)
TypeScript 运算符 TypeScript 主要包含以下几种运算: 算术运算符 逻辑运算符 关系运算符 按位运算符 赋值运算符 三元/条件运算符 字符串运算符 类型运算符 实例看图: 关系运算 ...
- TypeScript作为前端开发你必须学习的技能二)
TypeScript 变量声明 变量是一种使用方便的占位符,用于引用计算机内存地址.我们可以把变量看做存储数据的容器. TypeScript 变量的命名规则:和javascript一样.除了下划线 _ ...
- 移动web前端开发小结
注意:Chrome模拟手机的显示的界面是有误差的,强烈建议一定要在真机测试自己的移动端页面(以移动端页面为准). 1.页面高度渲染错误,页面的高度是否包含了导航,(华为手机就是偏偏有底部菜单) 设置窗 ...
- 自学前端开发,现在手握大厂offer,我的故事还在继续
简要背景 我是一个非科班出身的程序员,而且是连续跨专业者,用一句话总结就是:16 届本科学完物流,保送研究生转交通,自学前端开发的休学创业者. 17 年休学创业,正式开始学习前端,离开创业公司后,我又 ...
- 前端开发个人小结 · Retrospection的博客
序 2018年转眼来到了最后一个月,算下来我进入前端之门也有一年了,虽然下半年由于忙于筹备毕业论文的相关事项,前端这一块有所放下,但是想想还是给自己这一年的学习做一个总结. 现代化软件开发确实是一个复 ...
- JS前端开发判断是否是手机端并跳转操作(小结)
JS前端开发判断是否是手机端并跳转操作(小结) 这篇文章主要介绍了JS前端开发判断是否是手机端并跳转操作,非常不错,具有参考借鉴价值,需要的朋友可以参考下 常用跳转代码 ? 1 2 3 4 5 6 7 ...
随机推荐
- xilinx SDK在线仿真_烧写 提示失败
1.找到工程目录下的Binaries->xxx.elf-[arm/le] . 2.右击该elf,选择Debug As->Debug Configurations... 进入设置界面. 3. ...
- 内置方法 __str__ __repr__
内置方法(双下方法,魔术方法) 在不需要程序员定义,本身就存在的类中的方法就是内置方法 内置方法: __名字__ __init__ 不需要我们主动调用,而是在实例化的时候内部自动调用的,存在一种 ...
- DDOS反射攻击
0x01 环境 包含3台主机 attact 作为攻击方,使用Centos7.2 reflect 作为流量放大器,安装有dns .ntp .memcached三种可以放大流量的服务 windows_se ...
- SQL注入手册
英文版:链接: https://sqlwiki.netspi.com/ 中文版:链接: https://pan.baidu.com/s/1WWmjvYYnLC6_nItMVvUVig 密码: e98r ...
- Golang 包了解以及程序的执行
Golang 包了解以及程序的执行 引言 Go 语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案.Go 语言中为我们提供了很多内置包,如 fmt.o ...
- jinja2.exceptions.TemplateNotFound 报错处理
一.检查模板文件夹是否正确. 遇到这个问题,首先需要检查你的模板文件夹命名是否规范,Flask默认会在工程下寻找templates文件夹,这个是默认配置,不能写成template或者其他名字.当然,如 ...
- 如何使用 Spring Boot 实现异常处理?
Spring 提供了一种使用 ControllerAdvice 处理异常的非常有用的方法. 我们通过实现一个 ControlerAdvice 类,来处理控制器类抛出的所有异常.
- 面试问题之C++语言:简述编译过程
转载于:https://blog.csdn.net/ypshowm/article/details/89374706 编译过程主要分为四步: 1.词法分析(扫描) 运行类似于有限状态机的算法将源代码的 ...
- 发现程序美----while+for冒泡实现的
思想记录: 每一轮回的冒泡都将产生一个最大值,其后每次循环次数都将少一次,因为每次都会确定一个最大值. private void method(){ int[] list = {10,7,8,4,7, ...
- AQS分析笔记
1 介绍 AQS: AbstractQueuedSynchronizer,即队列同步器.是构建锁或者其他同步组件的基础框架.它维护了一个volatile int state(代表共享资源)和一个FIF ...