React学习--- 组件

React学习— 组件

1.组件的创建方式

函数式组件

特别注意这里的写法,如果要在 JSX 里写 js 表达式(只能是表达式,不能是流程 控制语句),就需要加 {},包括注释也是一样,并且可以多层嵌套

// 函数式组件
// 写组件模板的时候必须遵循jsx语法
function App() {
    
    
  return (
    <div className="App">
      hello reactjs
    </div>
  );
}

class组件

ES6 的加入让 JavaScript 直接支持使用 class 来定义一个类,react 的第二种创建组件 的方式就是使用的类的继承,ES6 class 是目前官方推荐的使用方式,它使用了 ES6 标准 语法来构建

// class组件
// 注意:组件名必须首字母大写(为了和普通标识符区分开),必须继承自 React.Component 组件
// class的好处就是可以在render并列的位置
// class组件中,使用的this是当前组件实例
// App这个组件必须继承自React.Component
class App extends React.Component {
    
    
  // App这个组件要想渲染什么由内部的render方法决定,必须要有render方法,这个render方法负责渲染组件的模板就是有什么标签
  // js中如果return后面没有语句就会自动加分号
  // 当想要使用插件时得改变 组件文件名的后缀改为jsx
  // 定义组件状态state,组件数据

  // 在constructor函数中对组件状态进行初始化
  constructor(props) {
    
    
    super(props)
    this.state = {
    
    //初始化组件状态
      count: 100,
      arr: ['nodejs', 'react', 'vue.js']
    }

  }
  // state = 100

  // state = {
    
    
  //   count: 100,
  //   arr: ['nodejs', 'react', 'vue.js']
  // }

  render() {
    
    //render中必须return返回 组件模板
    return (
      <div className="App">
        <h1>{
    
    this.state.count}</h1>
        <h1>{
    
    this.state.arr}</h1>
      </div>
    );
  }
}

2.组件命名规范

组件名称必须以大写字母开头。

<Welcome name="james">

小驼峰命名来定义属性

<Welcome className="blue" tabIndex="1" >

3.组件传值props

函数组件通过参数 props 接收外部组件传入的数据, 在组件内根据 props 处理 UI

传递值:

<Header id="1001" url="http://xxx.com"></Header>

接收值(函数式组件)

函数式组件用参数 props 接收值

function Header ( props ){
    
    
 return (
 <div className="header">
 {
    
    /* 组件模板中使用 组件的属性 */}
 <h1>{
    
    props.id},{
    
    props.url}</h1>
 </div>
 )
}

类组件中处理props

类组件通过this.props接收外部组件传入的数据,在组件内根据this.props处理UI

接收值(class组件)

class 组件内部用 this.props 接收值

class Header extends React.Component{
    
    
render(){
    
    
 return (
 <div className="header">
 {
    
    /* 组件模板中使用 组件的属性 */}
 <h1>{
    
    this.props.id},{
    
    this.props.url}</h1>
</div>
 )
 }
}

子组件:

import React, {
    
     Component } from 'react';

class Child extends Component {
    
    
    handleClick() {
    
    
        // this.props.title = 'state'; //props是只读的.
    }
    render() {
    
    
        return (
            <div className="child">
                {
    
    this.props.title}{
    
    this.props.count}
                <button onClick={
    
    () => {
    
     this.handleClick() }}>更改</button>
            </div>
        );
    }
}

export default Child;

父组件中

<Child title="今天学习props" count={
    
    100} />

注意

<></> 原名是<Fragment>可以省略,充当的是一个包裹元素(包裹其他标签), 最终在页面中不会渲染.

4.组件样式sass

在react组件中,使用sass编写组件样式,需要依赖sass插件。

使用步骤:

  1. 下载插件

    npm i sass -D

  2. 创建.scss文件,编写sass代码

  3. 在组件中引入scss文件

    import './App.scss';

5.组件的生命周期函数

主文件

import './App.css';
import Child from './Child';
//react中存在两种形式的组件: 函数式组件, 类组件
//使用 rcc 快速创建 类组件  ( 主要使用这个 )
//使用 rsf 快速创建 函数式组件

import React, {
    
     Component } from 'react';

