美文网首页
我的react学习

我的react学习

作者: cj_jax | 来源:发表于2019-04-19 19:07 被阅读0次

基础部分

创建一个react的项目

  • 创建一个react的项目

    全局安装 react 指令

        // 全局安装react (根据需要安装,不是必须的)
        npm i -g react // 或者 yarn -global react
    
        // 全局安装 react的脚手架 (创建react的应用,必须安装脚手架)
        npm i -g create-react-app // 或者 yarn -global create-react-app
    

    使用脚手架创建应用

    create-react-app 应用名称
    // 例如创建一个TodoList应用
    create-react-app todo-list
    

    注意点:

      1.全局安装create-react-app才能使用脚手架创建应用
      2.应用名称全部为小写字母,不能出现“TodoList”这样的名称
    

组件的使用

  • 组件的组成

        // React 是react组件必不可少的,用于支持jsx语法的模块,虽然看不到引用,但是不能少
        // Component 所有的react的组件都继承于Component,它是react组件的基类
        import React, { Component } from 'react';
    
        // TodoItem 自定义的组件
        import TodoItem from "./TodoItem"
    
        // 定义TodoList组件 ,该组件继承于基类Component
        class TodoList extends Component {
                /***
                 * constructor 当前类的构造函数
                * props 简单的理解:是父类传递的参数,例如 传递的值 或 方法,它是一个对象
                * super(props) 简单的理解是:继承父类中的传递的参数
                **/
            constructor(props){
                super(props)
                // state 是 所有react变量的仓储,简单理解就是:当前组件的变量都放在这个对象中
                this.state = {
                    inputValue: "",
                    List: []
                }
                // 使用 bind绑定this,让方法中的this永远指向当前的组件(可根据需求改变this的指向)
                this.getList =  this.getList.bind(this)
                this.inputChang = this.inputChang.bind(this)
                this.addItem = this.addItem.bind(this)
                this.delItem = this.delItem.bind(this)
            }
            // react组件必不可少的方法,return 返回的是jsx的模板,可以理解为类似html+js的模板
            render() {
                return (
                    {/*在jsx中只能有一个根标签,使用<></>(幽灵标签)包裹,既能满足jsx的语法格式,在浏览器解析时不会解析幽灵标签,减少了dom树结构节点 */}
                    <>
                        <div>
                            <input value={this.state.inputValue} onChange={this.inputChang} /> <button onClick={this.addItem}>添加</button>
                        </div>
                        <ul>
                            {this.getList()}
                        </ul>
                    </>
                );
            };
    
            // 遍历输出item
            getList() {
                ...
            }
            // 动态改变输入框的值
            inputChang( e ) {
                ...
            }
    
            // 添加item
            addItem() {
                ...
            }
    
            // 删除item
            delItem(index) {
                ...
            }
        }
        // 导出TodoList
        export default TodoList;
    
  • 认识jsx

    简单的jsx的语法

    ...
        render() {
            return (
                {/*在jsx中只能有一个根标签,使用<></>(幽灵标签)包裹,既能满足jsx的语法格式,在浏览器解析时不会解析幽灵标签,减少了dom树结构节点 */}
                <>
                    <div>
                        <input value={this.state.inputValue} onChange={this.inputChang} /> <button onClick={this.addItem}>添加</button>
                    </div>
                    <ul>
                        {this.getList()}
                    </ul>
                </>
            );
        };
    
    ...
    
    1. 在jsx中只能有一个根标签,使用<></>(幽灵标签)包裹,既能满足jsx的语法格式,在浏览器解析时不会解析幽灵标签,减少了dom树结构节点,也可以使用代码片段(Fragments ),效果和<></>相同,只是Fragments 还有更广泛的使用,后面会有详细说明

    2. 在jsx中使用注释,多行使用{/* 注释内容 */},单行使用

          // 多行
      
          {/* 多行注释内容 */}
          {/*
              多行注释内容
          */}
      
      
          // 单行
          {
              // 单行注释内容
          }
      
      
    3. 在jsx中使用组件的变量或者方法,使用{}包裹

    4. 在jsx中绑定的方法默认this指向undefined,所以需要使用bind绑定this的指向

          // 方式1: 在constructor指定this
          constructor(props){
              super(props)
              this.state = {
                  inputValue: "",
                  List: []
              }
              this.getList =  this.getList.bind(this)
              this.inputChang = this.inputChang.bind(this)
              this.addItem = this.addItem.bind(this)
              this.delItem = this.delItem.bind(this)
          }
      
          // 方式2:绑定事件的时候指定this
      
          ...
              <li onClick={this.delItem.bind(this,index)}></li>
          ...
      
      
  • 组件的基本通讯

  1. 最简单的 父 ---> 子 传值

    
    // 父组件通过在子组件标签上设置属性传递数据
        <Boy
            teacherName={ this.state.teacherName }
        />
    
        <Girl
            teacherName={ this.state.teacherName }
        />
    
    // 子组件通过this.props获取父组件传递的数据
    // this.props.teacherName 获取老师的名称
        render(){
            return (
                <>
                    <p>
                        我是{this.state.boyName},我的老师是{this.props.teacherName},
                        我对老师很
                        <button onClick={()=> this.props.say(this.state.boyName,"满意") } >
                            满意
                        </button>
                    </p>
                </>
            )
        }
    
    
  2. 最简单的 子 ---> 父 通讯

    
    // 父组件通过在子组件标签上设置属性传递数据
        <Boy
            say = { this.stuSay }
        />
    
        <Girl
            say = { this.stuSay }
        />
    // 子组件通过this.props获取父组件传递的数据
    // this.props.say 获取父组件提供的方法,通过调用父组件的方法,将传递的数据作为参数传入,当父组件的方法被调用,就通过获取当前方法参数的方式,得到了子组件传递的数据
        render(){
            return (
                <>
                    <p>
                        我是{this.state.boyName},
                        我对老师很
                        <button onClick={()=> this.props.say(this.state.boyName,"满意") } >
                            满意
                        </button>
                    </p>
                </>
            )
        }
    
    
  3. 最简单的非父子通讯

