最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    正文概述 掘金(逍遥coding)   2021-05-27   440

    一、条件渲染的三种方式

    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;
    
    
    效果如下

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    二、 点击事件

      // 在类中定义事件 改变盒子显示/隐藏
        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>
    

    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    三、父子组件传值

    1. 父组件通过属性形式传值

      {/*头部组件*/}
       <HeaderComponent  />
    

    2. 子组件通过props接收

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    3. 限制props参数类型

    3-1 引入prop-types
    import PropsType from 'prop-types'
    
    3-2 定义组件的propTypes
    HeaderComponent.propTypes = {
        title: PropsType.number
    }
    

    效果如下 定义的是数值类型, 传入的是字符串报错

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    4. 参数必填项: isRequired

    HeaderComponent.propTypes = {
        title: PropsType.string.isRequired
    }
    

    5. 参数默认值

    HeaderComponent.defaultProps = {
        title: '默认子组件值'
    }
    
      {/*头部组件*/}
       <HeaderComponent  />
    

    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    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
    
    

    效果如下

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    源码中propTypes的类型:

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    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>
    

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    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

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    通过bind(this)This就指向Obj了

       document.addEventListener('click', function () {
                    console.log(this.username)
                }.bind(this))
    

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    通过es6箭头函数就不会改变this指向从而直接调用

     document.addEventListener('click', () => {
                    console.log(this.username)
                })
    

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    八、生命周期钩子

     // 页面将要加载(不安全即将弃用) 
        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')
        }
    
    

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    九、子组件给父组件传值

    1.在子组件中通过props中的方法发送

     <button onClick={this.props.sendParent.bind(this,'发送消息给父组件')}>发送消息给父组件</button>
    

    2. 在父组件中通过sendParent接收消息

    HeaderComponent isShow={true} sendParent={this.getChildren.bind(this)} />
    
    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    3. 如果子组件不需要传值可以不绑定this

    <button onClick={this.props.onClick}>保存</button>
    
     <HeaderComponent isShow={true} sendParent={this.getChildren.bind(this)} onClick={this.saveData.bind(this)} />
      // 子组件保存数据
        saveData() {
            console.log('保存数据...')
        }
    

    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    4. 子组件的input输入框通过onChange实现数据的双向绑定

    子组件中

     <input onChange={this.props.onChange}/>
    

    父组件中

    <Input onChange={(e)=>{this.setState({iptValue:e.target.value})}}/>
    <br/>
    {this.state.iptValue}
    
    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    十、插槽

    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>
    

    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    注意如果插槽有多个节点childre接收的是一个数组

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

     <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;
    
    

    效果

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    十一、 优化相关

    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个文件

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    当点击显示Input组件的时候才会加载另外一个js文件

    react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化


    起源地下载网 » react条件渲染,循环,父子组件传值,生命周期, 插槽,React.lazy懒加载优化

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元