class App extends Component {
    
    
  // 挂载期(挂载期的方法会自动执行,而且只执行一次)
  constructor(props) {
    
    //这个函数会在组件挂载前就执行,组件并没有显示在页面上
    super(props);
    console.log('constructor');
    this.state = {
    
    }//初始化组件状态
  }
  componentWillMount() {
    
    //挂载前
    console.log('componentWillMount 将要挂载');
  }
  componentDidMount() {
    
    //挂载完成,组件就会显示在页面上
    console.log('componentDidMount 挂载完成');
    // 在这里发送网络请求,创建定时器,事件监听,理由是:这个方法只执行一次,而且会自动执行
    // 这里的this指的是组件实例this.timerid就是将定时器保存在当前组件实例身上,就可以在各个组件生命周期共享
    // 还可以直接保存在组件状态中,只不过保存在组件状态中定时器是可以改变的,如果不变化就可以保存在组件实例身上
    this.timerid = setInterval(() => {
    
    
      console.log('定时器在执行');
    }, 1000)
  }

  // 更新期(更新期的方法可能会反复调用执行)
  // 性能优化时写的地方
  shouldComponentUpdate(nextProps, nextState) {
    
    //控制组件是否更新,目的是提示组件性能(性能优化)
    // 组件性能优化:把有效的更新进行更新,无效的更新就不让它进行更新
    // 组件状态是否有变化,如果有变化就更新,没有变化就不更新
    // 当setState中的数据和state中的数据相等没有必要更新

    // if (this.state == nextState) {
    
    
    // 满足条件就不更新,传进来的state是两个对象,当每次更新的时候对象所指的地址都是不一样的,所以不能直接比较,要将对象转换为字符串进行比较
    if (JSON.stringify(this.state) == JSON.stringify(nextState)) {
    
    
      return false;
    } else {
    
    
      return true;//返回false 表示放弃更新,返回true 表示继续更新
    }
  }

  componentWillReceiveProps(nextProps) {
    
    //Props更新,才会执行(可以用这个函数来监听Props的变化)
    // nextProps 是最新的数据的对象
    // 用这个函数监听父组件传来的数据是否有变化
    console.log('componentWillReceiveProps 将要更新');
  }
  componentWillUpdate() {
    
    
    console.log('componentWillUpdate 将要更新');
  }
  componentDidUpdate() {
    
    
    console.log('componentDidUpdate 更新完成');
  }

  // 卸载期
  componentWillUnmount() {
    
    
    console.log('componentWillUnmount 将要卸载');
    // 在这里释放所占用的资源(网路请求,定时器,事件监听)
    clearInterval(this.timerid);
  }

  // render方法在组件初次渲染时会执行一次,在之后的组件每次更新时都会执行一次
  render() {
    
     //渲染组件模板到视图
    return (
      <div>
        <h1 className="class" id="big" onClick={
    
    () => {
    
     this.handleClick() }}>hello reactjs</h1>
        {
    
    /* 父组件先更新更新的时候子组件变化子组件更新子组件更新完父组件才更新完成 */}
        <Child title={
    
    this.state.count} />
      </div>
    );
  }

  handleClick() {
    
    //组件状态
    this.setState({
    
     count1 });
  }
}

export default App;

子文件

import React, {
    
     Component } from 'react';

class Child extends Component {
    
    

    // 挂载期(挂载期的方法会自动执行,而且只执行一次)
    constructor(props) {
    
    //这个函数会在组件挂载前就执行,组件并没有显示在页面上
        super(props);
        console.log('constructor');
        this.state = {
    
    }//初始化组件状态
    }

    componentWillReceiveProps(nextProps) {
    
    //Props更新,才会执行(可以用这个函数来监听Props的变化)
        // nextProps 是最新的数据的对象
        // 用这个函数监听父组件传来的数据是否有变化
        // 传过来的值是新的就会执行,传过来的值不是新的就不会执行
        // 这里传过来的数据是一个对象,要将对象转换为字符串进行比较,因为对象每次更新地址都会变化,只是值不变
        console.log('Child componentWillReceiveProps 将要更新');
    }
    componentWillUpdate() {
    
    
        console.log('Child componentWillUpdate 将要更新');
    }
    componentDidUpdate() {
    
    
        console.log('Child componentDidUpdate 更新完成');
    }
    render() {
    
    
        return (
            <div>

            </div>
        );
    }
}

export default Child;

6.受控组件 —— 表单处理

