JSX(JavaScript XML)
- 如何添加注释
{/* 在这里添加注释*/}
- react 的插值表达式
let name = 'xxx'
let id = 'id'
let className = 'h1tag'
let style = {color: 'red', backgroundColor: 'pink'}
let vDom = <h1 className={classNmae} style={style} id={id}>{name}</h1>
有三点需要注意
- style 属性必须是以对象形式传入
- 在style属性中,不能出现
-
,可以用驼峰命名来代替,background-color=backgroundColor
- 由于class是关键字,所以将标签中的class属性用className代替
react渲染列表
let arr = ['吃饭','睡觉','打豆豆']
let vDom = <div>
{arr.map((item, index) => {
return (<p key={index}>{item}</p>)
})}
</div>
一般 react 使用map()方法遍历,但是
for...in, for...of, forEach
都是可以的
react渲染对象
let obj = {
name: 'xxx',
age: 13,
id: "xxs"
}
let vDom = <div>
{Object.keys(obj).map((v, i) => {
return(<p key={i}>{v}:{obj[v]}</p>)
})}
</div>
Object.keys(obj)
获取obj的键为一个数组
Object.values(obj)
获取obj的值为一个数组
react组件
构建方式
1. 无状态组件/函数组件
function Com() {
return ('xml对象') //也就是组件内容
}
let vDom = <Com/>
2. 类组件
class MyCom extends React.Component {
render() {
return (<div>我是类组件</div>)
}
}
let classvDom = <MyCom/>
需要特别注意的是: 不管哪种方式创建组件,组件名首字母都
必须
大写
组件的属性
1. props 组件向外的接口,props是父组件传来的数据,所以不能修改自身props的值,使用props需要将props当作参数传入,然而props是一个对象
,就可以使用{prop.key}来使用外部以属性传入的值
1. 函数组件
function UseProps(props) {
return (<div>{props.xxx}</div>)
}
let vDom = <UseProps xxx=''/>
//当props的内容很多是,全部写在标签里面,很丑,很低效,所以,es6中的解构就可以用到了
第一步:创建props对象
let content = {
name: 'xxx',
sex: '男',
id: '001'
}
第二步:props对象解构在组件标签中即可
let vDome = <UseProps {...content}/>
2. 类组件(多值情况同上)
ClassUseProps extends React.Component {
render(){
return (<div>{this.props.name},{this.props.sex},{this.props.id}</div>)
}
}
let vDom = <ClassUseProps/>
区别:
函数组件:需要传入props
为形参,直接使用prop.xxx
类组件:要将props
传入constructor(props){super(props)}
马上会谈到,需要使用this.props.xxx
- props属性默认值的设置(在没有值传入的情况下使用)
// 函数组件和类组件添加默认值方法一样
ComponentName.defaultProps = {
add: '地球'
}
- props验证(验证数据类型是否为预期类型)
1. 安装 prop-types 包
npm i prop-types --save
2. 在<head></head>中通过<script src=''></script>引入
<script src='./node_module/./.'><script>
3. 使用 ComponentName.propTypes = {} 方法进行预期设定
ComponentName.propTypes = {
key: PropTypes.number //要验证必须为 什么类型
}
注意:props验证失败不会影响程序执行,只会在终端输出一个错误,便于在开发时发现错误,发行时最好取消
2. state属性,state是组件对内的接口,也就是自我数据管理属性,state数据是可以在组件内修改修改的,state数据发生改变后自动渲染(声明式渲染:数据改变自动渲染)
注意: 这就意味着我们不能再使用函数组件(无状态组件)
class UseState extends React.Component {
// ES6中会自动补上constructor,所以可以不写,但是如果写了,就必须把super(props)都写上
constructor(props) {
// super(props)的意思是继承父类的构造方法,如果要在构造器(constructor)中使用props,就在super中传入props
super(props)
// 定义state
this.state = {
// state数据
name: 'xxx'
}
}
render() {
return(
<div>
{/*this.setState({key: newValue})*/}
<button onClick={()=>{this.setState({name:'myName'})}}>click to setState</button>
<h1>{this.state.name}</h1>
</div>
)
}
}
修改state的值要要使用到
this.setState({key:newVlaue})
,它是一个异步函数,当state中的值发生改变之后,自动重新渲染
小知识点:如果要给组件编写函数,在class中与render()
,constructor()
同级书写,用this.functionName
调用,不添加圆括号
- 说一说异步的this.setState({})
创建组件类啊什么的我们都省略,专注于主题
this.setState({name: '修改后'}) //假设我们已经有一个state对象,而且state里面有 name:'修改前'
console.log(this.state.name) // 输出后发现它的值还是修改前
问题:这是由于异步函数加载的慢,用我自己的理解来说:异步就是从此处开始分支出此函数,程序继续向下走,也就是说你执行你的;我执行我的,这就是我理解的“异步”
解决办法:this.setState({}).then(原来的代码)
,意思就是等我把state的值修改好了,你再执行
* 说一说如果state中有JSX代码,怎样解析后插入到页面
专注主题
<div>{this.state.html}</div> // 假设state中有个 {html: "<p>希望展示在p标签里</p>"}
问题:事实总是不尽人意,
<p>希望展示在p标签里</p>
会原封不动的展示出来
解决办法:dangerouslySetInnerHTML = {{__HTML: this.state.html}}
,不用我说了,它自己都说了,很危险,看着就麻烦,估计没人用(自己理解,不喜勿喷)
3. ref属性,同样不能再无状态(函数)组件,中使用,简单来说就是一个添加一个标志,有三种方式
- 字符串方式
专注主题,假设什么都有了,下面内容是return出去的JSX
<div>
<h2 onClick={this.getInput}>click to get the input-tag value</h2>
<input ref='refname' typt='text' placeholder='input'/>
</div>
在class中有一个方法
getInput = ()=>{
console.log(this.refs.refname.value)
}
点击上述代码就可以输出输入框中的内容,
ref
是一个标志refs
是将所有ref
放到一个对象内方便使用
- 回调函数(推荐)
什么都有了
<input type='text' placeholder='ll' ref={(input)=>{this.anyname = input}
getInput = ()=>{
console.log(this.anyname.value)
}
其实它和字符串方式没什么区别,只不过他是将赋值方法写了出来,用了一个回调函数,
形参为当前节点
,而且它不再被存入refs
对象中了,所以调用方法略有不同
- React.creatRef()
我什么都有!
1. 先在constructor中创建好
this.beforValue = React.createRef()
2. 在节点将创建好的值赋值给ref
<input ref={this.beforValue}/>
3. 通过this.创建好的值.current来调用
getInput = ()=>{
console.log(this.beforValue.current.value)
}
需要注意的只有调用时要用到
this.beforValue.current.value
,current 就很突兀…
事件和this
react中调用函数不添加圆括号,前面有提到,添加后就会直接执行
那么问题来了,如果想传参数,怎么办???
往下读就会发现
绑定this的四种种方法
- 使用bind绑定this
调用函数时使用functionName.bind(this)
- 使用箭头函数(箭头函数会有本身开始向外寻找第一个对this有定义的‘东西’)
在创建函数时使用箭头函数 - 在constructor中提前绑定
this.functionName = this.functionName.bind(this)
- 用箭头函数调用方法(刚开始看很懵,代码一看就很清晰)
onClick={()=>{this.functionName()}
我们惊喜的发现除了第四种方式,其他方式都没有圆括号,此时我们只需要
functionName.bind(this, 参数1,参数2,···)
条件渲染
如果你看过
vue
,那么v-if
,v-else
等等指令应该有点印象,但是React并没有封装这些指令,那么我们在React 中应该如何使用条件渲染?
class UseIf extends React.Component {
constructor(props){
super(props)
this.state = {textBool:true}
}
changeC = () =>{
let textBool = this.state.textBool
this.setState({textBool: !textBool}) // 错误3 改变之前没有用变量接收
}
render(){
let text
if (this.state.textBool) { // 错误2 没加this.state
text = 'If成功'
} else {
text = 'if失败'
}
return (
<div>
<button onClick={this.changC}>点击切换</button> {/*错误1 没加this*/}
<div>{text}</div>
</div>
)
}
}
总结易错点:
- 当组件有多个字标签时要用一个父标签包裹起来
- 调用方法时必须使用
this.functionName
- 在
this.state
中的值如果想修改,必须使用一个变量先来接收一下
react组件生命周期
第一阶段:创建时
- constructor 最先执行
- componentWillMount 在组件挂载前调用
- render 此时只是渲染到内存中
- componentDidMount 在组件挂载之后执行
第二阶段:运行时
- shouldComponentUpdate 状态改变后,是否更新页面
- componentWillUpdate 在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
- render 调用render渲染
- componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
第三阶段:销毁时
- componentWillUnmount在组件从 DOM 中移除之前立刻被调用。