2019.3.12
ES6常用语法
1.Object 的keys、values、entries
const obj = {name:'imooc',course:'React开发App'};
console.log(Object.keys(obj));// "name" " course"
console.log(Object.values(obj));//"imooc" "React开发App"
console.log(Object.entries(obj));//name:'imooc',course:'React开发App'
2.模板字符串
name = 'imooc';
course = 'React';
console.log('helllo' + name+ ',course is ' + course);
console.log(`hello${name},course is${course}`)
3.函数扩展
默认参数值、箭头函数(间歇、保持this作用域)、展开运算符
function hello(name){
console.log(`hello${name}`)
}
const hello1 = (name)=>{
console.log(`hello${name}`)
}
helllo('imooc);
hello1('imooc')
//二者效果相同
const double = x =>2
console.log(double(5))//10
const hello = (name='imooc')=>{
console.log(`hello ${name}!`)
}
hello();//不赋值情况下使用默认值
hello('woniu');//赋值时使用该值
展开运算符
function hello(name1,name2){
console.log(name1,name2)
}
let arr = ['imooc','woniu']
hello.apply(null,arr)//赋值通过apply方法
hello(...arr)
···
const obj = {name:'imooc',course:'React'}
const obj2 = {type:'IT',name:'woniu'}
conosle.log({...obj,...obj2,date:'2019'})//将这些对象拼接到一个对象里
···
4.解构赋值
数组的解构
const arr = ['hello','imooc']
//let arg1 = arr[0]
//let arg2 = arr[1]
let [arg1,arg2] = arr
console.log(arg1,arg2)
对象的解构
const obj = {name:'imooc',course:'React'}
const {name,course} = obj
console.log(name,course)
5.类
class MyApp{
constructor(){
this.name = 'imooc'
}
sayHello(){
console.log(`hello ${this.name}!`)
}
}
const app = new MyApp()
app.sayHello()
6.ES6中新出现的数据结构
Set,元素不可重合
Map
Symbol
7.模块化
ES6自带模块化机制,告别seajs和require.js
Import,import{}
Export,Export default
Node现在还不支持,还需要require加载文件
8.其他
还有一些特性,虽不在ES6范围内,但也被babel支持,普遍被大家结合接受使用(需插件)
对象扩展符,函数绑定
装饰器
Async await
9.常用代码片段
数组
//映射新数组
let arr = [1,2,3]
console.log(arr.map(function(v){
return v*2
}))
console.log(arr.map(v=>v*2))
//遍历数组
[1,2,3].forEach(function(value,index){
console.log(value);
})
//所有元素是否通过测试
[1,2,3,4].some(v=>v*3)
//过滤数组
[1,2,3,4].filter(v=>v>2)
//查询符合条件的元素
arr = [{name:'dasheng',age:18},{name:'rmos',age:1}]
//查找索引
[1,2,3].indexOf(2)
//连接数组
arr1 = [1,2,3]
arr2 = [4,5,6]
[...arr1,...arr2]
//数组去重
arr = [1,2,2,3,3,4]
[...new Set(arr)]
对象
Object.keys({name:'imooc',age:1})//获取对象的key
Object.keys({name:'imooc',age:1}).length//获取对象里数据的数量
//扩展功能
const obj = {name:'imooc',age:1}
const newObj = {...obj, job:'IT', age:18}
console.log(newObj)
//获取列表的头和尾
const [head,...tail] = [1,2,3]//1,2,3
const [last,...intail] = [1,2,3].reverse()//3,2,1
2019.3.14
Express+mongodb开发web后台接口
mongodb是一个非关系型数据库,存储的是类似json的数据
const express = require('express')
const app = express()
app.get('/',function(req,res){
res.send('<h1>Hello world</h1>')
})//打开localhost:8080即可看到helloworld
app.get('/data',function(req,res){
res.json({name:'imooc',type:'IT'})
})//打开localhost:8080/data才可看到json
app.listen(8080,function(){
console.log('node app start at port 8080')
})
app.get方法
每次修改后要停用再重启node server.js,安装nodemon可不用重启
2019.3.19
React基础知识
1.组件间数据传递
为什么函数里是props.属性,class里是this.props.属性
function Hel(props){
return <h2>连长{props.老大}冲啊</h2>
}
class Hello extends React.Component{
render() {
let leader ='hhh'
return<h2>营长{this.props.老大},冲啊</h2>
}
}
2.state
做列表循环时,每个元素要有一个唯一的key,在虚拟dom判断时用。
class Hello extends React.Component{
constructor(props){
super(props)
this.state={
soilders:['虎子','柱子','根生']
}
}
render() {
return (
<div>
<ul>
{this.state.soilders.map(v=>{
return <li key={v}>{v}</li>
})}
</ul>
</div>
)
}
}
3.事件
把一个函数传递给别人之后直接执行,函数内部拿不到this,只有在前面bind或使用箭头函数。.
class Hello extends React.Component{
constructor(props){
super(props)
this.state={
soldier:['虎子','柱子','根生']
}
//解决方案一:绑定this
this.addSoldier=this.addSoldier.bind(this)
}
addSoldier(){
console.log("hello new soldier")
this.setState({ //返回一个新的state而非在原state上修改
soldier:[...this.state.soldier,'新兵蛋子'+Math.random()]
})
}
render() {
return (
<div>
<button onClick={this.addSoldier}>新兵入伍</button>
//解决方案二:写成立即执行的箭头函数
<button onClick={()=>this.addSoldier}>新兵入伍</button>
<ul>
{this.state.soldier.map(v=>{
return <li key={v}>{v}</li>
})}
</ul>
</div>
)
}
}
如果没有解决方案下面的代码,会报错,找不到this,也可以直接把addSoldier写成箭头函数。
4.生命周期
React组件有若干个钩子函数,在组件不同状态执行
- 初始化周期
- 组件重新渲染生命周期(setState等
) -
组件卸载声明周期
5.antd
安装babel-plugin-import可以按需加载。
如果使用 import { Button } from 'antd'; 的写法会引入 antd 下所有的模块。
为了提高打包编译的速度和浏览器下载资源的速度,可以通过以下的写法来只加载需要的组件:
import Button from 'antd/lib/button';
import 'antd/lib/button/style';
更好的办法是使用 babel,用 babel-plugin-import 来实现同样的按需加载效果.
现在插件会帮你转换成 antd/lib/xxx 的写法了,同时因为设置了 style 属性,模块样式也可以按需自动加载,不需要再手动引入css或less文件了。
只需要这样写:
import { Button } from 'antd';
Redux
1.Redux简介
管理状态、与react解耦合
功能:
- 有一个store,记录所有组件状态
- 需要改变时,告诉dispatch要干什么(action)
- 处理变化的人(reducer)拿到state和action,生成新的state
//新建store
//通过reducer建立
//根据老的state和action生成新的状态
function counter(state=0,action){
switch(action.type){
case '加机关枪':
return state+1
case '减机关枪':
return state-1
default:
return 10
}
}
const store = createStore(counter)
const int = store.getState()
console.log(int)//10
//设置listener并订阅,每次state变化都会触发监听事件
function listener(){
const current = store.getState()
console.log(`现有机关枪${current}把`)
}
store.subscribe(listener)
//派发事件 传递action
store.dispatch({type:'加机关枪'})
//console.log(store.getState())
store.dispatch({type:'加机关枪'})
store.dispatch({type:'减机关枪'})
2.Redux和React如何一起使用
- 把store.dispatch方法传递给组件,内部可以调用修改状态
- Subscribe订阅render函数,每次修改都重新渲染
- Redux相关内容,移到单独文件index.redux.js管理
使用store优化react组件:
- 原因:react里常有组件之间共享状态的情况,通常的做法是将组件状态提升到父组件,这样的后果是如果有多个子组件,尽管只有少数几个组件需要共享状态但父组件状态变化会引起所有子组件重新render,引发性能问题。把状态都放进全局store里,组件去订阅各自需要的状态,当状态发生变化时,只有订阅的状态发生变化的组件才重新render。
代码如下
/*index.js*/
import React from 'react'
import ReactDom from 'react-dom'
import { createStore } from 'redux'
import App from './App.js'
import { counter, addGUN, removeGUN } from './index.redux'
const store = createStore(counter)
function render(){
ReactDom.render(<App store={store} addGUN={addGUN} removeGUN={removeGUN}/>,document.getElementById('root'))
}
render()
store.subscribe(render)
/*index.redux.js*/
const ADD_GUN = '加机关枪'
const REMOVE_GUN = '减机关枪'
//redux
export function counter(state=0,action){
switch(action.type){
case ADD_GUN:
return state+1
case REMOVE_GUN:
return state-1
default:
return 10
}
}
//action creator
export function addGUN(){
return {type:ADD_GUN}
}
export function removeGUN(){
return {type:REMOVE_GUN}
}
/*App.js*/
import React from 'react'
// import { addGUN, removeGUN } from './index.redux.js'
//组件应该尽可能通用,与额外业务无关,最好不要有额外依赖,因此不要引入以上代码,增加耦合性,把addGUN,removeGUN在index.js里作为prosp传入
class App extends React.Component{
constructor(props){
super(props)
}
render(){
const store = this.props.store
const num = store.getState()
const addGun = this.props.addGUN
const removeGun = this.props.removeGUN
return (
<div>
<h1>现在有机枪{num}把</h1>
<button onClick={()=>{store.dispatch(addGun())}}>申请武器</button>
<button onClick={()=>{store.dispatch(removeGun())}}>收回武器</button>
</div>
)
}
}
export default App
2019.4.15
Key Words:处理异步、调试工具、更优雅地和react结合
- react处理异步需要redux-thunk插件
- npm install redux-devtools-extension并且开启
- 使用react-redux优雅地链接react和redux
- 使用applyMiddleWare开启thunk中间件
- 有了中间件thunk之后,action可以返回函数,使用dispatch提交action
2019.4.16
补充
redux-thunk
redux的核心概念:将需要修改的state放入store里,action用来描述发生了什么,发起一个action描述发生了什么,用reducer描述action如何改变state tree。创建store时要传入reducer,真正改变store中数据的是store.dispatch API。
- 概念 :dispatch一个action之后,在到达reducer之前,需要一些额外操作,需要用到middleware中间件进行日志记录、创建崩溃报告、调用异步接口或路由等。中间件都是对store.dispatch的增强。
- resux-thunk:redux-thunk中间件最重要的思想就是可以接受一个返回函数的action creator。如果这个action creator返回的是一个函数,就执行,反之按照原来的next(action)执行。正因为这个action creator可以返回一个函数,那么就可以在这个函数中执行一些异步操作。
补充
箭头函数
箭头函数相当于匿名函数,采用函数表达式的写法
完整写法:(参数1,参数2)=>{执行语句}
简写情况:
- 当要执行的代码只有一条return语句时,可省略大括号和return关键字
var sum = (x,y)=>x+y - 传入的参数只有一个时,可省略小括号
var square = x => xx
相当于:var square = function(x){return xx} - 不需要参数时,使用空的圆括号
var one = ()=>1;
相当于:var one = function(){ return 1}
在回调函数中箭头函数很简洁:
var arr= [1,2,3]
var result = arr.map(x=>x*x)
在排序中:
var arr=[1,12,3]
arr.sort((a,b)=>b-a)
有thunk的异步操作,添加延时操作
export function addAsync(){
return dispatch=>{
setTimeout(()=>{
dispatch(addGUN())
},2000)
}
}
2019.5.6
调试工具
chrome搜索redux安装
- 新建store的时候判断window.devToolsExtension
- 使用compose结合thunk和window.devToolsExtension
- 调试窗的redux选项卡,实时看到state
使用装饰器优化connect代码 - npm run eject 弹出个性化配置
- npm install babel-plugin-transform-decorators-legacy插件
- package.json里babel加上plugins配置
2019.5.8
react-redux的使用
- provider组件在应用最外层,传入store即可,只用一次。
- connect负责从外部获取组件需要的参数
- connect可以用装饰器方式写
provider:是react-redux提供的一个react组件,作用是把state传给它的所有子组件,当使用provider传入数据后,下面所有的子组件都可以共享数据。使用方法是把provider组件包裹在最外层,在provider里传入store。
connect:是一个高阶组件,使用方法是把指定的state和指定的action与react组件连接起来,后面括号写UI组件名。四个参数(mapStateToProps,mapDispatchToProps,mergeProps,options),后面俩参数可不要,第一个参数告诉store你需要哪个state,需要什么就直接在mapStateToProps中写出来,store就会返给你。第二个参数是告诉store要派发什么行为,需要派发什么就写在mapDispatchToProps中,store就会告诉reducer要派发的行为,reducer会根据旧的state和action返回新的state。
2019.6.7
Router4
核心概念
- 动态路由、Route、Link、Switch
入门组件
- BrowserRouter,包裹整个应用,只是用一次
- Route,路由对应渲染的组件,可嵌套
-
Link,跳转专用
例子:router4使用react-router-dom作为浏览器端的路由
入门组件
- url参数,Route组件参数可用冒号标识参数
- Redirect组件 跳转 (跳转的其他方式:push)
- switch只渲染一个子Route组件
需求:点击相应link出现对应组件内容,在url后加上不存在的参数,显示参数内容
class Test extends React.Component{
constructor(props){
}
render(){
console.log(this.props)
//获取location信息,并返回显示
return <h2>测试组件{this.props.match.params.location}</h2>
}
}
ReactDom.render(
<Provider store={store} >
<BrowserRouter>
<div>
<ul>
<li>
<link to='/'>一营 </link>
</li>
<li>
<link to='/erying'>二营</link>
</li>
<li>
<link to='/qibinglian'>骑兵连</link>
</li>
</ul>
<switch>
{/*只渲染命中的第一个Route*/}
<Route path='/' component={App}></Route>
<Route path='/erying' component={Erying}></Route>
<Route path='/qibinglian' component={Qibinglian}></Route>
<Route path='/:location' component={Test}></Route>
</switch>
</div>
</BrowserRouter>
</Provider>,
document.getElementById('root'))
Note:打印this.prop可以看到 this.props.match 中包含的 url 信息还是非常丰富的,其中
- history:包含了组件可以使用的各种路由系统的方法,常用的有 push 和 replace,两者都是跳转页面,但是 replace 不会引起页面的刷新,仅仅是改变 url。
- location:相当于URL 的对象形式表示,通过 search 字段可以获取到 url 中的 query 信息。(这里 state 的含义与 HTML5 history.pushState API 中的 state 对象一样。每个 URL 都会对应一个 state 对象,你可以在对象里存储数据,但这个数据却不会出现在 URL 中。实际上,数据被存在了 sessionStorage 中)(参考: 深入理解 react-router 路由系统)
- match:包含了具体的 url 信息,在 params 字段中可以获取到各个路由参数的值。
2019.6.16
React-router4
和redux配合
- 复杂redux应用,多个reducer,用combineReducers合并
- Redirect组件,跳转
- Switch只渲染一个子Route组件
Q1:在url里输入没有的后缀为什么不会报错?而是和第一个一样
需求:1)登陆:没有登陆信息统一跳转至login
2)页面:导航+显示+注销 一营 二营 骑兵连 router+redux
Tips:
- 选中代码文件里一样的单词替换成另一个:双击该单词选中后Crtl + Shift + L,输入新的单词将在所有位置替换掉