react脚手架
下载脚手架 npm i -g create-react-app
脚手架构建工程create-react-app hello-app
脚手架生成的工程被webpack管理,其中的入口文件等是指定的
public下的index.html为文档的入口,默认生成的具有移动端入口图标设置,移动端加壳配置文件manifest.json,一般项目中可以去掉
src中的index.js为脚本入口文件,App.js为一般项目都这么用作入口的组件\
一切皆是模块
import icon from './icon.svg'
import hello from './Hello/index.css' (css样式模块化进行组件间的样式隔离,防止样式污染)
...<div className={hello.container}>被设置样式的文本</div>...
其中的组件建议components 公共组件
pages==>业务逻辑页面,如Home、Item1、其中的index.jsx/index.js在路由中引入时可以省略
代码片段生成重复常用组件框架代码 》》ES7 React/Redux/GraphQL/React-Native snippets 插件,一些常用代码片段
跨域(一般客户端与服务器进程通信,ajax存在跨域问题)\
问题描述:一个本地客户端(3000端口)访问服务器(5000端口)实例
本地可以发,服务器收得到,并返回,此时客户端接收侧收不到
package.json配置代理服务proxy:"http://127.0.0.1:5000" 进行资源*转发*就可以收到5000端口的数据
1.配置代理(前端解决跨域,案例:一般项目中解决跨域的方式)
需要使用代理服务进行数据转发
react脚手架之下配置代理
1.package.json(仅能配置一个)
proxy: '代理服务器的地址'
2.配置n个代理地址
setupProxy.js(webpack脚手架)
const proxy = require('http-proxy-middleware')
module.exports = function(app){
app.use(
proxy('/api', {
target: '代理服务地址',
changeOrigin: true // 模拟5000端口
})
)
}
可类比于vue中的vue.config.js也是对webpack脚手架的代理设置
'/':{
target: process.env.VUE_APP_ENV_TARGET,
changeOrigin : true, //允许跨域
pathRewrite: {
}
},
2.cors解决跨域问题(服务端的解决跨域的方案,案例:访问github、iconfont等公共资源,弊端 在于安全性 所有网站都能访问)
案例
TodoList案例
1.拆分组件,静态实现页面
2.动态组件,组件之间的消息传递(头部,功能区,底部)
App ==>render
(
<div>
<Header/>
<Todos/> // Todos中是Item组件,粒度小点
<Footer/>
</div>
)
1.业务效果
显示todoList;头部输入,回车,向todolist添加一个item;移入,高亮行(考虑数据和DOM分离,物尽其用,才不滥用,Dom完成的状态:鼠标事件、键盘事件);
底部,显示状态(统计全部,统计已完成),可以全选
2.业务逻辑(父组件方法从props传入子组件,相当于引用传递,操作todos)
todoList=[ { id: '1', name: '吃饭', done: true } ];
addTodo-Header、updateTodo-Todos(状态在哪里,操作状态的方法就在哪里)
使用方法onChange/onClick-高阶函数与不使用柯里化;
3.props类型限制 import PropTypes from 'prop-types' tips:方法和属性不要使用es6的关键字(class、delete)
该案例的注意点
1.拆分组件、使用静态组件(注意className、style的 写法):强调对项目整体拆分组件的粒度
2.初始化组件状态,放在父组件还是子组件
1.组件自身使用,放在自身
2.与其他组件共享,放在其父组件中(官方称之为状态提升)
3.组件间通信
1.父传子(通过props)
2.子传父(通过props,父级给子级传一个方法,常用于操作提升的state等)
updateAppState(obj){
this.setState()
}
4.注意defaultChecked、checked以及defaultValue、value
5.重点来了:状态在哪里 ,操作状态的方法就在那里
github案例
解构赋值 const{keyWordElement:{value: myValue}} = this // 深度解构赋值,并进行重命名 关于react中的组件样式覆盖问题,采用css Model,类似于vue中的 scoped 推荐的形式为:BEM(Block模块、Element元素、Modifier修饰)home_title__hover 常用模块导入的形式,相当于加上命名空间前缀修饰 import myCss from './indnex.css'
tips: Objects are not vaild React child 对象类型 不能作为React组件的节点
兄弟组件之间的通信
消息订阅发布机制
第三方库PubSubJS npm i pubsub-js -D
import pubSubJs from 'pubsub-js'
componentDidMount(){
this.subscribe = pubSubJS.subscribe('getList', (_, stateObj)=>{
console.log('get data: ', stateObj)
})
}
//
componentWillUnmount(){
PubSubJS.unsubscribe(this.subscribe)
}
github案例总结\
- 1.组件状态设置合理,网络请求之后,成功、为空、失败的状态
- 2.解构赋值 、重命名
- 3.消息订阅与发布机制
- 4.fetch放送请求(原生、关注分离、兼容性差、Promise风格)
发送请求
xhr 原生发送请求 jQuery的ajax、Promise风格的axios
fetch(兼容性问题) 原生发送请求 Promise风格 但不怎么常用\
fetch('/api1/search/user1?q=sw').then(
res=>{
console.log('联系服务器成功')
return res.json()
},
//err=>{
//console.log('联系服务器失败')
//return new Promise() // 中断Promise链
//}
).then(
res=>{
console.log('获取数据成功,数据为:', res)
},
//err=>{
//console.log('获取数据失败')
//}
).catch( // 兜底处理Promise链中的错误,这样做就可以省略上面的错误处理了
err=>{
console.log(error)
}
)
==》 优化版本
try{
const res = await fetch('/api1/search/user1?q=sw')
const data = await res.json()
}catch(error){
console.log(error, '出现错误!')
}