可以解析html的js库---htmlparser😋😋😋
const fs = require('fs');
const { Parser, DefaultHandler } = require('htmlparser');
let rawHtml = fs.readFileSync('./index.html', 'utf-8');
let handler = new DefaultHandler((err, dom) => {
if (err) {
console.log(err);
} else {
console.log(dom, 'start');
dom.forEach(item => {
console.log('evevryDom', item);
})
console.info(JSON.stringify(dom, null, 2));
}
})
let parser = new Parser(handler);
parser.parseComplete(rawHtml)
chrome devtools基础😋😋😋
- 鼠标在Element中选中dom,回到Console中输入$0,获取该dom
- $_访问最近一次输出
- copy(something)复制控制台的内容, 到编辑器中直接粘贴
- keys({a:1, b:2})时输出['a','b'];values({a:1, b:2})时输出[1,2];
- 计算代码执行时间: console.time('aaa');const aaa= 1;console.timeEnd('aaa');
- 清空控制台clear();
dva基础😋😋😋
import React from 'react';
import { Dispatch } from 'redux';
import dva, { connect, RouterAPI } from 'dva';
import { Router, Route } from 'react-router';
import { Link } from 'react-router-dom';
interface Counter1State {
number: number;
}
type Counter1Props = Counter1State & {
number: number;
dispatch: Dispatch<any>;
}
interface Counter2State {
number: number;
}
type Counter2Props = Counter2State & {
number: number;
dispatch: Dispatch<any>;
}
type CombineState = {
counter1: Counter1State,
counter2: Counter2State,
}
let app = dva();
const delay = (ms: number) => new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms)
})
app.model({
namespace: 'counter1',
state: { number: 0 },
reducers: {
increment(state) {
return {
number: state.number + 1
}
},
decrement(state) {
return {
number: state.number - 1
}
}
},
effects: {
*asyncIncrement(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'increment' });
}
},
subscriptions: {
changeTitle({ history, dispatch }) {
history.listen(({ pathname }) => {
document.title = pathname;
})
}
}
});
app.model({
namespace: 'counter2',
state: { number: 0 },
reducers: {
increment(state) {
return {
number: state.number + 1
}
},
decrement(state) {
return {
number: state.number - 1
}
}
}
})
const Counter1 = (props: Counter1Props) => (
<div>
<p>{props.number}</p>
<button onClick={() => props.dispatch({ type: 'counter1/increment' })}>+</button>
<button onClick={() => props.dispatch({ type: 'counter1/asyncIncrement' })}>asyncIncrement</button>
<button onClick={() => props.dispatch({ type: 'counter1/decrement' })}>-</button>
</div>
)
const mapStateToProps1 = (state: CombineState): Counter1State => state.counter1;
const ConnectedCounter1 = connect(mapStateToProps1)(Counter1);
const Counter2 = (props: Counter2Props) => (
<div>
<p>{props.number}</p>
<button onClick={() => props.dispatch({ type: 'counter2/increment' })}>+</button>
<button onClick={() => props.dispatch({ type: 'counter2/decrement' })}>-</button>
</div>
)
const mapStateToProps2 = (state: CombineState): Counter2State => state.counter2;
const ConnectedCounter2 = connect(mapStateToProps2)(Counter2);
app.router((api?: RouterAPI) => {
let { history, app } = api!;
return (
<Router history={history}>
<>
<Link to="/counter1">counter1</Link>
<Link to="/counter2">counter2</Link>
<Route path="/counter1" component={ConnectedCounter1}></Route>
<Route path="/counter2" component={ConnectedCounter2}></Route>
</>
</Router>
)
});
app.start('#root');
roadhog基础😋😋😋
基于webpack的封装工具
打包,开发,测试
"scripts": {
"dev": "roadhog server",
"build": "roadhog build",
"test": "jest"
}
##### 配置文件.roadhogrc
```json
{
"entry": "src/index.js",
"disableCSSModules": false,
"publicPath": "/",
"outputPath": "./dist",
"extraBabelPlugins": [],
"extraPostCSSPlugins": [],
"autoprefixer": null,
"proxy": null,
"externals": null,
"library": null,
"libraryTarget": "var",
"multipage": false,
"define": null,
"env": null,
"theme": null
}
mock文件.roadhogrc.mock.js
以下接口均可以通过postman直接访问http://localhost:端口/路径
export default {
'GET /api/users': { users: [1,2] },
'GET /api/users/1': { id: 1 },
'POST /api/users/create': (req, res) => { res.end('OK'); },
};