1、基本知识
npm install -g create-react-app /* 安装create-react-app,建议使用cnpm */
create-react-app hl-app /* 使用命令创建应用,myapp为项目名称 */
cd hl-app /* 进入目录,然后启动 */
npm start
按以上执行,即可快速创建React开发环境。
打开http://localhost:3000/ 查看
配置工程
npm install redux --save //安装数据流 redux
npm run eject //安装相关的插件,跟配置
npm install express --save // 安装express
npm install install -g nodemon // 这个nodemon是帮助我们不用每次修改都重启服务器
运行时候: nodemon server.js 替换了之前的node server.js
只需要在页面上刷新就可以的了
注意: res.send 跟 res.json 他们之间是不太相同的
安装数据库 MongoDB 见官网: 然后命令行: mongo -->为了看是否安装成功
npm install mongoose --save //在项目中安装的,链接本地数据库MongoDB
使用mongodb----增(create)删(remove)改(update) 查(find findOne)
const express = require('express')
const mongoose = require('mongoose')
// 链接mongo,并且使用dashu集合
const DB_URL = 'mongodb://localhost:27017/dashu'
mongoose.connect(DB_URL)
// 以下这行可要可不要,要的话就是可以方便看到链接成功了
mongoose.connection.on('connected', function () {
console.log('mongo connect success')
})
// 类似于mysql的表 mongo里有文档、字段的概念
const User = mongoose.model('user', new mongoose.Schema({
user: {type: String, require: true},
age: {type: Number, require: true}
}))
//新增数据create
/*User.create({
user: 'xiaohua',
age: 20
}, function (err, doc) {
if (!err) {
console.log(doc)
} else {
console.log(err)
}
})*/
// 删除remove
// User.remove({age:20}, function () {
// console.log('delete success!')
// })
// 跟新(改)update
User.update({'user': 'xiaoming'}, {'$set': {age: 38}}, function (err, doc) {
console.log(doc)
})
// 新建app
const app = express()
app.get('/', function (req, res) {
res.send('<h1>hello world~~~~~</h1>')
})
app.get('/data', function (req, res) {
// 查询数据用find, 查询一条是用findOne
User.find({}, function (err, doc) {
if(!err) {
res.json(doc)
} else {
res.send('server 500')
}
})
// res.json({name: 'yemuxiaocao', type: 'IT', age: 90})
})
app.listen(9090, function () {
console.log('Node app run port 9090')
})
2、react跟es6基本知识
---props 属性传值 onClick事件 react生命周期
import React, { Component } from 'react';
import { Button } from 'antd-mobile';
class App extends Component {
render() {
const boss = '大树老板'
return (
<div>
<h1>老板名字:{boss}</h1>
<员工 员工='夜幕小草'></员工>
<员工2 员工='夜幕小草222'></员工2>
</div>
);
}
}
// props属性 由父组件传给子组件
class 员工 extends Component {
constructor(props) {
super(props)
this.state = {
solders: ['小牛', '阿虎', '阿辉', '小美']
}
/*第一种方式解决this*/
// this.addSolder = this.addSolder.bind(this)
console.log('组件初始化')
}
componentWillMount() {
console.log('组件马上就要挂载了')
}
componentDidMount() {
console.log('组件已经挂载')
}
componentWillReceiveProps(nextProps) {
console.log('组件要接收父组件的值了')
}
shouldComponentUpdate() {
console.log('判断组件是不是要更新组件')
return true; //记得要返回true
}
componentWillUpdate() {
console.log('马上就要更新组件了')
}
componentDidUpdate() {
console.log('组件更新完毕')
}
componentWillUnmount() {
console.log('组件卸载了')
}
// 点击事件修改数据,并且this的注意事项
// 第三种绑定this方式 addSolder = () => {}
addSolder(){
this.setState({
solders: [...this.state.solders, '新员工']
})
console.log('新员工。。。。')
}
render() {
console.log('渲染render函数')
return (
<div>
<h2>员工:{this.props.员工}</h2>
{/*第一种绑定this*/}
{/*<button onClick={ this.addSolder}>添加新员工</button>*/}
{/*第三种绑定this*/}
{/*<button onClick={ this.addSolder}>添加新员工</button>*/}
{/*第二种绑定this*/}
<Button type="primary" onClick={ () => this.addSolder()}>添加新员工</Button>
{/*<button onClick={ () => this.addSolder()}>添加新员工</button>*/}
<ul>
{this.state.solders.map((v, index )=> { return <li key={index}>{v}</li>})}
</ul>
</div>
)
}
}
// props函数式方式
function 员工2(props) {
return <h2>员工:{props.员工}, 好厉害!</h2>
}
export default App;
使用 antd-mobile
按需加载 :npm install antd-mobile --save
npm install babel-plugin-import --save-dev
// .babelrc or babel-loader option
{
"plugins": [
["import", { libraryName: "antd-mobile", style: "css" }] // `style: true` 会加载 less 文件
]
}
详细见官网:https://mobile.ant.design/docs/react/introduce-cn
3、redux基本使用
import { createStore } from 'redux'
//1新建store
//通过reducer建立
//根据老的state和action生成新的state
function counter(state=0, action) {
switch (action.type) {
case '加一':
return state + 1
case '减一':
return state - 1
default:
return 10
}
}
//新建store
const store = createStore(counter)
const init = store.getState()
console.log(init)
function listener() {
const current = store.getState()
console.log(`现在的数据是:${current}`)
}
//监听订阅数据变化
store.subscribe(listener)
// 派发事件,传递action
store.dispatch({type: '加一'})
store.dispatch({type: '加一'})
store.dispatch({type: '加一'})
store.dispatch({type: '加一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
一个友好的组件就是依赖性是比较弱的,所以在跟react组件搭配使用的时候,应该使用props这个属性来传递,在APP挂载的时候就应该挂上去的了。
4、友好的组件
index.js文件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { createStore } from 'redux'
import {counter, add, det} from "./index.redux";
const store = createStore(counter)
function render() {
ReactDOM.render(<App store={store} add={add} det={det}/>, document.getElementById('root'));
}
render()
registerServiceWorker();
/*监听手动跟新store*/
store.subscribe(render)
index.redux.js文件
// import {actionType} from "./index.actionType";
/* action type*/
const ADD = '加一'
const DET = '减一'
//根据老的state和action生成新的state
// reduer
export function counter(state=0, action) {
switch (action.type) {
case ADD:
return state + 1
case DET:
return state - 1
default:
return 10
}
}
/*action creator*/
export function add() { return {type: ADD} }
export function det() { return {type: DET} }
/*只不过是把action跟action-type分开了而已*/
APP.js文件
import React, { Component } from 'react';
import { Button } from 'antd-mobile';
// import {add, det} from "./index.redux";
// import {actions} from "./index.action";
class App extends Component {
render() {
const boss = '大树老板'
const store = this.props.store
const num = store.getState()
const add = this.props.add()
const det = this.props.det()
return (
<div>
<h1>老板名字:{boss}</h1>
<h2>当前的数量是{num}</h2>
<Button type="primary" onClick={ () => store.dispatch(add)}>加一</Button>
<Button type="primary" onClick={ () => store.dispatch(det)}>减一</Button>
<员工 员工='夜幕小草'></员工>
<员工2 员工='夜幕小草222'></员工2>
</div>
);
}
}
// props属性 由父组件传给子组件
class 员工 extends Component {
constructor(props) {
super(props)
this.state = {
solders: ['小牛', '阿虎', '阿辉', '小美']
}
/*第一种方式解决this*/
// this.addSolder = this.addSolder.bind(this)
console.log('组件初始化')
}
componentWillMount() {
console.log('组件马上就要挂载了')
}
componentDidMount() {
console.log('组件已经挂载')
}
componentWillReceiveProps(nextProps) {
console.log('组件要接收父组件的值了')
}
shouldComponentUpdate() {
console.log('判断组件是不是要更新组件')
return true; //记得要返回true
}
componentWillUpdate() {
console.log('马上就要更新组件了')
}
componentDidUpdate() {
console.log('组件更新完毕')
}
componentWillUnmount() {
console.log('组件卸载了')
}
// 点击事件修改数据,并且this的注意事项
// 第三种绑定this方式 addSolder = () => {}
addSolder(){
this.setState({
solders: [...this.state.solders, '新员工']
})
console.log('新员工。。。。')
}
render() {
console.log('渲染render函数')
return (
<div>
<h2>员工:{this.props.员工}</h2>
{/*第一种绑定this*/}
{/*<button onClick={ this.addSolder}>添加新员工</button>*/}
{/*第三种绑定this*/}
{/*<button onClick={ this.addSolder}>添加新员工</button>*/}
{/*第二种绑定this*/}
<Button type="primary" onClick={ () => this.addSolder()}>添加新员工</Button>
{/*<button onClick={ () => this.addSolder()}>添加新员工</button>*/}
<ul>
{this.state.solders.map((v, index )=> { return <li key={index}>{v}</li>})}
</ul>
</div>
)
}
}
// props函数式方式
function 员工2(props) {
return <h2>员工:{props.员工}, 好厉害!</h2>
}
export default App;
5、使用插件使得redux跟react更加好的链接跟调试及其开发,调试工具在浏览器google应用商店分别搜索redux和react都是安装第一个
异步任务处理:npm install redux-thunk --save
使用applyMiddleware开启thunk中间件
在index.js页面开启
import thunk from 'redux-thunk'
import { createStore, applyMiddleware } from 'redux'
const store = createStore(counter, applyMiddleware(thunk))
index.redux.js文件
//异步操作
export function addAsync() {
return dispatch => {
setTimeout(()=>{
dispatch(add())
}, 2000)
}
}
6、调试工具,在google应用商店搜索redux,安装第一个安装
index.js全局配置一下
import thunk from 'redux-thunk'
import { createStore, applyMiddleware, compose } from 'redux'
import {counter, add, det, addAsync} from "./index.redux";
//compose处理集合的问题
const store = createStore(counter, compose(
applyMiddleware(thunk),
window.devToolsExtension? window.devToolsExtension() : f=>{}
))
看一下效果
image.png
6-1、使用react-redux之前的代码(记录一下代码)
---APP.js文件
import React, { Component } from 'react';
import { Button } from 'antd-mobile';
// import {add, det} from "./index.redux";
// import {actions} from "./index.action";
class App extends Component {
render() {
const boss = '大树老板'
const store = this.props.store
const num = store.getState()
const add = this.props.add()
const det = this.props.det()
const addAsync = this.props.addAsync()
return (
<div>
<h1>老板名字:{boss}</h1>
<h2>当前的数量是{num}</h2>
<Button type="primary" onClick={ () => store.dispatch(add)}>加一</Button>
<Button type="primary" onClick={ () => store.dispatch(addAsync)}>延时2秒加一</Button>
<Button type="primary" onClick={ () => store.dispatch(det)}>减一</Button>
<员工 员工='夜幕小草'></员工>
<员工2 员工='夜幕小草222'></员工2>
</div>
);
}
}
// props属性 由父组件传给子组件
class 员工 extends Component {
constructor(props) {
super(props)
this.state = {
solders: ['小牛', '阿虎', '阿辉', '小美']
}
/*第一种方式解决this*/
// this.addSolder = this.addSolder.bind(this)
console.log('组件初始化')
}
componentWillMount() {
console.log('组件马上就要挂载了')
}
componentDidMount() {
console.log('组件已经挂载')
}
componentWillReceiveProps(nextProps) {
console.log('组件要接收父组件的值了')
}
shouldComponentUpdate() {
console.log('判断组件是不是要更新组件')
return true; //记得要返回true
}
componentWillUpdate() {
console.log('马上就要更新组件了')
}
componentDidUpdate() {
console.log('组件更新完毕')
}
componentWillUnmount() {
console.log('组件卸载了')
}
// 点击事件修改数据,并且this的注意事项
// 第三种绑定this方式 addSolder = () => {}
addSolder(){
this.setState({
solders: [...this.state.solders, '新员工']
})
console.log('新员工。。。。')
}
render() {
console.log('渲染render函数')
return (
<div>
<h2>员工:{this.props.员工}</h2>
{/*第一种绑定this*/}
{/*<button onClick={ this.addSolder}>添加新员工</button>*/}
{/*第三种绑定this*/}
{/*<button onClick={ this.addSolder}>添加新员工</button>*/}
{/*第二种绑定this*/}
<Button type="primary" onClick={ () => this.addSolder()}>添加新员工</Button>
{/*<button onClick={ () => this.addSolder()}>添加新员工</button>*/}
<ul>
{this.state.solders.map((v, index )=> { return <li key={index}>{v}</li>})}
</ul>
</div>
)
}
}
// props函数式方式
function 员工2(props) {
return <h2>员工:{props.员工}, 好厉害!</h2>
}
export default App;
---index.js文件
/*1-3章关于react的测试*/
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import thunk from 'redux-thunk'
import { createStore, applyMiddleware, compose } from 'redux'
import {counter, add, det, addAsync} from "./index.redux";
//compose处理集合的问题
const store = createStore(counter, compose(
applyMiddleware(thunk),
window.devToolsExtension? window.devToolsExtension() : f=>{}
))
function render() {
ReactDOM.render(<App store={store} add={add} det={det} addAsync={addAsync}/>, document.getElementById('root'));
}
render()
registerServiceWorker();
/*监听手动跟新store*/
store.subscribe(render)
/*第四章reduxtest*/
/*import { createStore } from 'redux'
//1新建store
//通过reducer建立
//根据老的state和action生成新的state
function counter(state=0, action) {
switch (action.type) {
case '加一':
return state + 1
case '减一':
return state - 1
default:
return 10
}
}
//新建store
const store = createStore(counter)
const init = store.getState()
console.log(init)
function listener() {
const current = store.getState()
console.log(`现在的数据是:${current}`)
}
//监听数据变化
store.subscribe(listener)
// 派发事件,传递action
store.dispatch({type: '加一'})
store.dispatch({type: '加一'})
store.dispatch({type: '加一'})
store.dispatch({type: '加一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})
store.dispatch({type: '减一'})*/
---index.redux.js文件
// import {actionType} from "./index.actionType";
/* action type*/
const ADD = '加一'
const DET = '减一'
//根据老的state和action生成新的state
// reduer
export function counter(state=0, action) {
switch (action.type) {
case ADD:
return state + 1
case DET:
return state - 1
default:
return 10
}
}
/*action creator*/
export function add() { return {type: ADD} }
export function det() { return {type: DET} }
//异步操作
export function addAsync() {
return dispatch => {
setTimeout(()=>{
dispatch(add())
}, 2000)
}
}
/*只不过是把action跟action-type分开了而已*/
7、使用react-redux来更好的链接react跟redux
image.png
npm install react-redux --save
image.png
改造后的代码: 提供了Provider 跟connect方法,是非常不错的
<Button type="primary" onClick={ () => store.dispatch(add)}>加一</Button>
connect里边已经有dispatch方法
<Button type="primary" onClick={ this.props.add}>加一</Button>
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux'
import {counter, add, det, addAsync} from "./index.redux";
//compose处理集合的问题
const store = createStore(counter, compose(
applyMiddleware(thunk),
window.devToolsExtension? window.devToolsExtension() : f=>{}
))
ReactDOM.render(
(<Provider store={store}>
<App />
</Provider>), document.getElementById('root'));
//引用react-redux,取消以下的的写法,属性add={add} det={det} addAsync={addAsync}也不要了,
//全部集合在connect当中
// function render() {
// ReactDOM.render(<App store={store} add={add} det={det} addAsync={addAsync}/>, document.getElementById('root'));
// }
// render()
registerServiceWorker();
/*监听手动跟新store*/
// store.subscribe(render)
App.js文件
import React, { Component } from 'react';
import { Button } from 'antd-mobile';
import {connect } from 'react-redux'
import {add, det, addAsync} from "./index.redux";
// import {actions} from "./index.action";
class App extends Component {
render() {
const boss = '大树老板'
// const store = this.props.store
// const num = store.getState()
// const add = this.props.add()
// const det = this.props.det()
// const addAsync = this.props.addAsync()
return (
<div>
<h1>老板名字:{boss}</h1>
<h2>当前的数量是{this.props.num}</h2>
<Button type="primary" onClick={ this.props.add}>加一</Button>
<Button type="primary" onClick={ this.props.addAsync}>延时2秒加一</Button>
<Button type="primary" onClick={ this.props.det}>减一</Button>
<员工 员工='夜幕小草'></员工>
<员工2 员工='夜幕小草222'></员工2>
</div>
);
}
}
/*获取数据--直接传给属性*/
const mapStatetoProps = (state) => {return {num: state}}
/*获取方法--*/
const actionCreators = {add, det, addAsync}
/*通过connect来链接*/
App = connect(mapStatetoProps, actionCreators)(App)
export default App;
index.redux.js文件
// import {actionType} from "./index.actionType";
/* action type*/
const ADD = '加一'
const DET = '减一'
//根据老的state和action生成新的state
// reduer
export function counter(state=0, action) {
switch (action.type) {
case ADD:
return state + 1
case DET:
return state - 1
default:
return 10
}
}
/*action creator*/
export function add() { return {type: ADD} }
export function det() { return {type: DET} }
//异步操作
export function addAsync() {
return dispatch => {
setTimeout(()=>{
dispatch(add())
}, 2000)
}
}
/*只不过是把action跟action-type分开了而已*/
connect可以用装饰器方法来写:
image.png
npm run eject
npm install babel-plugin-transform-decorators-legacy --save-dev
然后在package.json文件中配置babel加上plugins配置
"plugins": [
"transform-decorators-legacy", // 就是配置此项
[
"import",
{
"libraryName": "antd-mobile",
"style": "css"
}
]
]
App.js文件 @connect链接方式减少丑陋的写法,简洁,这个就是装饰器的写法
import React, { Component } from 'react';
import { Button } from 'antd-mobile';
import {connect } from 'react-redux'
import {add, det, addAsync} from "./index.redux";
// import {actions} from "./index.action";
/*获取数据--直接传给属性*/
// const mapStatetoProps = (state) => {return {num: state}}
/*获取方法--*/
// const actionCreators = {add, det, addAsync}
/*通过connect来链接*/
// App = connect(mapStatetoProps, actionCreators)(App)
@connect(
// 你要state什么属性放到props里边
state => ({num: state}),
// 你要什么方法,放到props里边, 自动dispatch
{add, det, addAsync}
)
class App extends Component {
render() {
const boss = '大树老板'
// const store = this.props.store
// const num = store.getState()
// const add = this.props.add()
// const det = this.props.det()
// const addAsync = this.props.addAsync()
return (
<div>
<h1>老板名字:{boss}</h1>
<h2>当前的数量是{this.props.num}</h2>
<Button type="primary" onClick={ this.props.add}>加一</Button>
<Button type="primary" onClick={ this.props.addAsync}>延时2秒加一</Button>
<Button type="primary" onClick={ this.props.det}>减一</Button>
<员工 员工='夜幕小草'></员工>
<员工2 员工='夜幕小草222'></员工2>
</div>
);
}
}
export default App;
image.png
8、react-router4路由配置及其使用 官网:https://reacttraining.com/
image.png
image.png
npm install react-router-dom --save
image.png
---index.js文件
路由的简单用法:
主要是BrowserRouter, Route, Link。。BrowserRouter里边要有一个总标签包住,exact 是完全匹配 。Link是链接。
Redirect 直接跳转
Route对应的是路由,里边有一个path属性
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux'
import {counter, add, det, addAsync} from "./index.redux";
import {BrowserRouter, Route, Link, Redirect , Switch} from 'react-router-dom'
//compose处理集合的问题
const store = createStore(counter, compose(
applyMiddleware(thunk),
window.devToolsExtension? window.devToolsExtension() : f=>{}
))
function Two() {
return <h1>员工222</h1>
}
function Three() {
return <h1>员工333</h1>
}
ReactDOM.render(
(<Provider store={store}>
<BrowserRouter>
<div>
<ul>
<li>
<Link to='/'>一员工</Link>
</li>
<li>
<Link to='/two'>二员工</Link>
</li>
<li>
<Link to='/three'>三员工</Link>
</li>
</ul>
<Redirect to='/three' component={Three}></Redirect>
<Route path='/' exact component={App}></Route>
<Route path='/two' component={Two}></Route>
<Route path='/three' component={Three}></Route>
{/*<App />*/}
</div>
</BrowserRouter>
</Provider>), document.getElementById('root'));
image.png
import {conbinReudcers} from 'redux'
合并reducer,因为状态很多的时候
reducer.js文件
// 合并所有的reducer 并且返回。 使用的方法是combineReducers
import {combineReducers} from 'redux'
import {counter} from "./index.redux";
import {auth} from "./Auth.redux";
export default combineReducers({counter, auth})
auth.js文件
import React, {Component} from 'react'
import { connect } from 'react-redux'
import { login } from './Auth.redux'
import { Route, Link, Redirect, Switch} from 'react-router-dom'
// 两个reducers, 每个reducers都有一个state
// 合并reducers
@connect(
state => state.auth,
{login}
)
class Auth extends Component{
constructor(props){
super(props)
}
render(){
const app = <button></button>
return (
<div>
{ this.props.isAuth ? <Redirect to='/dashboard'/> : null}
<h2>你没有权限,你还没有登录!!!</h2>
<button onClick={this.props.login}>登录</button>
</div>
)
}
}
export default Auth
<------------------------------------------------------------待续-------------------------------------------------------->
网友评论