一、条件渲染的三种方式
1. 三元表达式
// 构造器
constructor() {
super();
this.state = {
bShow: true
}
}
// 在render函数return中判断
{this.state.bShow ? <div className={'box'}/> :''}
2. &&运算符
{this.state.bShow && <div className={'box'}/>}
3. if判断
// 在render函数return外判断
let box2 = ''
if (this.state.bShow) {
box2 = <div className={'box'}/>
}
页面代码
import React from 'react'
import HeaderComponent from './component/header'
import ReactDom from 'react-dom'
import './assets/css/app.css'
class App extends React.Component {
// 构造器
constructor() {
super();
this.state = {
bShow: true
}
}
// 生命周期钩子
componentDidMount() {
// console.log(this.refs.node.innerHTML)
console.log(document.getElementById('header'))
console.log(ReactDom.findDOMNode(document.getElementById('header')))
}
// 渲染dom
render() {
let username = '张三'
let content = "<span style='color: #ff0000'>搞颜色</span>"
let box2 = ''
if (this.state.bShow) {
box2 = <div className={'box'}/>
}
return (
<div className="App">
{/*头部组件*/}
<HeaderComponent />
{username}
<div dangerouslySetInnerHTML={{__html: content}}/>
{/*<div ref="node">节点信息</div>*/}
{this.state.bShow ? <div className={'box'}/> :''}
<br/>
{this.state.bShow && <div className={'box'}/>}
<br/>
{box2}
</div>
)
}
}
export default App;
效果如下
二、 点击事件
// 在类中定义事件 改变盒子显示/隐藏
change() {
this.setState({bShow: !this.state.bShow})
}
// 在return中通过bind(this)去调用事件
{/*显示隐藏*/}
<button onClick={this.change.bind(this)} >显示/隐藏</button>
三、 列表循环
1. 在state中定义一个数组
this.state = {
// 盒子显示隐藏
bShow: true,
// 商品数据
aGoods: [
{id:1,title:'潮流女装'},
{id:2,title:'品牌男装'},
{id:3,title:'手机电脑'}
]
}
2. 在render函数中用es6的map方法渲染
<ul>
{this.state.aGoods.map((v ,i)=> (
<li key={i}>{v.title}</li>
))}
</ul>
效果
三、父子组件传值
1. 父组件通过属性形式传值
{/*头部组件*/}
<HeaderComponent />
2. 子组件通过props接收
效果
3. 限制props参数类型
3-1 引入prop-types
import PropsType from 'prop-types'
3-2 定义组件的propTypes
HeaderComponent.propTypes = {
title: PropsType.number
}
效果如下 定义的是数值类型, 传入的是字符串报错
4. 参数必填项: isRequired
HeaderComponent.propTypes = {
title: PropsType.string.isRequired
}
5. 参数默认值
HeaderComponent.defaultProps = {
title: '默认子组件值'
}
{/*头部组件*/}
<HeaderComponent />
效果
6. 父子组件的例子, 父组件控制子组件的显示隐藏
import React from 'react'
import HeaderComponent from './component/header'
import ReactDom from 'react-dom'
import './assets/css/app.css'
class App extends React.Component {
// 构造器
constructor() {
super();
this.state = {
// 盒子显示隐藏
bShow: true,
// 商品数据
aGoods: [
{id:1,title:'潮流女装'},
{id:2,title:'品牌男装'},
{id:3,title:'手机电脑'}
],
// 子组件盒子的显示隐藏
childShow: true
}
}
// 生命周期钩子
componentDidMount() {
// console.log(this.refs.node.innerHTML)
// console.log(document.getElementById('header'))
console.log(ReactDom.findDOMNode(document.getElementById('header')))
}
// 改变盒子显示/隐藏
change() {
this.setState({bShow: !this.state.bShow})
}
// 改变盒子显示/隐藏
changeChildComponent() {
this.setState({childShow: !this.state.childShow})
}
// 渲染dom
render() {
let username = '张三'
let content = "<span style='color: #ff0000'>搞颜色</span>"
let box2 = ''
if (this.state.bShow) {
box2 = <div className={'box'}/>
}
return (
<div className="App">
{/*显示子隐藏*/}
<button onClick={this.changeChildComponent.bind(this)} >显示/隐藏</button>
{/*头部组件*/}
<HeaderComponent isShow={this.state.childShow} />
{username}
<div dangerouslySetInnerHTML={{__html: content}}/>
{/*显示隐藏*/}
<button onClick={this.change.bind(this)} >显示/隐藏</button>
{/*<div ref="node">节点信息</div>*/}
{this.state.bShow ? <div className={'box'}/> :''}
<br/>
{this.state.bShow && <div className={'box'}/>}
<br/>
{box2}
<ul>
{this.state.aGoods.map((v ,i)=> (
<li key={i}>{v.title}</li>
))}
</ul>
</div>
)
}
}
export default App;
import React,{Component} from 'react'
import PropsType from 'prop-types'
class HeaderComponent extends Component{
render() {
return (
<div id="header" style={this.props.isShow ? {display: "block"} : {display: 'none'}}>{this.props.title}</div>
)
}
}
HeaderComponent.propTypes = {
title: PropsType.string.isRequired,
isShow: PropsType.bool
}
HeaderComponent.defaultProps = {
title: '默认子组件值',
isShow: true
}
export default HeaderComponent
效果如下
源码中propTypes的类型:
7. 面试题state和props的区别
state和props主要区别于props是不可变的, 而state可以根据于用户交互来改变。这就是为什么有些容器组件需要定义state来更新和修改数据。而子组件只能通过props来传递数据。
7.1 面试题在React, 何为state?
状态是React组件的和兴, 是数据的来源, 必须尽可能简单. 基本上状态是确定组件呈现和行为的对象. 与props不同, 他们是可变的, 并创建动态和交互式组件, 可以通过this.state访问他们
7.2 面试题在构造函数中调用super(props)的目的是什么?
在super(被调用之前), 子类是不能使用this的, 在ES2015中, 子类必须在constructor中调用super(). 传递props给super()的原因则是便于(在子类中)能在constructor访问props
7.3 面试题setState的第二个参数是异步回调函数
// 按钮文案
btnText: '原按钮'
// 改变按钮的文案
changeBtnText() {
this.setState({btnText: '新文案'}, () => {
console.log(this.state.btnText)
})
}
<button onClick={this.changeBtnText.bind(this)}>{this.state.btnText}</button>
7.4 面试题为什么onClick调用方法还有通过bind(this)去调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
function Obj() {
this.username = '张三'
this.init()
}
Obj.prototype.init = function () {
console.log(this)
document.addEventListener('click', function () {
console.log(this)
})
}
new Obj()
</script>
</body>
</html>
显然第一次打印this指向Obj, 第二次就指向document
通过bind(this)This就指向Obj了
document.addEventListener('click', function () {
console.log(this.username)
}.bind(this))
通过es6箭头函数就不会改变this指向从而直接调用
document.addEventListener('click', () => {
console.log(this.username)
})
八、生命周期钩子
// 页面将要加载(不安全即将弃用)
componentWillMount () {
console.log('componentWillMount')
}
// 在组件接收到一个新的props时被调用. 这个方法在render时不会被调用(不安全即将弃用)
componentWillReceiveProps(nextProps, nextContext) {
console.log('componentWillReceiveProps',nextProps)
}
// 页面渲染完成
componentDidMount() {
// console.log(this.refs.node.innerHTML)
// console.log(document.getElementById('header'))
console.log(ReactDom.findDOMNode(document.getElementById('header')))
}
// 返回一个布尔值. false为不更新组件, true为更新, 在组件接收到新的props或者state时被调用. 在初始化时不被调用. 可以再你确认不需要更新组件时使用. 用户优化
shouldComponentUpdate(nextProps, nextState, nextContext) {
return this.state.bShow !== nextState.bShow;
}
// 组件将要更新
componentWillUpdate(nextProps, nextState, nextContext) {
console.log('componentWillUpdate',nextProps,nextState)
}
// 在组件完成更新后立即调用. 在初始化时不会被调用
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate', prevProps, prevState)
}
// 组件从dom中移除的时候立即被调用. (当离开页面的时候被调用)
componentWillUnmount() {
console.log('componentWillUnmount')
}
九、子组件给父组件传值
1.在子组件中通过props中的方法发送
<button onClick={this.props.sendParent.bind(this,'发送消息给父组件')}>发送消息给父组件</button>
2. 在父组件中通过sendParent接收消息
HeaderComponent isShow={true} sendParent={this.getChildren.bind(this)} />
效果
3. 如果子组件不需要传值可以不绑定this
<button onClick={this.props.onClick}>保存</button>
<HeaderComponent isShow={true} sendParent={this.getChildren.bind(this)} onClick={this.saveData.bind(this)} />
// 子组件保存数据
saveData() {
console.log('保存数据...')
}
效果
4. 子组件的input输入框通过onChange实现数据的双向绑定
子组件中
<input onChange={this.props.onChange}/>
父组件中
<Input onChange={(e)=>{this.setState({iptValue:e.target.value})}}/>
<br/>
{this.state.iptValue}
效果
十、插槽
1. 通过childre去接收参数
例如封装一个button组件
import React, {Component} from 'react'
class Button extends Component {
render() {
console.log(this.props.children)
return (
<React.Fragment>
<button type={this.props.type}>{this.props.children}</button>
</React.Fragment>
)
}
}
Button.defaultProps = {
type: 'button'
}
export default Button
父组件中
<form action={'http://www.baidu.com'} target={'_blank'}>
<input type="text"/>
<Button type={"submit"}>提交 </Button>
<Button type={"reset"}>重置</Button>
<Button>删除</Button>
<Button>修改</Button>
</form>
效果
注意如果插槽有多个节点childre接收的是一个数组
<Button type={"submit"}>提交 <span>123</span> </Button>
3. 利用插槽重新className和style
3.1 子组件中
import React, {Component} from 'react'
import './style.css'
class Button extends Component {
render() {
console.log(this.props.children)
return (
<React.Fragment>
<button type={this.props.type} className={'my-button '+ this.props.className} style={this.props.style}>{this.props.children}</button>
</React.Fragment>
)
}
}
Button.defaultProps = {
type: 'button'
}
export default Button
父组件中
import React from 'react'
import Button from './component/button'
import './assets/css/app.css'
class App extends React.Component {
// 构造器
constructor() {
super();
this.state = {
}
}
// 渲染dom
render() {
return (
<div className="App">
<form action={'http://www.baidu.com'} target={'_blank'}>
<input type="text"/>
<Button type={"submit"}>提交 <span>123</span> </Button>
<Button type={"reset"}>重置</Button>
<Button className={'btn-danger'} style={{height:'200px'}}>删除</Button>
<Button>修改</Button>
</form>
</div>
)
}
}
export default App;
效果
十一、 优化相关
1. React.lazy()(16.6以后的版本)
lazy(方法是用来对项目diamante进行分割, 懒加载用的. 只有当组件被加载, 内部的资源才会导入.为什么需要懒加载?)
在react的项目中import导入其他组件和库都是默认在初始直接导入的, webpack等打包工具会将import导入的文件直接合并到一个大文件中,入股哦项目很大, 打包完后初始化加载需要加载的文件会很大, 这时候就需要代码分割
2.React.Suspense()(16,6以后的版本)
Suspense的作用就是在遇到异步请求或者异步导入组件的时候等待请求和导入完成在进行渲染
3 使用lazy和suspense优化Input组件的懒加载
import React, {lazy,Suspense} from 'react'
import Button from './component/button'
import './assets/css/app.css'
const Input = lazy(()=>import('./component/Input'))
class App extends React.Component {
// 构造器
constructor() {
super();
this.state = {
iptShow: false
}
}
// 渲染dom
render() {
return (
<div className="App">
<form action={'http://www.baidu.com'} target={'_blank'}>
{this.state.iptShow &&
<Suspense fallback={<React.Fragment />}>
<Input />
</Suspense>
}
<Button type={"submit"}>提交 <span>123</span> </Button>
<Button type={"reset"}>重置</Button>
<Button className={'btn-danger'} >删除</Button>
<Button>修改</Button>
<Button onClick={()=>{this.setState({iptShow: !this.state.iptShow})}}>显示/隐藏</Button>
</form>
</div>
)
}
}
export default App;
开始js只加载了3个文件
当点击显示Input组件的时候才会加载另外一个js文件
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!