以下内容,当具有ES6,JS语法,node环境,前端组件基础观点,写过java代码,包你3天上手React项目,下面最先…
react引见
- react: 一个js框架,让开发者能够在js中写html代码,也就是jsx语法,称为假造dom(类似一个js对象)
- react-dom: 挂载节点,将jsx写的假造dom变成真的dom
- render: 每次都是新旧假造dom之间举行比较,以后才会天生实在dom
建立react项目
命令行运用 npx create-react-app my-app-name 即可建立项目
react中组件(子父之间传值)
A: 父组件 B: 子组件
在A.js文件中运用<B name={name} getName={this.getName}>
个中name为A文件中一个变量,getName为A文件中一个要领
在B.js文件中,可直接运用this.props.name
或this.props.getName
或const { name, getName } = this.props
来获得A中变量,或运转A中要领,末了一种最经常使用,这类体式格局是ES6中新增的解构赋值.
父->子 经由过程子标签上加上属性的体式格局,直接通报,在子重运用this.props来接住属性
子->父 经由过程在子中挪用父通报的要领来完成
详细运用场景: 一个页面右上角挂载一个三级联动选项卡(三级数据从接口猎取),main作为父组件主页面,select作为子组件三级选项卡页面
- main页面担任ajax请求,拿总数据,为子组件准备好一切即插即用数据和要领,在运用select标签的时刻,悉数通报给子
- select页面,在this.props中担任解构一切数据和要领,直接运用,无需体贴逻辑完成
- main叫逻辑组件(智慧组件), select叫UI组件(蠢人组件)
JSX语法
- render中return中的代码都是JSX,和html代码类似.
- 在js中直接写html语法,也能够运用自定义标签,比方能够写本身组件,App组件能够写成 <App />,首字母必需大写开首,JSX标签中,大写开首,基础都是组件,小写开首基础是html标签.
- render顶用JSX语法写html代码,必需在最外层包含一个div,不然编译会报错,在16版本中,假如运用Fragment来示意占位符,在html中显现的时刻,可去掉组件最外层的谁人div,demo以下
<React.Fragment>
// 你的jsx代码
</React.Fragment>
- 运用js表达式/js变量须要运用{}把表达式包裹起来,demo以下
// ES6 ``,${}加三目运算符可处置惩罚庞杂的css名字
<div className={`classA classB ${this.state.isSelect ? 'selected' : ''}`} />
// for轮回遍历请运用map要领,sortTableRows是state中一个变量
{sortTableRows && sortTableRows.map(item => (
<div key={item.id} className="table-row">
<span>{item.title}</span>
<span>{item.author}</span>
<span>{item.comments}</span>
<span>{item.points}</span>
<span>
<CancelButton onClick={() => onMiss(item.id)}>miss</CancelButton>
</span>
</div>
))}
- html标签中举行事宜绑定,事宜称号首字母必需大写,比方 onChange中C就是大写的
- 在html款式中,运用className来替代class
- 运用dangerouslySetInnerHTML={{__html: item}},可在提交数据的时刻,对数据中html标签举行转义处置惩罚
- <label for=”insertArea”>输入内容</label> for须要换成htmlfor
事宜绑定
jsx合成事宜绑定,js高阶函数,绑定的是函数,不能让函数立时实行
不带参数绑定,背面不能加(), 假如加,那函数会立时实行,而不是事宜发作时刻回调实行
带参数绑定,须要在一个匿名函数中写绑定函数
// 合成事宜绑定,不带参数
<li onClick={this.props.delItem}>{item}</li>
// 合成事宜绑定,带参数
<li onClick={(index) => this.props.delItem(index)}>{item}</li>
state和props和render
state: 组件本身内部保护数据,每次更新只须要关联须要变动的数据
1, set数据不依靠之前的数据,直接挪用setState
this.setState({
foo: bar
})
2, set数据依靠之前数据,一定要运用带参数挪用setState
this.setState((prevState, props) => (
// 你的代码
))
// bad
// setState是异步,代码中多个set,有能够fooCount和barCount已被转变
const { fooCount } = this.state
const { barCount } = this.props
this.setState({ count: fooCount + barCount })
// good
this.setState((prevState, props) => (
count: prevState.fooCount + props.barCount
))
props: 父->子,一切通报过来的数据都附加在props中,子在props中能够拿到一切父通报过来的数据
render: 只需state举行set操纵,render一定会实行,包含父state举行set以后,父和子的render都邑被实行
ajax接参数
- 子组件是UI组件,接完父组件数据直接运用,可直接在子组件props中直接运用父组件ajax请求猎取到的数据
- 子组件须要将父组件ajax数据赋值到本身的state中,只能在componentWillReceiveProps生命周期中处置惩罚,不能在constructor中处置惩罚,缘由: 父组件ajax请求最起码第二次render父组件,而子组件中constructor只会实行一次
上述体式格局处置惩罚体式格局比较贫苦,引荐运用体式格局3
3, 父组件担任供应数据和处置惩罚处置惩罚的函数,子组件只担任猎取数据,衬着页面,子组件事宜交互,也是经由过程props来挪用父组件中的函数(经常使用)
生命周期(主要)
以下是运用场景和注重点
组件挂载阶段(只会实行一次,render除外)
constructor(): 设置state,猎取父组件props,并初始化本身的state,并绑定函数中this指向
componentWillMount(): 不能猎取页面dom元素,现在还没用过
render():衬着页面,不做运算,到这里为止,一切数据都应该是经由处置惩罚可直接运用的数据
componentDidMount(): 可猎取dom元素,ajax请求放这里,挪用setState,设置dom元素监听,绘制canvas
组件更新阶段(state或props发作变化)
componentWillReceiveProps(nextProps): nextProps为更新新属性,可举行新旧属性对照,也能够依据新数据来盘算和设置本身的state
shouldComponentUpdate(nextProps, nextState): 返回布尔值,可做衬着优化,依据场景决议是不是衬着该组件,不要挪用setState
componentDidUpdate(prevProps, prevState): 操纵 DOM 或许实行更多异步请求的时机
componentWillUnmount: 作废收集请求,删除监听,一些扫尾事情,不要挪用setState
react中this指向
- 自定义函数的时刻,写自定义函数,须要在constructor中举行函数this指向的绑定
- 在constructor中举行this指向绑定,然后写平常函数
// 体式格局1
getTodoItem = () => {
// 你的逻辑
}
// 体式格局2
constructor(props) {
super(props)
this.inputOnChange = this.inputOnChange.bind(this)
}
inputOnChange() {
// 你的逻辑
}
组件范例
ES6类组件: 有this,props,有state,有生命周期,依据设计图,平常看成父组件运用,从接口拿数据,盘算制品数据,编写事宜函数来处置惩罚数据
无状况组件(纯函数): 吸收输入(props),输出jsx组件实例,没有this,没有生命周期,没有state,可依据props中的数据来盘算相符本身请求的数据(组件中直接挪用要领),
props中能够通报数据,也能够通报函数,平常当作子组件运用,demo以下
import React from 'react'
/*查询表单组件
* Search在运用的时刻,标签中心就是children
* <Search value={searchTerm} onSubmit={this.onSubmit} onChange={this.onChange}>查询</Search> children的值就是查询
*/
const Search = ({value, onChange, onSubmit, children}) => {
return (
<div>
<form onSubmit={onSubmit}>
<input type='text' value={value} onChange={onChange}/>
<button type='submit'>{children}</button>
</form>
</div>
)
}
export default Search
import React from 'react'
import {Slider} from "antd"
import moment from "moment"
import './style.less'
/*
* 时候轴无状况组件
* timeData: 时候数组列表
* timeChange: 时候轴change事宜的回调
* worktime: 当前选中时候
* */
const TimeSlider = ({timeData, timeChange, worktime}) => {
/*
* 猎取时候轴当前选中值
* */
const getDefaultValue = () => {
const { id } = times.find(item => {
return item.dateTime === worktime
})
return id
}
/*
* 猎取时候轴的总长度
* */
const getMax = () => {
return timeData.length
}
/*
* 猎取时候轴显现的time数据
* 花样:
* {
* 0: '2019-11-11'
* 24: '2019-11-12'
* 23: '2019-11-13'
* }
* */
let times = []
const getMarks = () => {
let dates = []
console.log('timeData len', timeData.length)
timeData.map((item, index) => {
const time = {id: index, dateTime: item}
times.push(time)
dates.push(moment(item).format('YYYY-MM-DD'))
})
const newDates = [...new Set(dates)]
console.log('newDates', newDates)
let marks = {}
let datesAmount = []
newDates.map(item => {
const amount = getDateAmount(item, timeData)
const temp = {date: item, amount: amount}
datesAmount.push(temp)
})
for (let i = 0,length = datesAmount.length; i < length; i++) {
const date = {
style: {
color: '#fff',
marginLeft: 0
},
label: moment(datesAmount[i].date).format('MM/DD'),
}
if (i === 0) {
//const mark = JSON.parse(`{"0":"${date}"}`)
const mark = {0: date}
Object.assign(marks, mark)
} else {
const index = i - 1
const lastAmount = getLastDateAmount(index, datesAmount)
// const mark = JSON.parse(`{"${lastAmount}":"${date}"}`)
const mark = { [lastAmount]: date }
Object.assign(marks, mark)
}
}
return marks
}
/*
* 依据 2019-11-11来猎取 数据 ['2019-11-11 11:11:11'] 对应的小时数目
* */
const getDateAmount = (date, timeData) => {
let amount = 0
for (let i = 0,length = timeData.length; i < length; i++ ) {
const item = timeData[i]
if (item.includes(date)) {
amount = amount + 1
}
}
return amount
}
/*
* 猎取当前index往前推一个的一切小时数目
* */
const getLastDateAmount = (index, datesAmount) => {
let sum = 0
for (let i = 0; i <= index; i++) {
sum = sum + datesAmount[i].amount
}
return sum
}
const formatter = (value) => {
const time = times.find(item => {
return item.id === value
})
return moment(time.dateTime).format('HH:mm')
}
const onTimeChange = (value) => {
const time = times.find(item => {
return item.id === value
})
timeChange(time.dateTime)
}
return (
<div className='time-slider'>
<Slider max={getMax()} marks={getMarks()} defaultValue={getDefaultValue()} value={getDefaultValue()} tipFormatter={formatter} onChange={onTimeChange}/>
</div>
)
}
export default TimeSlider
两款chrome插件
- React Developer Tools // F12,检察每一个react组件中state和props的值
- Redux DevTools // F12,检察redux中store的值