React总结和遇到的坑
一、react项目
前端react后端node:https://github.com/GainLoss/react-juejin
前端react后端Pyton:https://github.com/GainLoss/python-react
二、react理解
1.react优点
组件、单向数据、虚拟DOM、生态系统、JSX
组件:一个组件就像一个接受道具作为输入并输出声明的函数接口。 UI应该由尽可能多的组件组成可以最大限度地提高可重用性。
单项数据:React使用单向数据流,因此只会更改数据结果更改UI。如果您使用Redux,则可以在全局应用程序中更改数据存储,组件监听那里的变化。
具体流程:(1)操作通过将数据传输到Dispatcher来启动数据流。(2)Dispatcher接收操作并将数据传递到所有store。(3)store包含应用程序的状态,并在收到相关操作后对其进行更新。(4)视图从store接收数据并重新呈现组件。
虚拟DOM:虚拟DOM允许UI在UI变化中具有高效性。这个组件应呈现的内部和之间的过程实际渲染是什么,它允许React在不同的工作平台。
生态系统:react有丰富的生态,有很多插件可以供开发者使用。
2.react和vue的对比
相同之处:(1)使用虚拟DOM (2)组件化
不同之处:(1)react如果状态变化,是从根节点开始重新渲染;vue是确定到某一个节点需要变化,只是更新这个节点;(2)react是用jsx渲染模板;vue使用的是Template模板渲染,还是Html模板;
选取:react生态比较好,插件多;vue学习难度低;
三、在创建项目的时候,各种坑和总结
关于react-router的坑和总结:
1.react-router现在版本是4,所以如果将嵌套的路由都放一块的话,就会出错:
报这种错误Warning: You should not use <Route component> and <Route children> in the same route;
所以将需要嵌套的路由放到你的组件中
2.在页面有导航的时候,我们需要实现点击导航跳转页面的功能,这时候我们需要在导航的render中这样写:
我们用Link: <li key={index}><Link to="/+{item.name}">{item.name}</Link></li> 而且我们需要引入一个import { Link } from 'react-router-dom'
3.我们想要获取当前页面的路由或者说是浏览器中地址栏的地址:
在当前组件中props里面有当前的地址,找一个恰当的生命周期钩子然后再这个函数中this.props里面就可以获取到,或者可以直接在render中return中元素里的{}里面直接获取
4.react-router路由有两种形式:
HashRouter这种的带hash #
BrowerBouter这种是利用html5中history的,这种是需要服务器端支持的,兼容性不是很好
6.有时候需要实现,根据当前地址实现对应导航显示:
在当前组件中获取this.props,然后将这个值赋给this.state,在需要当前组件中渲染导航组件的位置,在导航组件中写<Nav urlLocation={this.state.url}/>,最后在导航组件中获取到this.props里面包含的就是当前路由地址
7.有时候我们需要实现点击排序,给当前路由添加参数:我用的是Link这种方法
组件里面:
<div style={homeMainLeftTwodiv2}>
{
this.state.HomeMenutwo.map((item,index)=>
<span key={index} className={this.query===item.sort?"homesortactive":''}>
<Link to={{pathname:"/home",search: 'sort='+item.sort,}}>{item.name}</Link>
<Route path="/home/:id" component={Home}/>
</span>
)
}
</div>
在router路由中:还是和之前一样的
8.想只是改变地址栏的地址而不是调转页面,就比如我当前页面有两个选择,点击选择,改变地址栏地址,但是还是当前的组件
import createHashHistory from 'history/createHashHistory'
const history = createHashHistory() //点击一级菜单事件
clickTop(event) {
let that = this;
let tab = event.currentTarget.dataset.tab;
that.setState({ menuOne: tab })
console.log(that.setState)
history.push({
pathname: '/home/'+tab,
})
} {
this.state.HomeMenuTop.map((item, index) =>
<span key={index} className={this.state.menuOne === item.tab ? "homesortactive" : ""} data-tab={item.tab} onClick={this.clickTop}>
{item.name}{this.state.menuOne}
</span>
)
}
9.react-router2迁移到react-router4的特性:https://github.com/gmfe/Think/issues/6
10.在npm start之后页面出现这种错误Uncaught TypeError: Super expression must either be null or a function, not undefined
原因是:在编写组件的时候React.Component写错了
11.在react中使用事件:
如果没有用bind的话那么点击事件只在页面一开始的时候执行,不会在元素点击的时候执行,只有用this.click.bind(this)就可以,在点击元素的时候也执行这个函数
class FLeft extends React.Component{
constructor(props){
super(props)
this.state={
currentIndex:0,
} }
clickTab(index,e){
this.setState({currentIndex:index});
}
render(){
var styles={
width:'100%',
height:'300px'
}
var index=this.state.currentIndex;
return (
<div className="f_left">
<textarea className="f_left_text"></textarea>
<div className='f_left_text_choose'>
<span>图片</span>
<span>链接</span>
<span>话题</span>
<button>发布</button>
</div>
<div className='choose_tab'>
<span onClick={this.clickTab.bind(this,0)} className={this.state.currentIndex===0?'active':''}>推荐</span>
<span onClick={this.clickTab.bind(this,1)} className={this.state.currentIndex===1?'active':''}>动态</span>
</div>
</div>
)
}
}
12.在react中使用iconfont (Unicode编码)
一般使用的时候直接用<i className="iconfont">编码</i>这样就可以了,但是当你循环出来i标签的时候,那么iconfont使用的是字符串表示unicode编码,那么我们需要改写一下编码
想使用字符串来传递的话,只要将 "" 改为 “\ue655” 即可。
13.在react中循环中设置点击事件
这个里面只有把点击事件设置成异步的才不会循环出全部的元素的点击事件
<HomeHeader>
{
this.props.homeheader.map((item)=>{
var id=item.id;
return <HomeHeaderItem onClick={()=>this.props.clickChangeList(id)} key={item.id}><Link to={{pathname:'/home/'+id}}>{item.val}</Link></HomeHeaderItem>
})
}
</HomeHeader>
14.配置文件的路径:
有时候在一个组件中要引入一个新的组件,可能路径需要写很多的../,现在我们需要设置一个单词表示父级文件夹
背景:"react": "^16.5.2","react-dom": "^16.5.2","react-scripts": "2.0.4"
打开node_modules中的react-script中webpack.config.dev.js这个文件(是开发环境配置),里面的
resolve:{
alias: {
'react-native': 'react-native-web',
'@': paths.appSrc //对应的是相同文件夹下面的paths.js文件夹里面
},
}
设置完成之后,在组件中引入import Header from '@/common/header/header.js'
关于在react中引入css或者引入外部文件:
1.在react中怎么引入css文件呢:
{
test:/\.css$/,
exclude: /node_modules/,
loader: "style-loader!css-loader"
}
2.html元素中添加css样式的时候:
两种:一种是class名字填写,但是在jsx中class需要写成className; 二种是在行间写样式style={{}}里面放置样式 ;三种是style={colorstyle}里面放置一个变量
关于react中元素渲染和数据交互的总结:
this.state.HomeMenuone.map((item,index)=>
<span key={index}>{item.name}</span>
)
如果不加的话,会出这种错误
2.在react中引入图片的话,当然之前的直接放在src中也是可以的,但是比较好的方法是:
import img from './right.png'
<img src={img}/>
这种方法有可能会出现这种错误:出现Uncaught Error: Module parse failed: Unexpected character '�' (1:0),这种我的解决办法是重新npm install就可以了
3.在前后台交互的时候我用的是fetch实现的:
注意的是在fetch成功调取之后将结构赋给一个数组的时候,在then中需要用这个才能设置好this.setState({result:data}),然后map这个result
4.使用fetch获取后台数据:
fetch("/list/show").then((response)=>{
if(response&&response.status===200){
return response.json();
}
}).then((data)=>{
this.setState({result:data})
});
5.上面的是直接获取后台的数据,但是有时候我们需要用fetch给后台传参数(后台用的是express):
我们如果用get就是和上面是一样的,但是如果我们用post是有区别的和之前的写法,有两种写法:
一种:
if(this.props.location.search){
let idValue=this.props.location.search.split('=')[1];
fetch('/list/detail',{method:'POST',headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},body: `id=${idValue}`}).then((response)=>{
return response.json()
}).then((result)=>{
this.setState({result:result})
})
}
二种:
if(this.props.location.search){
let idValue=this.props.location.search.split('=')[1];
let formData = new FormData();
formData.append("id",123);
fetch('/list/detail',{method:'POST',body:
formData}).then((response)=>{
return response.json()
}).then((result)=>{
this.setState({result:result})
})
}
上面这两种都可以;
另外后台因为用的是express,所以你需要在dev-server.js中添加一个body-parser这个模块是为了解析客户端请求的body的内容,内部使用JSON编码,url编码处理以及对文件的上传处理。
关于react中事件处理的总结:
1.当我们想点击元素,相应的改变state的时候,可以这样:
//constructor
this.clickMenu=this.clickMenu.bind(this)
//点击事件
clickMenu(event){
var that=this;
let sort=event.currentTarget.dataset.sort;
that.setState({query:sort}) }
// render中
<div style={homeMainLeftTwodiv1}>
{
this.state.HomeMenuone.map((item,index)=>
<span key={index} className={this.state.query===item.sort?"homesortactive":'' } data-sort={item.sort} onClick={this.clickMenu}>
<Link to={ {pathname:"/home", search: 'sort='+item.sort,} } >{item.name}</Link>
<Route path="/home/:id" component={Home}/>
</span>
)
}
</div>
React总结和遇到的坑的更多相关文章
- react input的几个坑
[react input的几个坑] 1.input标签中设置value后,input进入controlled模式,valuechange由自动变为手动,导致input无法编辑.如: <input ...
- 【react native】有关入坑3个月RN的心路历程
由于一些原因,笔者最近变更到了RN的团队,回归到了hybrid app的开发的圈子中,固然是有蛮多新鲜感和新机遇的,不过遥想起以前在hybrid中各种view之前跳转的头疼等各种问题,笔者怀着忐忑的心 ...
- React Native 环境搭建踩坑
React Native (web Android)环境搭建踩坑(真的是一个艰辛的过程,大概所有坑都被我踩了 官方文档地址 : https://facebook.github.io/react-nat ...
- 谈谈出入React框架踩过的坑
1 在JSX的元素中写入内联样式,例如<div style={"color:blue"}></div> 报错:warning:Style prop valu ...
- 记一个react拖动排序中的坑:key
在做一个基于react的应用的时候遇到了对列表拖动排序的需求.当使用sortable对列表添加排序支持后发现一个问题:数据正确排序了,但是dom的顺序却乱了,找了一会儿原因后发现是因为在渲染数据的时候 ...
- react项目构建中的坑—淘宝镜像安装后要设置
基本的搭建步骤参考博客:https://blog.csdn.net/qq_27727251/article/details/86593415 这里要强调的坑是:安装完淘宝镜像要将其设置为默认Regis ...
- 【react native】rn踩坑实践——从输入框“们”开始
因为团队技术栈变更为react native,所以开始写起了rn的代码,虽然rn与react份数同源,但是由于有很多native有关的交互和变动,实际使用还是碰到蛮多问题的,于是便有了这个系列,本来第 ...
- 搭建react native所遇到的坑
一.所遇问题 在搭建react native环境中,遇到执行react native run-android命令出现如下问题 Could not resolve all dependencies f ...
- 【React Native】日常踩坑记录_以后将持续更新
作为一名有理想.有抱负的一代iOS程序员,本着“我头发够多,还能学”的原则,我选择了追随那些大佬的脚步,于2018年开始了React Native. 第一步:找文档.准备安装开发环境: 第二步:一步步 ...
随机推荐
- 前端PostJosn,后端转化相应的类
/// <summary> /// JsonPost特性类 /// </summary> [AttributeUsage(AttributeTargets.Method, In ...
- Spring中如何向 Bean注入系统属性或环境变量
[转自] http://unmi.cc/spring-injection-system-properties-env/ 在 Spring 中为 javabean 注入属性文件中的属性值一般人都知道的, ...
- 正确优雅地解决用户退出——JSP及Struts解决方案
摘要 在一个有密码保护的Web应用中,正确处理用户退出过程并不仅仅只需调用HttpSession的invalidate()方法.现在大部分浏览器上都有后退和前进按钮,允许用户后退或前进到一 ...
- Git本地缓存问题 修改密码后git无法拉取
问题描述:使用正确的用户名和密码可以登录到Git代码仓库,但是在本地无法使用Git bash命令行的方式拉取代码. 问题原因:第一次使用Git bash方式拉取代码时,会根据当前的用户和密码生成一串. ...
- esper(4-5)- Context 条件
条件主要包含:Filter,Pattern,Crontab以及Time Period Filter主要就是对属性值的过滤,比如: create context NewUser partition by ...
- python 十大经典排序算法
排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.常见的内部排序算法有:插入排序.希尔排序.选 ...
- groovy——运行方式、基本语法、引入方式、metaClass
jvm运行groovy类有两种方式: 1.使用groovyc编译所有的*.groovy为java的*.class文件,把这些*.class文件放在java类路径中,通过java类加载器来加载这些类. ...
- 解决Resharper在Core项目中无法执行单元测试的问题
项目升级core了,resharper最近升级到2018.1版本,但是安装后还是无法直接运行单元测试,昨天小姐姐发了解决方法,贼有用.所以记录一下,给自己以后或者其他遇到此问题的小伙伴用. 解决Re ...
- yield用法
yield的__next__()和send()的用法,详见代码 def D(): n = 1 while n < 5: m = yield n print("m:",m) p ...
- oracle trim不掉空白字符分享(转)
本文转自:http://www.2cto.com/database/201306/223558.html 问题背景:一个工商注册号,正常的用trim能解决的问题,但是这个case,trim后和肉眼看到 ...