1.脚手架
npm install -g create-react-app
使用方法:create-react-app XXX(项目名称),会自动init并install好项目,直接npm start就好了。
react-scripts 是什么?
react-scripts
是create-react-app
生成项目所有的依赖。
通常情况下,我们创建spa
应用时是使用npm
安装项目依赖,在通过配置webpack.config.js
进行配置,搭建好环境后在src
编写源代码。而create-react-app
是自动构建,在package.json
中只有react-scripts
作为依赖,而在reacr-scripts
中已经配置好了项目所有需要的。另外,关于webpack.config.js,需要使用eject命令导出。
引用:https://blog.csdn.net/qq_22889599/article/details/79507721
EnterData(event){ const {textBox} = this.state; if(event.keyCode==13){ this.setState( {textBox:textBox.concat(event.target.value)} ); } }
3.setState与States
this.state={ textBox:[] }
this.setState( {textBox:textBox.concat(event.target.value)} );
但是使用的时候,依然需要:
const {textBox} = this.state;
先取下来再进行数据操作。
4.CSS元素使用
let diagramContainer={ padding: '20px', window.innerWidth, height: window.innerHeight, border: '1px solid gray' };
<div className="Dotcon" style={diagramContainer}>
<div id={pid} style={{position:'absolute',height:'80px','80px',border:'1px solid blue',color:'blue',float:'left',left:pleft,top:ptop}}>{pid}</div>
var name1 ="Mike"; var age1=20; var message1=`hello,${name1},your age is ${age1}`;
6.JS数组CRUD
追加:
textBox.concat(event.target.value)
删除:
var index; const {textBox} = this.state; for(var i=0;i<textBox.length;i++){ if(textBox[i]==value){ index = i; break; } } textBox.splice(index,1);
7.弹框操作(person就是输入的值)
var person=prompt("请输入你的名字","Harry Potter");
8.父子组件传值与回调
首先要将接收方法在父组件传入子组件,子组件的click(或其他事件)事件里再次调用父组件的方法(这个方法已经传入,所以可以从props里拿到,从而回调)。
onChildDelete(value) { //这里拿到的value靠子组件传回 }
return ( <div className="InputComponent"> <AddText onChildDelete={this.onChildDelete.bind(this)} /> </div> ); //注意这里必须.bind(this),否则在onChildDelete方法不可用this.props
onChildDelete(){ this.props.onChildDelete(this.props.Text) } render() { return ( <div className="AddText"> <li>{this.props.Text}<a onClick={this.onChildDelete.bind(this)}></a></li> </div> ); //子组件调用父组件传进来的方法,进行回调,并传回一个值。
引用:https://www.cnblogs.com/lixuemin/p/5754289.html
9.数组Map与事件响应
const BlackComponent = () => <div>我是黑色组件</div>;
class App extends React.Component {
constructor(props) {
super(props);
this.state = { comps: [] };
}
render() {
const { comps } = this.state;
return (
<div>
{comps.map(comp => {
return <BlackComponent key={comp} />;
})}
<p>---------------</p>
<button onClick={() => this.setState({ comps: comps.concat([Date.now()]) })}>加组件</button>
</div>
);
}
}
//当然,map还可以传入index值
10.取Input的值
import React , {Component} from 'react'; export default class App extends Component{ search(){ const inpVal = this.input.value; console.log(inpVal); } render(){ return( <div> <input type="text" ref={input => this.input = input} defaultValue="Hello"/> <button onClick={this.search.bind(this)}></button> </div> ) } }
https://blog.csdn.net/Shuiercc/article/details/81383679
10.安装淘宝镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
11.react-router的使用
import {BrowserRouter,Route,Switch} from 'react-router-dom' <BrowserRouter> <Switch> <Route exact path='/' render={() => <FirstPage/>} /> <Route path='/RabbitMessageQueue' component={InputComponent}/> <Route path='/TodoList' component={TodoList}/> </Switch> </BrowserRouter> //需要先注册路由,带exact默认为第一个页面且必须。 在其他组件中: import {Link} from 'react-router-dom';
<ul> <li style={{color:color}}><Link style={{color:color}} to='/'>Home</Link></li> <li style={{color:color}}><Link style={{color:color}} to='/RabbitMessageQueue'>RabbitMessageQueue</Link></li> <li style={{color:color}}><Link style={{color:color}} to='/TodoList'>TodoList</Link></li> </ul>
12.redux的使用
在主页面中,注册store,并配置到全局。
import { createStore} from 'redux' import { Provider } from 'react-redux' const store = createStore(dataHandler); function createStore { switch (action.type) { case 'CHANGE_THEME': return { themeColor: action.color }; default: return state; } } render() { return ( <Provider store={store}> <BrowserRouter> ... </BrowserRouter> </Provider> ); } //需要把最外层组件囊括进provider,这样数据才能在所有组件可用。
在子组件中(MenuList):
import { connect } from 'react-redux'; function mapStateToProps(state) { return { themeColor: state.themeColor } } function mapDispatchToProps(dispatch) { return { setThemeColor: (type,value) => dispatch({ type: type, color: value }), } } export default connect( mapStateToProps, mapDispatchToProps )(MenuList) //mapStateToProps让redux的state同步到react的props中,而mapDispatchToProps同理,将dispatch方法同步到了props中。
然后,你就可以在组件中使用:
const { setThemeColor} = this.props; const color = this.props.themeColor; <button onClick={()=>{setThemeColor('CHANGE_THEME','#3399FF')}}>Normal</button> <li style={{color:color}}><Link style={{color:color}} to='/'>Home</Link></li>
在另外的组件中共享数据也需要这么做。
function mapStateToProps(state) { return { themeColor: state.themeColor } } export default connect(mapStateToProps)(Header) //然后你就可以同步所有组件中的themeColor的变化了,而props数据的改变同样会让render重新绘制。
可以看到,使用redux可以做到跨组件数据同步,而不需要将数据先一步步传递给父组件,再传递给另一个子组件。如果加上@解释器,会更加优雅。
class AutoFocusTextInput extends React.Component { componentDidMount() { this.textInput.focusTextInput(); } render() { return ( <CustomTextInput ref={(input) => { this.textInput = input; }} /> ); } }
14.更改启动端口(VSCode)
{ "scripts": { "start": "set PORT=9000 && roadhog server",//加入set PORT=9000 && }, }
15.react.dva的使用
典型的一个dva应用。
import dva from 'dva'; import React from 'react'; import dva, { connect } from 'dva'; import './style.css'; // 1. Initialize const app = dva(); // 2. Model app.model({ namespace: 'count', state: 0, reducers: { add (count) { return count + 1 }, minus(count) { return count - 1 }, }, }); class TestError extends React.Component { componentDidCatch(e) { alert(e.message); } componentDidMount() { // throw new Error('a'); } render() { return <div>TestError</div> } } // 3. View const App = connect(({ count }) => ({ count }))(function(props) { return ( <div> <TestError /> <h2>{ props.count }</h2> <button key="add" onClick={() => { props.dispatch({type: 'count/add'})}}>+</button> <button key="minus" onClick={() => { props.dispatch({type: 'count/minus'})}}>-</button> </div> ); }); // 4. Router app.router(() => <App />); // 5. Start app.start('#root');
一共需要五步就能搭建一个囊括react、react-router、react-redux的应用。
① const app = dva();
可以往里传入各种初始化数据,hook之类的,比如:
initialState: { products: [ { name: 'dva', id: 1 }, { name: 'antd', id: 2 }, ], },
② app.model();
接收一个json数组,当中三个值:
const modelsCombine=[ { namespace: 'count', state: 0, reducers: { add (count) { return count + 1 }, minus(count) { return count - 1 }, }, }, { namespace: 'products', state: [], reducers: { 'delete'(state, { payload: id }) { return state.filter(item => item.id !== id); }, }, } ] modelsCombine.forEach(m=>app.model(m))
③ const App = connect()();
一般来说,一个页面需要一个model和一个connect()就够了,这里的connect()可以剥离成独立文件,在路由配置中注册好就行,不需要堆在一起。
product.js:
import React from 'react'; import { connect } from 'dva'; import ProductList from '../components/ProductList'; const Products = ({ dispatch, products }) => { function handleDelete(id) { dispatch({ type: 'products/delete', payload: id, }); } return ( <div> <h2>List of Products</h2> <ProductList onDelete={handleDelete} products={products} /> </div> ); }; // export default Products; export default connect(({ products }) => ({ products, }))(Products);
④ app.router();
写一个独立的路由配置就够了。
app.router(require('./router').default); //router.js import React from 'react'; import { Router, Route, Switch } from 'dva/router'; import MainPage from './components/MainPage'; import SecondPage from './components/SecondPage'; import Countor from './routers/Countor'; import Products from './routers/Products'; function RouterConfig({ history }) { return ( <Router history={history}> <Switch> <Route path="/" exact component={MainPage} /> <Route path="/SecondPage" exact component={SecondPage} /> <Route path="/Countor" exact component={Countor} /> <Route path="/Products" exact component={Products} /> </Switch> </Router> ); } export default RouterConfig;
⑤ app.start('#root');
启动。
官方项目分层大致如此:
16.代理
package.json中
"proxy": "http://localhost:8080/"