React学习笔记(一)

552 阅读5分钟

React和JSX语法

在 React 中使用 JSX 语法描述用户界面,它是一种 JavaScript 语法扩展。

在 React 代码执行之前,Babel 会将 JSX 语法转换为标准的 JavaScript API。

JSX 语法就是一种语法糖,让开发人员使用更加舒服的代码构建用户界面。

JSX 语法

可以在JSX中使用表达式,JSX本身其实也是一种表达式,可以将它赋值给变量,当作参数传递,作为返回值

const user = {
  name: 'tom',
  age: 10
}
const element = <h1>hello {user.name} </h1>

function userInfo () {
  return <div>{element}<div>age: {user.age}</div></div>
}

插值表达式

插值表达式中各种数据的插值状态

  • number——正常输出

  • true / false——不输出

  • undefined——不输出

  • null——不输出

  • 数组——去掉逗号后渲染在页面

  • 对象——需要调用属性名,不然会报错

    function App () {
      const booleanVal = true
      const numberVal = 10
      const nullVal = null
      const undefinedVal = undefined
      const arrayVal = [1, 2, 3, 4]
      const ObjectVal = {    name: 'tom'  }
      return (
        <div>
          <div>{booleanVal}</div> {/* 不输出 */}
          <div>{numberVal}</div> {/* 输出  10 */}
          <div>{nullVal}</div> {/* 不输出 */}
          <div>{undefinedVal}</div> {/* 不输出 */}
          <div>{arrayVal}</div> {/* 输出  1234 */}
          {/* {ObjectVal} 报错 */}
          <div>{ObjectVal.a}</div> {/* 输出  tom */}
        </div>
      )}
    

列表渲染

function test2 () {
  const arrayVal = [1, 2, 3, 4, 5]
  return (
    <ul>
      {
        arrayVal.map(item => {
          return <li>itemVal: {item}</li>
        })
      }
    </ul>
  )}

JSX中属性值为字符串类型要加上引号,属性名称最好用驼峰式命名法;属性值式Javascript表达式时,属性值不用引号,要用大括号;类名必须使用className,不能用class;JSX中的标签必须闭合,不然会报错

const element1 = <div greeting="普通属性值" ></div>
const element2 = <img src={user.avatarUrl} /> {/* 值是表达式用大括号 */}
const element3 = <input type="text" /> {/* 标签必须闭合 */}
const element4 = <div className="user-avatar round">类目属性一定要用className</div>

标签中的事件

JSX中事件的绑定涉及this的指向,需要注意

{/* 第一个参数即是事件对象 不需传递 */}
<button onClick={this.eventHandler}>按钮</button>
{/* 需要传递事件对象 */}
<button onClick={e=>this.eventHandler('arg',e)}>按钮</button>
{/* 最后一个参数即是事件对象 不需传递 */}
<button onClick={this.eventHandler.bind(null, 'arg')}>按钮</button>
{/* 绑定this的指向 */}
constructor () {
  {/* 在构造函数中将当前eventHandler进行强绑定 指向当前类组件实例 */}
  this.eventHandler = this.eventHandler.bind(this)
}
eventHandler () {}
<button onClick={this.eventHandler}>按钮</button>
{/* 另一种方式是用箭头函数 */}
addAge = ()=>{
  console.log(this)
}
<button onClick={this.addAge}>按钮</button>

组件

React中组件分为 类组件 和 函数组件

组件名称首字母必须大写,用来区分组件和普通标签

在JSX语法的外层必须有一个根元素

  1. 函数式组件
    • 函数的名称就是组件的名称
    • 函数的返回值就是组件要渲染的内容
    • 函数组件中没有this
  2. 类式组件
    • 组件类必须继承React.Component
    • 组件类必须有render方法
    • 类组件中this指向实例本身

类组件

import React, { Component } from 'react';
class App extends Component {
    constructor() {}
    render () {
        return <div>Hello, 我是类组件</div>
    }
}

函数组件

const Person = () => {
     return <div>Hello, 我是函数型组件</div>;
}

组件props传递

在调用组件时可以向组件内部传递数据,在组件中可以通过props获取外部传递进来的数据

  1. props 对象中存储的数据是只读的,不能在组件内部被修改。

  2. 当 props 数据源中的数据被修改后,组件中的接收到的 props 数据会被同步更新。( 数据驱动DOM )

    <Person name="乔治" age="20"/>
    <Person name="玛丽" age="10"/>
    
    // 类组件
    class Person extends Component {
      constructor(props) {
        super(props) // 会将props挂载到当前实例的this上
        // 这里可以拿到props 也可以用this.props
      }
      render() {
        return (
          <div>
            <div>姓名:{this.props.name}</div>
            <div>年龄:{this.props.age}</div>
          </div>
        );
      }
    }
    
    // 函数组件
    // 通过函数的参数接收props
    const Person = props => {
      return (
        <div>
          <div>姓名:{props.name}</div> 
         <div>年龄:{props.age}</div>
        </div>
      );
    }
    

设置props默认值

// 类组件
class App extends Component {
    // 作为props的默认值  和传入props重复时,传入props值覆盖
    static defaultProps = {
        defaultName: 'tom'
    }
}
// 函数组件
function ThemedButton(props) {
}
ThemedButton.defaultProps = {
  theme: "secondary",
  label: "Button Text"
}

组件children

通过props.children可以获取到在调用时填充到组件标签内部的内容(类似Vue的slot)

<Person>组件内部的内容</Person>
const Person = (props) => {
    return (
     <div>{props.children}</div> {/* 组件内部的内容 */}
    );
}

单向数据流

  1. 在React中, 关于数据流动有一条原则, 就是单向数据流动, 自顶向下, 从父组件到子组件.

  2. 单向数据流特性要求我们共享数据要放置在上层组件中.

  3. 子组件通过调用父组件传递过来的方法更改数据.

  4. 当数据发生更改时, React会重新渲染组件树.

  5. 单向数据流使组件之间的数据流动变得可预测. 使得定位程序错误变得简单.

类组件state

类组件除了能够从外部 (props) 接收状态数据以外还可以拥有自己的状态 (state),此状态在组件内部可以被更新,状态更新 DOM 更新。

组件内部的状态数据被存储在组件类中的 state 属性中,state 属性值为对象类型,state 这个属性名称固定不可更改。

class App extends Component {
  constructor () {
    super()
    this.state = {
      person: { name: '张三', age: 20 },
    }
  }
  render () {
    return (
      <div>
        {this.state.person.name}
        {this.state.person.age}
      </div>
    );
  }
}

更改组件状态

state 状态对象中的数据不可直接更改,如果直接更改 DOM 不会被更新,要更改 state 状态数据需要使用 setState方法。

class App extends Component {
  constructor () {
    this.state = {
      person: { name: '张三', age: 20 },
    }
    this.changePerson = this.changePerson.bind(this)
  }
 changePerson () {
    this.setState({
      person: {
        name: '李四',
        age: 15
      }
    })
  }
  render() {
    return (
      <div>
        {this.state.person.name}
        {this.state.person.age}
        <button onClick={this.changePerson}>按钮</button>
      </div>
    );
  }
}

state和props区别

  1. state 的主要作用是用于组件保存、控制、修改 自己 的可变状态,在组件内部进行初始化,也可以在组件内部进行修改,但是组件外部不能修改组件的 state
  2. props 的主要作用是让使用该组件的父组件可以传入参数来配置该组件,它是外部传进来的配置参数,组件内部无法控制也无法修改 
  3. state 和 props 都可以决定组件的外观和显示状态。通常,props 做为不变数据或者初始化数据传递给组件,可变状态使用 state