核心思路:找到共同的父组件,同时使用父组件传递的值和方法

过程有些复杂,这里省略了

teacher.js

import React,{ Component } from "react"

// 导入 Boy(男孩) 和 Girl(女孩) 组件
import Boy from "./boy"
import Girl from "./girl"

export default class Teacher extends Component {
    constructor(props){
        super(props)
        this.state = {
            teacherName: "Tom",
            stuName: "",
            stuSayContent: "",
            boyName: "",
            girlName: "",
            boySayContent: "",
            girlSayContent: ""
        }
        this.stuSay = this.stuSay.bind(this);
        this.boySaySecret = this.boySaySecret.bind(this);
        this.grilSaySecret = this.grilSaySecret.bind(this);
    }
    render(){
        let evaluation = false
        if (this.state.stuName!=="" && this.state.stuSayContent) {
            evaluation = true
        }
        return (
            <>
                <p>我是{ this.state.teacherName }老师</p>

                <div>
                    {
                        evaluation ? (<p>学生评价:{this.state.stuName}对我很{this.state.stuSayContent}</p>) : " "
                    }
                </div>

                <Boy
                    say = { this.stuSay }
                    teacherName={ this.state.teacherName }
                    boySaySecret = {this.boySaySecret}
                    girlSayContent = {this.state.girlSayContent}
                />

                <Girl
                    say = { this.stuSay }
                    teacherName={ this.state.teacherName }
                    grilSaySecret = {this.grilSaySecret}
                    boySayContent = {this.state.boySayContent}
               />
            </>
        )
    }
    stuSay(stuName,stuSayContent){
        this.setState(()=>{
            return {
                stuSayContent,
                stuName
            }
        })
    }
    boySaySecret(constent){
        this.setState(()=>{
            return {
                boySayContent : constent
            }
        })
    }
    grilSaySecret(constent){
        this.setState(()=>{
            return {
                girlSayContent : constent
            }
        })
    }
}

