美文网首页
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