React Hooks和React Hot Loader默认配置相冲突
设置RHL的pureSFC
配置为true,详见讨论。
1
| setConfig({ pureSFC: true })
|
一个简单的rollup配置样例
最近有一个开发前端录音库(严格来说是改进)的需求,目标是发布到npm管理平台上,在打包库上rollup的发挥要优于webpack。刚好想用用试试,就用了rollup作为打包工具。因为场景比webpack更简单,配置上也比webpack好配很多,基本看看官方文档就可以上手了。
不过,文档里用的babel版本还是6.x,使用新版本babel后,配置文件rollup.config.js
和.babelrc
有些改动,这里列在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; import babel from 'rollup-plugin-babel'; import { terser } from "rollup-plugin-terser";
export default { input: 'src/index.js', output: { file: 'index.js', format: 'es' }, plugins: [ resolve(), commonjs(), babel({ exclude: 'node_modules/**' }), terser() ] };
{ presets: [ [ '@babel/env', { loose: true, modules: false } ] ], plugins: [ ['@babel/proposal-object-rest-spread', { loose: true }] ] }
|
mouseout
和mouseleave
事件的区别
mouseout: https://developer.mozilla.org/en-US/docs/Web/Events/mouseout
mouseleave: https://developer.mozilla.org/en-US/docs/Web/Events/mouseleave
mouseout
在鼠标离开该元素表面时触发,包括进入到该元素的子元素中
mouseleave
在鼠标离开该元素区域时触发,即离开该元素和所有子元素区域
sublime goto definition 快捷键
参考这里
只lint changed file的脚本方案
利用git diff-index
。下面以tslint为例。
1 2 3 4
| files=$(git diff-index --relative --name-only --cached HEAD | grep -e '\\.ts$' -e '\\.tsx$'); if test -n \"$files\"; then echo $files | xargs tslint --fix -t codeFrame; fi
|
升级版
使用lint-staged,只lint staged的文件内容,代替上面冗长的脚本。
吸顶样式效果
CSS
参考:MDN
最简洁的实现方式,缺点是支持度较差,只在iOS平台支持度较好。除非做中后台,否则需要谨慎使用。
1 2 3 4
| .stick { position: sticky; top: 20px; }
|
JS
不用赘述,检查滚动元素的scrollTop
属性做判断即可,在指定位置上,设置position:fixed
配合z-index
等实现吸顶。
另外有意思的一点是,在position:fixed
的情况下,如果没有设置left
,left
将相对当前元素相对定位。
一个更友好的图片加载组件
需求
提供类似知乎App内的体验:
- 在图片加载时有相同大小的占位图和文案提示
- 图片加载失败后有相同大小的占位图和文案提示,点击文案可以重新加载图片
思路
重点在需要图片大小相同的占位图,这通常意味着:
- 图片的大小需要伴随图片下发
- 客户端的图片宽度或高度固定(通常是宽度)
点击重新加载可以通过在图片url后拼接每次不一样的参数实现,例如时间戳。
遮罩可以用图片背景色 + :after
伪元素或另外的元素实现。剩下的把loading、loaded、failed状态处理好,工作并不困难。
下面是粗略实现的一个demo。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
import React, { Component } from 'react';
import './index.less';
interface IProps { width: number; height: number; src: string; onLoad?: () => void; onError?: () => void; }
interface IState { src: string; loaded: boolean; failed: boolean; }
class SmartImage extends Component<IProps, IState> { public readonly state: IState = { src: this.props.src, loaded: false, failed: false };
public render() { const { width, height } = this.props; const { src, loaded, failed } = this.state;
return ( <div className="smart-image-container"> <img className="smart-image" width={750} height={750 * height / width} src={src} onLoad={this.handleSuccess} onError={this.handleError} /> {!loaded ? ( <div className="smart-image-hint" onClick={this.handleRetry}> {failed ? <span>图片加载失败,点此重试</span> : <span>图片加载中...</span> } </div> ) : null } </div> ); }
private handleSuccess = () => { this.setState({ failed: false, loaded: true }); if (this.props.onLoad) { this.props.onLoad(); } }
private handleError = () => { this.setState({ failed: true }); if (this.props.onError) { this.props.onError(); } }
private handleRetry = () => { if (!this.props.src.startsWith('http') || !this.state.failed) { return; } this.setState({ failed: false, src: `${this.props.src}?ts=${Date.now()}` }); } }
export default SmartImage;
|