决定一个人命运的不是能力而是选择
1.加快安装
npm config set registry registry.npm.taobao.org
2.写代码过程中webstorm底部一直闪烁,代码也提示不了
File->Invalidate Cahes/Restart -> Invalidate and Restart
3.按钮未点击自动执行点击事件
handlerClick = (questionId)=>{
console.log('我执行了')
}
<button type="button"
onClick={
this.handlerClick(question_id)
}>补习详情
</button>
handlerClick (questionId){
console.log('我被点击了')
}
<button type="button"
onClick={
this.handlerClick.bind(this,question_id)
}>补习详情
</button>
第一种和第二种是两种常见的函数定义方法,第一种是箭头函数,第二种是普通函数。推荐用箭头函数
- 避免普通函数this造成的一系列问题,而箭头函数this指向函数定义的组件
- 每次刷新组件都会重新执行bind方法,对性能有影响
但是第一种箭头函数确带来了奇怪的问题:按钮未点击handlerClick函数自动执行了,而不传参数的话是不会自动执行的,这是为什么?明明看起来两种写法差不多!在讲这个问题之前我们首先来看一下匿名函数
function (){
console.log('我执行了')
}
忽略箭头函数的内部细节,我们发现其实箭头函数就是匿名函数。再来看看匿名函数是如何执行的
(function (){
console.log('我执行了')
})()
聪明的你应该发现问题了,第一种箭头函数传参就相当于匿名函数立即执行。讲清楚了为什么会立即执行,看下如何解决
<button type="button"
onClick={()=>{
this.handlerClick(question_id)
}
}>补习详情
</button>
这有什么区别?第一种箭头函数的写法等价于
onClick=(function(){
console.log('我执行了')
})(questionId)
第二种等价于
onClick=function(){
return function handlerClick(questionId){
console.log('我执行了')
}
}
那么bind为什么不会立即执行?因为bind返回的还是函数
4.ant Design Select组件的坑
<Select defaultValue={0} onChange={this.handleClasses} className="selectClasses">
{
allClass.map((value, index) =>
<Select.Option value={index}>{value.class_name}</Select.Option>
)
}
</Select>
开始allClass是空数组,等到网络请求返回allClass才有数据,然后组件会刷新。这时候很奇怪defaultValue没有刷新,莫名其妙的设置不了默认数据。会出现下图所示的情况
下面的写法可以避免这种情况
{
allClass.length !== 0 ?
<Select defaultValue={0} onChange={this.handleClasses} className="selectClasses">
{
allClass.map((value, index) =>
<Select.Option value={index}>{value.class_name}</Select.Option>
)
}
</Select> : <div/>
}
这种写法更优雅
{
allClass.length !== 0 &&
<Select defaultValue={0} onChange={this.handleClasses} className="selectClasses">
{
allClass.map((value, index) =>
<Select.Option value={index}>{value.class_name}</Select.Option>
)
}
</Select>
}
5.react.setState()之后不能获取更新后的数据
下面获取到的count还是-1
this.state={
count = -1
};
this.setState({ count: 0 });
console.log(this.state.count);
实际上setState并不会立马执行,它会把状态存到队列中,稍后才会更新state的值,下面的写法可以避免这种情况
this.setState({ count: 0 },
() => console.log(this.state.count))
6.自己搞的简易的react Componet
export default class Component {
constructor(props = {}) {
this.props = props;
}
setState(state) {
const oldEl = this.el;
this.state = state;
this._renderDOM();
if (this.onStateChange) this.onStateChange(oldEl, this.el);
}
_renderDOM() {
this.el = this._createDOMFromString(this.render());
if (this.onClick) {
this.el.addEventListener('click', this.onClick.bind(this), false)
}
;
return this.el;
}
_createDOMFromString = (domString) => {
const div = document.createElement('div');
div.innerHTML = domString;
return div;
}
mount = (component, wrapper) => {
wrapper.appendChild(component._renderDOM());
component.onStateChange = (oldEl, newEl) => {
wrapper.insertBefore(newEl, oldEl);
wrapper.removeChild(oldEl);
}
}
onStateChange(oldEl, newEl) {}
render() {}
onClick() {}
}
7.react-router-dom使用
函数方式跳转传参this.props.history.push({
pathname: '/detail',
state: {
id: 3
}
)
防止重复跳转死循环
this.props.history.replace('/detail');
goBack返回
this.props.history.goBack();
8.redux使用,redux用于数据共享
index.js注册
import counter from './reducers/index';
import {createStore} from 'redux';
const store = createStore(counter);
const render = () =>
ReactDOM.render(<App
value={store.getState()}
onIncrement={() => store.dispatch({type: 'INCREMENT'})}//action
onDecrement={() => store.dispatch({type: 'DECREMENT'})}
/>, document.getElementById('root'));
render();
store.subscribe(render);
creare函数
export default (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state
}
}
组件
const {value, onIncrement, onDecrement} = this.props;
<p>{value}次数拉拉拉</p>
<button onClick={onIncrement}>加上</button>
<button onClick={onDecrement}>减去</button>
9.js精度问题
0.07.toFixed()*100 = 7.00000000000000001%
(0.07*100).toFixed() = 7%
好用的js方法
1.正确返回字符串长度function length(str) {
return [...str].length;
}
或者
function countSymbols(string) {
return Array.from(string).length;
}
2.判断一个字符是单字节还是双字节
function is32(c){
return c.codePointAt(0) > 0xFFFFFF;
};
3.正则判断金额是否正确
let s = "1512.1";
let patter = /^\d+\.?\d{1,2}$/g.test(s);
4.将数组中布尔值为false的成员转为0
Array.from([1, , 2, , 3], (n) => n || 0)
5.数组去重
[...new Set([1,2,3,4,5,2])]
6.去除重复字符串
[...new Set('ababbc')].join('')