boy.js


import React,{ Component } from "react"

export default class Boy extends Component {
    constructor(props){
        super(props)
        this.state = {
            boyName: "龙震天"
        }
    }
    render(){
        return (
            <>
                <p>
                    我是{this.state.boyName},我的老师是{this.props.teacherName},
                    我对老师很
                    <button onClick={()=> this.props.say(this.state.boyName,"满意") } >
                        满意
                    </button>,
                    我想对女孩说:<button onClick={()=> this.props.boySaySecret("我喜欢你")}>悄悄话</button>,
                    她对我说:{this.props.girlSayContent}

                </p>
            </>
        )
    }

}

gril.js


import React,{ Component } from "react"

export default class Boy extends Component {
    constructor(props){
        super(props)
        this.state = {
            girlName: "怜香玉"
        }
    }
    render(){
        return (
            <>
                <p>
                    我是{this.state.girlName},我的老师是{this.props.teacherName},
                    我对老师很
                    <button onClick={()=> this.props.say(this.state.girlName,"不满意") } >
                        不满意
                    </button>,
                    我想对男孩说:<button onClick={() => this.props.grilSaySecret("我也是")}>悄悄话</button>,
                    他对我说:{this.props.boySayContent}
                </p>
            </>
        )
    }

}


高级部分

import React, { Component } from "react";
class Test extends Component {

render() {
  return (
  <>
    {this.props.content}
  </>
)
}
MyComponent.propTypes = {
   // 你可以将属性声明为 JS 原生类型,默认情况下
   // 这些属性都是可选的。
   optionalArray: PropTypes.array,
   optionalBool: PropTypes.bool,
   optionalFunc: PropTypes.func,
   optionalNumber: PropTypes.number,
   optionalObject: PropTypes.object,
   optionalString: PropTypes.string,
   optionalSymbol: PropTypes.symbol,

  // 任何可被渲染的元素(包括数字、字符串、元素或数组)
  // (或 Fragment) 也包含这些类型。
  optionalNode: PropTypes.node,

  // 一个 React 元素。
  optionalElement: PropTypes.element,

  // 一个 React 元素类型(即,MyComponent)。
  optionalElementType: PropTypes.elementType,

  // 你也可以声明 prop 为类的实例,这里使用
  // JS 的 instanceof 操作符。
  optionalMessage: PropTypes.instanceOf(Message),

  // 你可以让你的 prop 只能是特定的值,指定它为
  // 枚举类型。
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),

  // 一个对象可以是几种类型中的任意一个类型
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  // 可以指定一个数组由某一类型的元素组成
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 可以指定一个对象由某一类型的值组成
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  // 可以指定一个对象由特定的类型值组成
  optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
  }),
  
  // An object with warnings on extra properties
  optionalObjectWithStrictShape: PropTypes.exact({
    name: PropTypes.string,
    quantity: PropTypes.number
  }),   

  // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
  // 这个 prop 没有被提供时,会打印警告信息。
  requiredFunc: PropTypes.func.isRequired,

  // 任意类型的数据
  requiredAny: PropTypes.any.isRequired,

  // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
  // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  },

  // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
  // 它应该在验证失败时返回一个 Error 对象。
  // 验证器将验证数组或对象中的每个值。验证器的前两个参数
  // 第一个是数组或对象本身
  // 第二个是他们当前的键。
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  })
}

export default Test;
  • state 、props 、render() 之间的关系
    父组件(主组件):当组件的state 或者 props发生改变的时候。render函数就会重新执行
    子组件:当父组件的render函数运行时,它的所有子组件render函数都将重新执行。

相关文章

网友评论

      本文标题:我的react学习

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