h5全员营销项目总结

h5全员营销项目总结

七月 20, 2020

项目概况

公司有个小程序项目是全员营销小程序,这次的需求是做个H5版本的。基本是把现有的部分功能给搬过来。所以这次需求的特点是:工作量大、从头开发React项目、全面。能很全面的考验我的能力,并发现我的不足。

然后记下一些坑、一些好的和一些不足的地方。以便以后再次遇到。

正文

html语义化

以前开发基本上都是全套div过去,顶多用个section,因为div布局最方便,用其他反而还得写覆盖样式。然后跳转都是清一色用js的history.push来跳转。而这次一起开发的小哥,不仅html严格按照语义化编写,甚至路由跳转都大量用<Link /><NavLink />来实现。虽然实现麻烦,但是后来我觉得,这么做还是很有道理的。
大量使用语义化标签可以让浏览器更好的识别页面的功能大概是什么,不然页面清一色的div。确实让浏览器很为难。

所以,以后有跳转的地方都应该用<Link />实现,即使需要拦截按需跳转,也应该:

1
2
3
4
5
6
7
8
<Link to="/index" onClick={this.handleClick} />

handleClick = (e) => {
e.preventDefault();
if(condition) {
this.props.history.push(e.currentTarget.pathname)
}
}

React中Keep-Alive的原理

未实现。

react动画

未实现。

popupFactory

就是实现不了,实现成功了再写入gist

权限控制这块应该提前提前捋清楚

本次开发是要同时支持微信授权、企业微信授权和非微信环境下手机登陆。而且还有权限系统控制不同模块。所以其实这部分是很复杂的。这次做得不好的是,并没有统一的梳理这部分的功能,然后系统的画出流程图,才进行开发。

css modules in React

隔了很久才写。具体的坑记不太清了。

自定义Error

因为Error对象是个比较特殊的对象,如需自定义一个有Error对象效果的对象,唯一的办法是创造一个类然后继承Error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyError extends Error {
constructor(msg, customMessage, customCode) {
super(msg);
this.myMessage = customMessage;
this.myCode = customCode;
}
}


// 触发
throw new MyError('msg', 'myMessage', 502);


// 接收到的error
catch(e) {
console.log(e.message);
console.log(e.myMessage);
console.log(e.myCode);
}

关于better-scroll2的坑

小程序很多页面都用上了下拉刷新,而且以一起的经验,为了避免其他坑。这期决定加上better-scroll自定义组件。并且发现最新版better-scroll2已经出来,开开心心决定使用它。但是后来开发过程中,遇到了许多坑🕳

组件内的fix、sticky将会失效。

因为better-scroll用的是transform来实现的滚动效果。是以最终布局,再进行位移操作。所以,即使元素fixed、sticky到了应该的位置,但是也会transform位移一次。最终的效果和relative一样。所以结论是,不能再滚动内容里使用fixed和sticky定位。

fixed应该用creatPortal来把元素移动到滚动组件之外。但是sticky。。就有点麻烦了。

pullingUp插件有问题。

我开发时,使用的是2.0.0-beta.10版本的pull-up插件。遇到的问题是,组件滚动到底部后,就会取消监听,导致只能触发一次触底事件。。。。。这,,,,完全没法用。。。只能自己用onScroll来实现自定义的触底事件。

better-scroll用的touchStart来实现的onClick

具体内部没看源码。反正这个问题会造成,用户无法在input标签内长按粘贴。input在betterscroll里的情况下,input聚焦时,再长按粘贴时,手指一触碰到input标签就触发了失焦,所以跟没没法长按触发粘贴。。太坑了。

最后,有表单的页面,改用原生滚动。

React input标签中的onChange与onInput

Tab与TabsPane的实现

项目中也用到了Tab组件,所以参照了antd的写法,把

路由配置

React开发,数据应该始终放在父组件

也有点忘了。好像踩了个坑,比如一个页面有3个列表,三个列表交互不相同,每个列表都有分页逻辑。正常情况下,得把三个不相同的列表分成三个组件(jsx)但是获取数据方面,还得在父组件去统一处理,父组件把数据传给子组件,子组件只负责渲染。
如果把三分数据交给三个组件内部处理,则会造成一些奇怪的逻辑问题。

非组件文件触发react-router-dom的无刷新跳转

react组件可以通过this.props.$router或者react-router-dom中的useHistory拿到。但非组件js想要利用react-router的无刷新跳转,则得利用一下history库

1
2
3
4
5
6
7
8
9
//history.js
import { createBrowserHistory } from 'history';

const history = createBrowserHistory();

export push = history.push
export replace = history.replace

export default history;

然后在把react-router-dom注入react的地方,给Router对象传入history库createBrowserHistory创建的实例对象

1
2
3
4
5
6
7
8
9
import { Router } from 'react-router-dom';
import history from './history.js'

ReactDOM.render(
<Router history={history}>
<App />
</Router>,
document.getElementById('container')
);

然后在项目任何地方都可以用history.js暴露出来的history实例对象操作React-router.

原理其实是,React-router也是基于history库来实现的。在组件传入history实例对象,是让react-router利用我们定义的history来实现。这样也就是变相的暴露了react-router的操作路由的history对象。也就可以在任何地方调用了

其他

by the way。虽然Taro号称同时支持多端。但是事实证明,一套Taro代码编译成多端平台是不可能实现的事。。。仅仅把Taro当作一个可以用React编写小程序的框架即可。。