特别说明:HTML中表单元素是可输入的,也就是有自己的可变状态,但是默认表单元素的值不受所在组件state的控制,也就是表单元素所在组件无法实时获取最新的表单元素值

6.1非受控组件

表单元素值不受所在组件状态的控制,我们将这样的表单元素称为:非受控组件

6.2受控组件

受控组件:值受到React组件状态控制的表单元素

一般是通过defaultValue属性,onChange事件配合将非受控组件变为受控组件

  1. 文本框、富文本框、下拉框操作value属性
  2. 复选框操作checked属性
import './App.css';

//react中存在两种形式的组件: 函数式组件, 类组件
//使用 rcc 快速创建 类组件  ( 主要使用这个 )
//使用 rsf 快速创建 函数式组件

import React, {
    
     Component } from 'react';

class App extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    this.state = {
    
    
      phone: '',
      isRead: false//是否勾选协议
    }
  }
  handleChange(e) {
    
    
    this.setState({
    
    
      phone: e.target.value
    }, () => {
    
    
      console.log(this.state);
    })
  }
  handleChecked(e) {
    
    
    this.setState({
    
    
      isRead: e.target.checked
    }, () => {
    
    
      console.log(this.state);
    })
  }
  render() {
    
     //渲染组件模板到视图
    return (
      <div>
        {
    
    /* 非受控元素变成受控元素,通过value和onChange绑定实现 */}
        {
    
    /* value绑定,将组件状态绑定到元素的value属性 */}
        {
    
    /* onChange绑定,当元素的值发生改变时更新元素的值到组件状态 */}
        <input type="text" value={
    
    this.state.phone} onChange={
    
    (e) => {
    
     this.handleChange(e) }} placeholder='请输入手机号' />
        <input type="checkbox" value={
    
    this.state.isRead} onChange={
    
    (e) => {
    
     this.handleChecked(e) }} />
      </div>
    );
  }
}

export default App;

6.3多表单元素操作

  1. 给表单元素添加name属性,名称与state相同
  2. 根据表单元素类型获取对应值
  3. 在change事件处理程序中通过[name]来修改对应的state
import './App.css';

//react中存在两种形式的组件: 函数式组件, 类组件
//使用 rcc 快速创建 类组件  ( 主要使用这个 )
//使用 rsf 快速创建 函数式组件

import React, {
    
     Component } from 'react';

class App extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    this.state = {
    
    
      phone: '',
      pass: '',
      isRead: false//是否勾选协议
    }
  }
  handleChange(e) {
    
    
    // 获取目标控件input元素对应的别名
    // e.target.name
    this.setState({
    
    
      // 因为别名是个变量,所以用方括号括起来
      // 如果是单选。复选框,通过e.target.checked取值
      // 如果是其它元素,通过e.target.value取值
      [e.target.name]: ((e.target.type == 'checkbox' || e.target.type == 'radio') ? e.target.checked : e.target.value)
    }, () => {
    
    
      console.log(this.state);
    })
  }

  login() {
    
    
    // 发送登录请求
    // 删除里面没有用的或者取出有用的传过去
    // 这样直接删除会影响之前的解决方法是深拷贝
    // delete this.state.isRead;

    // 深拷贝state
    var newState = JSON.parse(JSON.stringify(this.state));
    delete newState.isRead;
    console.log(newState);
    // user_login(this.state).then((res)=>{
    
    

    // })
  }

  render() {
    
     //渲染组件模板到视图
    return (
      <div>
        {
    
    /* 非受控元素变成受控元素,通过value和onChange绑定实现 */}
        {
    
    /* value绑定,将组件状态绑定到元素的value属性 */}
        {
    
    /* onChange绑定,当元素的值发生改变时更新元素的值到组件状态 */}
        <input type="text" name="phone" value={
    
    this.state.phone} onChange={
    
    (e) => {
    
     this.handleChange(e) }} placeholder='请输入手机号' /><br />
        <input type="password" name="pass" value={
    
    this.state.pass} onChange={
    
    (e) => {
    
     this.handleChange(e) }} placeholder='请输入密码' />
        <input type="checkbox" name="isRead" value={
    
    this.state.isRead} onChange={
    
    (e) => {
    
     this.handleChange(e) }} />
      </div>
    );
  }
}

export default App;

猜你喜欢

转载自blog.csdn.net/m0_53181852/article/details/127820441
今日推荐