前端知识点回顾——Reactjs
React.js
编写react需要安装的三个开发环境下的模块
- babel 解析JSX
- react 实现ui用户界面
- react-dom 处理dom
JSX:在JavaScript里面写html代码(最好用圆括号包起来,单标签要闭合),在html代码中用插值符号{}可以写js代码
ReactDOM.render(element, container, cb) 往容器中渲染一个组件element
循环返回dom的时候要加上key属性,但这个属性不能在props中取到
添加css用style属性=一个对象,属性名用驼峰形式命名。
事件名字用驼峰形式命名,其最后一个参数才是事件对象event。
Object.keys(obj)
可以通过扩展运算符+对象给一个标签添加属性:{...data[item]}
声明式无状态组件
function Main(props){ //大写名字的函数,返回一个组件
return (
<div>{props.con}</div>
)
}
let element = (
<div>
<Main con={'simple'}/>
</div>
);
声明式有状态组件
定义一个类继承React.Component,在render方法中返回要渲染的HTML元素。
class Head extends React.Component {
constructor(props){
super(props) // 执行父类的构造函数
this.name = 'dream'
this.age = 18
}
// 不要写function
say(){
console.log('say方法')
}
render(){ // 渲染
return (
<header> 这是真正的有状态的组件 头部 </header>
)
}
}
将在原型上的事件触发函数指向this的三个方法
在标签的事件属性中使用bind;
<header onClick={this.handleClick.bind(this,'argument')}></header>
在constructor中改变函数的this指向,但这种就不适合传参;
this.handleClick = this.handleclick.bind(this)
在原型上定义该函数的时候使用箭头函数;
handleClick = (e)=>{}
//传参的时候使用箭头函数
<header onClick={(e)=>{this.handleClick('arguments',e)}}></header>
包含关系
组件的子元素会被存到props.children属性中:
function FancyBorder(props){
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog(){
return (
<FancyBorder color='blue'>
<h1>Welcome</h1>
<p>Thank you for visiting my blog!</p>
</FancyBorder>
)
}
虽然不太常见,但有时你可能需要在组件中有多个入口,这种情况下你可以使用自己约定的属性而不是 children:
function SplitPane(props){
return (
<div>
<div>
{props.left}
</div>
<div>
{props.right}
</div>
</div>
)
}
function App(){
return (
<SplitPane
left={<Contacts />}
right={<Chat />}
/>
);
}
属性和组合为你提供了以清晰和安全的方式自定义组件的样式和行为所需的所有灵活性。请记住,组件可以接受任意元素,包括基本数据类型、React 元素或函数。
关键字
class -> className
value -> defaultValue
for -> htmlFor
focus -> autoFocus
操作DOM的方式
常规的获取DOM方法:id,类名等
通过事件对象,在该元素身上绑定的事件函数中获取; event.target
通过ref属性,在旧版本中通过给标签ref属性一个字符串,然后实例对象中的ref对象是由保存以ref属性为键,对应的节点为值的键值对组成
<input ref={'btn'}/> //this.refs.btn就指向这个节点
在新版本中建议在ref属性中使用回调函数,在回调函数中给实例对象定义一个值,将该节点直接赋给该值:
<div ref={itemDiv=>this._div=itemDiv}></div> //this._div就指向这个节点
findDOMNode 参数是dom节点时返回dom节点,参数是组件时返回组件渲染的dom节点
子组件往父组件通讯的方法
把父组件的方法通过props传递给子组件,在子组件中调用并传参,就会传到父组件的方法中
生命周期函数
生命周期:组件从定义到挂载,最后渲染到页面的一个过程。
第一阶段:挂载阶段
constructor 构造函数
只会在定义组件的时候执行一次,在此阶段可用于初始化state状态。
componentWillMount()
在组件即将被挂载的时候调用一次,此时组件还没有被渲染出来,这个时候不能够进行DOM操作。此时可以请求接收后端的数据。
render()
渲染组件。
componentDidMount()
此阶段组件挂载完成,用户能够在页面上看到数据,可以对DOM进行操作。若组件包含子组件,则在子组件渲染完毕(constructor->cDM)后才会触发这个函数。
第二阶段:更新阶段(子组件)
(子组件的)构造函数
componentWillReceiveProps(nextProps)
父组件的数据更新会触发子组件的这个函数执行,在这里可以处理父组件更新后,通过props传到子组件的数据,更新构造函数中对应的state值的数据。
shouldComponentUpdate(nextProps, nextState)
是否更新组件,是否触发重新渲染,函数必须有一个Boolean的返回值,true表示执行render函数重新渲染并继续执行后面的生命周期函数,false表示不重新渲染,也就不会再继续执行render和后面的生命周期函数。无论是父组件中this.state导致props数据发生变化还是子组件中的this.state数据发生变化都会触发,对应的参数(state触发的就对应nextState,props触发的就对应nextProps)就变成那个将会发生改变后的数据。
一定要加上判断!因为setState后改变了state的状态又会触发这个函数,以免进入无限循环。另外一方面通过判断数据是否发生变化,如果发生变化则返回true触发重新渲染,不发生变化则返回false避免不必要的重渲染行为。
关于这个钩子函数的重要性的一篇博文:https://www.cnblogs.com/penghuwan/p/6707254.html
componentWillUpdate(nextProps, nextState)
组件即将会被更新。
render()
渲染组件。
componentDidUpdate(prevProps, prevState)
组件渲染完成后执行。对应的参数(state触发的就对应nextState,props触发的就对应nextProps)为会发生改变前的数据。
componentWillUnmount()
关闭网页或者子组件被销毁(在父组件中被取消引用的时候,会先触发父组件的render方法)的时候会执行
thi.setState()除了接收变量改变state属性外,还可以用第二种形式接收一个函数
this.setState((prevState, props)=>{
//先前的状态作为第一个参数,此次更新被应用时的props作为第二个参数
})
})
总结setState操作会触发的生命周期函数顺序如下:
setState -> shouldComponentUpdate(返回true继续往下,返回false就在这里截止了) -> render -> 子组件的componentwillreceiveprops -> 子组件shouldcomponentupdate(返回true继续往下,返回false就在这里截止了) -> 子组件componentwillupdate -> 子组件 render -> 子组件componentdidupdate -> componentdidupdate
利用脚手架开发
安装: npm i create-react-app -g
创建:create-react-app appname
运行项目:npm start
表单控件
- 非受控(非约束性)表单控件:用户输入的表单的值value,react根本就不知道,例如常规的文本表单用户输入了什么react都不能实时得到,需要转成受控表单控件。
- 受控(约束性)表单控件:让react管理表单的数据,能够监视表单的一举一动。表单的value值改变则重新渲染(用自己的说法就是表单的初始状态是由state里决定,表单值value一旦改变state值也要随着进行更新,然后重新渲染表单)
//文本框
class Text extends React.Component{
state = {val : ''}
handleChange = (e)=>{
this.setState({val:e.target.value});
}
render(){
return (
<div>
<input type='text' value={this.state.val} onChange={this.handleChange}></input>
</div>
)
}
}
//单选框
class Radio extends React.Component{
state = {
sex: 'male';
}
handleChange = (e)=>{
this.setState({sex: e.target.value});
}
render(){
return (
<div>
<input type='radio' name='sex' value='male' checked={this.state.sex === 'male'} onChange={this.handleChange}/>
<input type='radio' name='sex' value='female' checked={this.state.sex === 'female'} onChange={this.handleChange}/>
</div>
)
}
}
//下拉菜单
class Select extends React.Component{
state = {
cityList: ['GZ','SZ','SH'],
city:''
}
handleChange = (e)=>{
this.setState({city:e.target.value});
}
render(){
return (
<div>
<select name='city' value={this.state.city} onChange={this.handleChange}>
{
this.state.cityList > 0 &&
this.state.cityList.map((item,index)=>{
return (
<option key={index}>{item}</option>
)
})
}
</select>
</div>
)
}
}
//复选框
class Checkbox extends React.Component{
state = {
name: [{value:'a',checked:true},{value:'b',checked:false},{value:'c',checked:false}]
}
handleChange = (index,e)=>{
const arr = this.state.name;
arr[index].checked = !arr[index].checked;
this.setState({name:arr});
}
render(){
return (
this.state.name > 0 && this.state.name.map((item,index)=>{
return (
<input key={index} type='checkbox' checked={item.checked} onChange={this.handleChange.bind(this,index)}>{item.value}</input>
)
})
)
}
}
路由模块 react-router-dom
BrowserRouter 通常起名为Router, 是一个组件,可以让根组件挂载不同的其他组件
HashRouter 项目上线需要改为hashrouter,让后退操作可用
Route 根据路由控制不同的组件显示
<Route exact path='/' component={Home}></Route>
//exact表示严格匹配 path属性表示当前路由 component表示在当前路由下渲染Home组件
Link 控制路由跳转,相当于a标签
NavLink 功能和Link一样,但有更多api
<NavLink exact to={'/'} activeClassName='active'>首页</NavLink>
//exact严格匹配 to表示要跳转的路由 activeClassName表示标签在active状态下添加的类名
Switch 包裹Route,表示只匹配一个路由,渲染一个组件
Redirect 重定向,用于判断状态看是否需要进行重新定向,一旦渲染到页面上就重定向至指定路由。
<Redirect to='/'></Redirect>
在组件卸载之前 是可以更新状态的(setstate),在组件卸载之后 不要更新状态(setstate),会报错。
例如刚进入页面渲染组件时,过3秒它会更新state,如果在三秒内跳转到其他路由,也就是把这个组件给卸载的话就会出现报错信息。
这个时候可以通过设置componentWillUnmount,将this.setState函数设置为空。
this.props.match.path 得到匹配该子组件的路由
this.props.match.params.id 得到匹配该子组件的动态路由/:id
路由模块化
将路由的属性值保存于组件的state中或者是另起一个js文件保存导入,遍历然后展开(可以用扩展运算符…)
保存在state中:
用js模块导入:
//js模块
//直接导入组件
import News from '';
import Not404 from '';
import NewDetails from '';
const routes = [
{
exact: true, //要用到精确匹配则设置为true
path: '/',
component: Home
},
{
path: '/news',
component: News,
children: [ //子路由
{
exact: true,
path: '/news/',
component: NewIndex
},
...
]
},
...
{
path: '*',
component: Not404 //404模块放在最后
}
]
export default routes
//jsx
import routes form '';
import {Component} from 'react';
import {Switch,Route} from 'react-router-dom';
class App extends Compnent{
render(){
return (
<Switch>
{
routes.length>0 && routes.map((item,index)=>{
return <Route key={index} {...item} />
})
}
</Switch>
)
}
}
嵌套路由传参
如果像上面实现了路由模块化后,那么像News这个组件还有子路由children这个属性怎样去传递给它的子路由呢?答案就是我们不能简单地用component去指向路由要渲染的组件了,而是改用render方法。
还是以上面的routes路由模块数组举例
//jsx
import routes form '';
import {Component} from 'react';
import {Switch,Route} from 'react-router-dom';
class App extends Compnent{
render(){
return (
<Switch>
{
routes.length>0 && routes.map((item,index)=>{
return <Route key={index} path={item.path} render={props=><item.component {...props} routes={item.children}>}/>
})
}
</Switch>
)
}
}
这里用render方法替代component,直接表示返回组件,把子路由children通过routes属性传过去。另外要注意的是{...props}最好写上,这里包含了match等重要的属性,以便在组件中能够取到path和动态路由的值。
prop-types
可以引用内置模块prop-types设置父组件传过来的props属性的数据类型以及设置默认值:
import PropTypes from 'prop-types';
class Head extends Component{...}
//定义父组件中props属性的数据类型
Head.propTypes = {
data: PropTypes.array
}
//设置子组件的props默认的属性值
Head.defaultProps = {
simple: '子组件的默认值'
}
前端知识点回顾——Reactjs的更多相关文章
- 前端知识点回顾——HTML,CSS篇
前端知识点回顾篇--是我当初刚转行为了面试而将自己学过的前端知识整理成的一份笔记,个人目的性很强,仅供参考. doctype 有什么用 doctype是一种标准通用标记语言的文档类型声明,目的是告诉标 ...
- 前端知识点回顾之重点篇——ES6的Promise对象
Promise Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大. 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异 ...
- 前端知识点回顾之重点篇——CSS中flex布局
flex布局 来源: http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool 采用 Flex 布局的元素 ...
- 前端知识点回顾——mongodb和mongoose模块
mongodb和mongoose模块 数据库 数据库有关系型数据库(MySQL)和非关系型数据库(mongodb),两者的语法和数据存储形式不一样. mySQL 关系型数据库 类似于表格的形式,每一条 ...
- 前端知识点回顾——koa和模板引擎
koa 基于Node.js的web框架,koa1只兼容ES5,koa2兼容ES6及以后. const Koa = requier("koa"); const koa = new K ...
- 前端知识点回顾——Nodejs
Node.js 事件循环机制 setImmediate()是将事件插入到事件队列尾部,主线程和事件队列的函数执行完成之后立即执行setImmediate指定的回调函数,和setTimeout(fn,0 ...
- 前端知识点回顾之重点篇——jQuery实现的原理
jQuery jQuery的实现原理 参考:https://blog.csdn.net/zhouziyu2011/article/details/70256659 外层沙箱和命名空间$ 为了避免声明了 ...
- 前端知识点回顾——Javascript篇(六)
fetch 在原生ajax+es6promise的基础上封装的一个语法糖,返回promise对象. fetch(url, initObj) .then(res=>res.json()) .the ...
- 前端知识点回顾之重点篇——CORS
CORS(cross origin resource sharing)跨域资源共享 来源:http://www.ruanyifeng.com/blog/2016/04/cors.html 它允许浏览器 ...
随机推荐
- CSS属性margin、padding的区别
原始状态 不设置margin和padding的状态 margin 设置外边距之后的状态 padding 设置内边距之后的状态 ,注意是撑开,外框高宽由300px变成450px. 说明:本文为原创作品, ...
- sql语句开启事务
以下为示例代码: begin tran update 表 where 姓名='A' update 表 where 姓名='B' rollback else commit
- TreeMap核心源码实现解析
TreeMap实现了SotredMap接口,它是有序的集合.而且是一个红黑树结构,每个key-value都作为一个红黑树的节点.如果在调用TreeMap的构造函数时没有指定比较器,则根据key执行自然 ...
- 学习使用Django一 安装虚拟环境
以上环境可以先在虚拟机上操作,熟练之后再正式机操作!!! 再学习Djangj之前,先讲个小概念,虚拟环境 记得刚刚开始学习Python的时候,往往是用的那个包,就Cmd 上 直接输入“pip ...
- Go语言中的defer
可以用作一些资源的释放. 1.在一个函数内的defer执行顺序是先写的后执行,后写的先执行(遵循栈结构) func DeferTest1(){ defer fmt.Println("我是 d ...
- n诺挑战赛5题解
Drinking 题意:就是给你n瓶酒的初始伤害值,第几天喝这瓶酒伤害值就是这瓶酒的初始伤害值第几倍,而且他每天喝的瓶数不超过m.要你输出所有的情况,就是他喝(1~n)瓶的伤害值的最小, 思路:就是这 ...
- Nginx 配置参数中文说明
Nginx配置参数中文详细说明: #定义Nginx运行的用户和用户组 user www www; # #nginx进程数,建议设置为等于CPU总核心数. worker_processes ; # #全 ...
- Dijkstra算法和Floyd算法
一.简介 迪杰斯特拉(Dijkstra)算法和弗洛伊德(Flyod)算法均是用于求解有向图或无向图从一点到另外一个点最短路径. 二.Dijkstra 迪杰斯特拉算法也是图论中的明星算法,主要是其采用的 ...
- redis事务机制
目录 一.事务的实现 1.multi——开启事务 2.命令入队列 3.exec——执行事务 4.DISCARD——放弃执行 5.错误处理 二.watch命令 redis官方文档:Redis trans ...
- list交集
在C#语言程序设计中,List集合是常用的集合数据类型,在涉及集合类型的运算中,有时候我们需要计算2个List集合中共有的数据,即对2个List集合求交集运算.此时可以使用C#语言提供的Interse ...