美文网首页
react语法结构

react语法结构

作者: 光头小青蛙 | 来源:发表于2019-09-29 10:29 被阅读0次

    1.react JSX语法原理

    • react是函数式编程,使用jsx语法来渲染组件。jsx语法是合法的JavaScript代码,看上去和我们平常写的html代码差不多,只不过html代码片段写在了JavaScript里面,这就是jsx语法。
    class Header extends Component {
      render () {
        return (
          <div>
            <h1>React 小书</h1>
          </div>
        )
      }
    }
    ReactDOM.render(
      <Header />,
      document.getElementById('root')
    )
    
    • javascript中,每一个DOM元素都可以用JavaScript对象来表示,一个DOM元素一般包含标签名,属性,样式,子元素或内容,这些都可以用合法的JavaScript语法来表示。这个看起来就和vuerender函数一样了,其实vue的render函数也是借鉴了reactjsx语法。我们在写的时候是以标签的形式写的,react.js会自动编译成下面的JavaScript对象来表示,两者表示的结构和信息是一致的。
    • 所谓的jsx就是JavaScript对象,看到这种代码结构的时候,大概就明白这是一个怎样的过程。
    • 通常渲染react组件,先从jsx结构开始,编译成JavaScript结构,然后渲染成DOM结构,再插入到页面。

    为什么要有JavaScript这一层,就是因为,在转换的时候,可能不是转换成DOM可能是转换成react -app(react-native),所以会有JavaScript这一层作中转。

    <div class='box' id='content'>
      <button>Click</button>
    </div>
    {
      tag: 'div',
      attrs: { className: 'box', id: 'content'},
      children: [
        {
          tag: 'button',
          attrs: null,
          children: ['Click']
        }
      ]
    }
    

    2.组件render方法

    • render函数返回jsx结构,类似于vuetemplate,也是必须有一个唯一顶级元素包裹;
    • 也可以使用<Fragment> 标签,并列展示多个同级标签而不报错,使用需要引用。
    • jsx结构可以插入JavaScript表达式,需要用{ }包裹起来,表达式的结果会渲染到页面,{ }里面可以放任何的表达式,包括jsx结构。jsx也能像普通元素那样赋值,能够作为参数传递。
    import React, { Component ,Fragment} from 'react';
    
    render () {
      const badWord = <span> is not good</span>
      return (
        <div>
          <h1>
            React 小书
            {badWord}
          </h1>
        </div>
      )
    }
    

    3.组件嵌套

    • 定义一个组件,可以在别的组件里面嵌套,就像使用普通的标签一样,和vue的组件使用类似。多个组件的嵌套就组成了组件树。

    注意自定义组件必须要使用大写的字母开头。

    class Title extends Component {
      render () {
        return (
          <h1>React 小书</h1>
        )
      }
    }
    class Header extends Component {
      render () {
        return (
          <div>
            <Title />//嵌套组件
          </div>
        )
      }
    }
    

    4.事件绑定

    • react.js监听事件形式和原生事件更吻合,也是通过onClickonChange等事件名前面加on,这点和vue不同,vue是通过@click事件名前面加@来绑定事件。
    • 绑定的事件需要写在组件内部,用{}包裹起来,通过on实现的事件绑定,只能用在普通的html标签,而不能用于组件标签。
    • 绑定的事件也会有event对象,只不过react.jsevent对象进行了封装,提供统一的api
    • 在事件里面不能通过this访问到当前的实例对象,需要使用bind把实例方法绑定到当前实例上,然后在函数内部就能够访问 this实例,在调用的使用不影响传参。
    class Everything extends Component{
      bodyClick(){
      console.log(this)
    }
    render(){
        return (
            <div onClick={this.bodyClick.bind(this)} className="Header" style={bodyStyle}>
              我是身体
          </div>
    )
    }
    

    4.类名ID样式设置

    • react.js的类名不能直接在标签内使用class来设置,需要使用className来设置类名,id是可以直接设置。
    • 一些自定义的属性名也可以直接在标签内设置,
    • 设置css样式不能直接写在行内,可以使用类名,id外部映入的css文件设置样式,行内样式可以使用变量的形式来设置。或者使用双引号包裹,以json的形式书写。
    • label标签绑定for的时候不能直接使用for,必须使用htmlFor

    react.js在解析的时候遇见<会解析为html,遇见{会以javascript解析。所以不能放在""里面。

    class Body extends Component {
      render() {
        let bodyStyle={
          color:"blue",
          height:"100px",
          fontSize:"20px",
          lineHeight:"100px"
        }
        return (
          <div data-name="der" id="der"  className="Header" style={bodyStyle}>
              <h1 style={{fontSize:"50px"}}>today</h1>
          </div>
        );
      }
    }
    

    5,组件state状态设置

    • 每一个组件都会有一个自己的数据状态(state),类似于vuedata,用来存储组件的数据状态。
    • 设置state状态在construstor里面设置,constructor方法是es6类的默认方法,一个类必须要有一个constructor方法,默认返回实例对象(this)。
    • 改变state是使用setState方法,它接受一个对象或者一个函数作为参数,作为一个对象的时候,传入更改的部分即可,但是会有一个问题,调用setState并不会立即执行,所以在改变state的函数里面打印的还是旧的值,但是新的值已经渲染到页面。
    • 函数作为setState的参数的时候,有时候在函数里面需要使用改动之后的值,就得用函数作为参数
      constructor(){
        super()
        this.x=123;
        this.y=123;
        this.state={
          name:"xiaoming",
          flag:false
        }
      }
      bodyClick(e){
        this.setState({
          name:"123",
          flag:!this.state.flag
        })
        this.setState((prevState)=>{
        console.log(prevState)//name:123,flag:true可以获取到改动之后的值。
        })
      }
    

    6,props组件传参

    • 使用propsvue的差不多,只不过reactprops不需要v-bind,直接按照标签属性的格式书写就行。
    • 在接收props的组件内通过this.props.参数名来访问传进来的参数,传进来的参数在接收组件内是无法更改的,只能在传入组件更改。
    • props可以传出的参数类型包括对象,数组,函数,等类型,
    • props也可以像vue设置默认值,不传的时候使用默认值。
    • props传的是和render同级的函数时需要bind(this),确定this指向。
    class Body extends Component {
      bodyClick(e){
        console.log(this.props)
        if(this.props.fun){
          this.props.fun();
        }
      }
        static defaultProps = {//设置默认值
            title: '取消',
            unlikedText: '点赞'
        }
      render() {
        return (
          <div    onClick={this.bodyClick.bind(this)} className="Header">
            <h1>{this.props.content.name}{this.props.title?this.props.title:"failed"}</h1>
          </div>
        );
      }
    }
    class App extends Component {
      render() {
        return (
          <div className="App">
          <Body der={['123']} fun={()=>{console.log("传了个函数")}} content={{name:"name"}} title="props标题"></Body>
          </div>
        );
      }
    }
    

    7.列表数据渲染

    • react的数据渲染没有vue那么的方便,一个v-for就可以搞定了,react数据渲染有多种方式,第一种是手动for循环,第二种使用map方法,
    • react数据循环也需要一个唯一标志符key
    第一种
    class Other extends Component{
        render(){
            let arr=['第一页','第一页','第一页','第一页','第一页','第一页','第一页','第一页',]
            let array=[]
            arr.forEach((item,index)=>{
               array.push( <div   className={index===0?'navActive menu-list':'menu-list'} key={index}>{item}</div>)
          })
            return (
                <div className="left-menu-wrapper">
                    { array}
                </div>
            )
        }
    }
    第二种
    class Other extends Component{
        render(){
            let arr=['第一页','第一页','第一页','第一页','第一页','第一页','第一页','第一页',]
            let array=arr.map((item,index)=>{
                  return   <div   className={index===0?'navActive menu-list':'menu-list'} key={index}>{item}</div>
            })
            return (
                <div className="left-menu-wrapper">
                    { array}
                </div>
            )
        }
    }
    第三种
        render(){
            let arr=['第一页','第一页','第一页','第一页','第一页','第一页','第一页','第一页',]
                return (
                    <div className="left-menu-wrapper">
                        {
                            arr.map((item,index)=>{
                                return   <div  onClick={this.navTab} className={index===0?'navActive menu-list':'menu-list'} key={index}>{item}</div>
                            })
                        }
                    </div> 
                )
        }
    

    8.生命周期

    • react在组件渲染并插入到页面会有一个生命周期,和vue的生命周期类似。可以像render一样定义在组件的内部。
    • contrustor组件内部的状态初始化都是在这里面进行,state也是放在了里面。
    • componentWillMountrender函数之前调用。
    • componentDidMountrender函数调用之后调用。
    • componentWillUnmount组件删除的时候调用。
    • componentWillUpdate组件重新渲染时开始调用。
    • componentDidUpdate组件更新完毕时调用。
    • componentWillReceiveProps props改变时调用。
    • shouldComponentUpdate控制组件是否重新渲染。
    class Toder extends Component{
        constructor(){
            super();
            this.contentArr=[];
            this.state={
                contentArr:[]
            }
        }
        UNSAFE_componentWillReceiveProps(nextProps){
            console.log("props改变")
        }
        UNSAFE_componentWillMount(){
            console.log("组件开始渲染")
        }
        UNSAFE_componentWillUpdate(){
            console.log("组件重新渲染")
        }
        UNSAFE_componentDidUpdate(){
            console.log("组件重新渲染完毕")
        }
        componentWillUnmount(){
            console.log("组件销毁")
        }
        render(){
            return (
                <div className="comment-wrapper">
                </div>
            )
        }
    }
    

    9.DOM操作

    • 虽然react提供了很多的方法进行事件监听,有些功能的实现避免不了DOM的操作,所以需要使用ref来操作DOM
    • ref为回调函数的时候,函数的参数就是当前的DOM,当元素挂载完成之后,就会执行函数。
    • ref为字符串的时候可以通过this.refs.字符串访问DOM
    • 可以给html标签加ref,也可以给组件加ref
    • 一般不提倡操作DOM
    函数
    <button ref={(dom)=>{console.log(dom)}} >点击</button>
    字符串
     <div ref="ggg" className="comment-wrapper">
     </div>
    

    10.容器类组件

    • 容器类组件顾名思义就是将一个组件当做一个容器,动态的向里面插入内容。
    • 实现原理就是通过props向容器组件传入html标签结构,在容器组件内通过this.props渲染出来,传入的html结构可以访问到定义props组件的state,也能触发方法。这样通过一个容器组件就能复用很多的代码,
    定义props组件
    class Body extends Component {
      constructor(){
        super();
        this.state={
          title:"123"
        }
      }
      btnClick(){
        console.log(this.state)
      }
      render() {
        let content=<div>
            <input placeholder="请输入内容" type="text"/>
            <button onClick={this.btnClick.bind(this)}>删除</button>
        </div>
        return (
          <div className="body-container">
            <Toder content={content} title={this.state.title}></Toder>
          </div>
        );
      }
    }
    容器组件
    class Toder extends Component{
        constructor(){
            super();
            this.contentArr=[];
            this.state={
                contentArr:[]
            }
        }
        UNSAFE_componentWillMount(){
            console.log(this.props.content.props)
        }
        render(){
            return (
               <div>
                    <div style={{backgroundColor:"skyblue"}}>{this.props.content.props.children[0]}</div>
                    <div style={{backgroundColor:"pink"}}>{this.props.content.props.children [1]}</div>
               </div>
            )
        }
    }
    
    

    11.渲染html字符串

    • react里面要渲染一个类似于html的字符串是会转义,防止xss攻击,所以要讲字符串以html标签的形式渲染出来,需要使用dangerouslySetInnerHTML.

    注意标签中间不能有任何内容包括空格和换行。

        render(){
            return (
                <div dangerouslySetInnerHTML={{__html: this.state.text}}></div>
            )
        }
    

    12. 验证props

    • 验证props是非常有必要的,大项目开发能少走很多弯路。
    • 验证props 使用react自带的prop-types,可以验证传的props的数据类型,以及是否必须传值。
    • isRequired表示必须传值。
    • 常用的验证数据类型有number,string,boolean,object
    先引入
    import PropTypes from "prop-types"
    再设置验证
    class Item extends Component {
        constructor(){
            super()
            this.state={
    
            }
        }
        handleClick(){
            this.props.delItem(this.props.index)
        }
        render() { 
            return ( 
                <li onClick={this.handleClick.bind(this)}>{this.props.item}</li>
             );
        }
    }
    Item.propTypes={
        index:PropTypes.number.isRequired
    }
    

    相关文章

      网友评论

          本文标题:react语法结构

          本文链接:https://www.haomeiwen.com/subject/ruffpctx.html