草庐IT

React面向组件编程(上)

程序员--韩同学 2023-11-08 原文

文章目录

前言:

  • React组件中默认封装了很多属性,有的是提供给开发者操作的,其中有三个属性非常重要:state、props、refs。通过这三大核心属性的使用,我们能够实现对组件的状态进行更新。

一,组件的基本理解和使用

1. 函数组件

 <script type="text/babel">
        function MyComponent() {  
            return <h2>我是函数定义的组件(适用于简单组件的定义)</h2>
        }
        ReactDOM.render(<MyComponent />, document.getElementById('test'))
    </script>

函数组件的渲染过程

 1.React解析了组件标签,找到了对应的组件
 2.发现这个组件是一个函数定义的,随后调用该函数,生成一个虚拟dom
 3.最后将虚拟dom转化成为真实dom,呈现在页面中

2. 类式组件

<script type="text/babel">
        class MyComponent extends React.Component {
            render() {
                return <h2>我是类定义的组件适用于复杂数据类型</h2>
            }
        }
        ReactDOM.render(<MyComponent />, document.getElementById('test'))
    </script>

类式组件的渲染过程

1.React解析了组件标签,找到了对应的组件
2.发现这个组件是一个类定义的,随后new出来一个实例对象,并通过该实例调用原型上的render方法
3.将render()返回的内容生成一个虚拟dom
4.最后将虚拟dom转化成为真实dom,呈现在页面中

3.组件的注意事项

组件名必须首字母大写
虚拟DOM元素只能有一个根元素
虚拟DOM元素必须有结束标签

二,组件的三大核心属性

1.state

  • state 是一个对象,它包含组件的数据状态,当状态变化时,会触发视图的更新。你可以理解它的作用跟 Vue 中的 data 对象类似。
<script type="text/babel">
        class Weather extends React.Component {
            constructor() {
                super()
                this.state = {
                    isHot: false,
                    wind: '微风'
                }
                this.chang = this.chang.bind(this)
            }
            render() {
                let { isHot, wind } = this.state
                return <h2 onClick={this.chang}>今天的天气很 {isHot ? "炎热" : "凉爽"},{wind}</h2>
            }hang() {
                console.log(this)
                this.setState({
                    isHot: !this.state.isHot
                })
            }
        }
        ReactDOM.render(<Weather />, document.getElementById('test'))
    </script>

1. 注意事项

1.组件中render方法中的this为组件实例对象
2.组件自定义的方法中this为undefined,如何解决?
	1.强制绑定this: 通过函数对象的bind()
	2.箭头函数
3.状态数据,不能直接修改或更

2.简写方式

<script type="text/babel">
        class Weather extends React.Component {
           state = {
                    isHot: false,
                    wind: '微风'
                }

            render() {
                let { isHot, wind } = this.state
                return <h2 onClick={this.chang}>今天的天气很 {isHot ? "炎热" : "凉爽"},{wind}</h2>
            }

            chang = ()=>{  
                this.setState({
                    isHot: !this.state.isHot//这里的修改是一种合并,对比属性的变化,如果有赋新值,没有则跳过
                })
            }
        }
        ReactDOM.render(<Weather />, document.getElementById('test'))
        let a = new Weather()
</script>

设置状态:setState

setState(object nextState[, function callback])

不能在组件内部通过 this.state 修改状态,因为该状态会在调用 setState() 后被替换。

setState() 并不会立即改变 this.state,而是创建一个即将处理的 statesetState() 并不一定是同步的,为了提升性能 React 会批量执行 stateDOM 渲染。

setState() 总是会触发一次组件重绘,除非在 shouldComponentUpdate() 中实现了一些条件渲染逻辑。


2.props

  • React 中组件通过 props 属性接收外部传入的数据,这点 Vue 跟 React 是一致的
  • react 中说的单向数据流值说的就是 props,根据这一特点它还有一个作用:组件之间的通信
  • props 本身是不可变的,但是有一种情形它貌似可变,即是将父组件的 state作为子组件的 props,当父组件的 state 改变,子组件的 props 也跟着改变,其实它仍旧遵循了这一定律:props 是不可更改的
<script type="text/babel">
  class MyComponent extends React.Component {
    render() {
      return (
        <ul>
          <li>{this.props.name}</li>
          <li>{this.props.age}</li>
        </ul>
      );
    }
  }
  ReactDOM.render(
    <MyComponent name="Bob" age="18" />,
    document.getElementById("test")
  );
</script>

props的特点:

  1. 每个组件对象都会有props(properties的简写)属性
  2. 组件标签的所有属性都保存在props中
  3. 内部读取某个属性值:this.props.propertyName
  4. 作用:通过标签属性从组件外 向组件内传递数据(只读 read only)
  5. 对props中的属性值进行类型限制和必要性限制

对props进行限制

  1. 引入 prop-type 库,这就是专门用于限制 props 属性的一个库
  2. 导入 prop-type 库,到当前页面
  3. 根据 Person.propTypes = {} 进行限制
class MyComponent extends React.Component {
  render() {
    return (
      <ul>
        <li>{this.props.name}</li>
        <li>{this.props.age}</li>
      </ul>
    );
  }
}

// 校验类型
MyComponent.propTypes = {
  name: PropTypes.string, // 这里的 PropTypes 变量是全局挂载的
  age: PropTypes.number,
};

ReactDOM.render(
  <MyComponent name="Bob" age={18} />,
  document.getElementById("test")
);

props的简写

<script type="text/babel">
        class Weather extends React.Component {
            constructor(props) {//是否接受,取决于是否使用外部数据
                super(props)//只能上面接受了props,super()就去传递,否则后续的使用,可能就会出现问题
            }
            static propTypes = {
                name: PropTypes.string.isRequired,//限制name为字符串类型,必填
                // age: PropTypes.number,
                sex: PropTypes.string,
                speak: PropTypes.func
            }
            static defaultProps = {
                sex: '男',
            }
            render() {
                let { name, age, sex } = this.props
                return (
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age + 1}</li>
                    </ul>
                )
            }
        }
     ReactDOM.render(<Weather name="tom" age={26} sex="女" />, document.getElementById('test'))

</script>

函数组件使用props

<script type="text/babel">
  // 函数组件
  function MyComponent(props) {
    return (
      <ul>
        <li>{props.name}</li>
        <li>{props.age}</li>
      </ul>
    );
  }
  // 校验类型
  MyComponent.propTypes = {
    name: PropTypes.string,
      age: PropTypes.number,
  };

  ReactDOM.render(
    <MyComponent name="Bob" age={18} />,document.getElementById("test")
  );
</script>

3.ref

  • React 中的 Refs 可以让我们访问 DOM 节点,它有三种使用方式:字符串方式回调函数式createRef
  • 在 React 中 Refs 提供了一种方式,允许用户访问DOM 节点或者在render方法中创建的React元素
  • 在 React单项数据流中,props是父子组件交互的唯一方式。要修改一个子组件,需要通过的新的props来重新渲染。
    但是在某些情况下,需要在数据流之外强制修改子组件。被修改的子组件可能是一个React组件实例,也可能是一个DOM元素。对于这两种情况,React 都通过 Refs的使用提供了具体的解决方案。

字符串方式

<script type="text/babel">
  class MyComponent extends React.Component {

    handleAlert = () => {
      // 在 refs 中获取定义的 ref 标识
      const { myInput } = this.refs;
      console.log(myInput); // <input type="text">
      alert(myInput.value);
    };

    render() {
      return (
        <div>
          {/* 使用 ref="" 方式直接定义字符串标识  */}
          <input ref="myInput" type="text" />
          <button onClick={this.handleAlert}>alert</button>
        </div>
      );
    }
  }

  ReactDOM.render(<MyComponent />, document.getElementById("test"));
</script>

回调函数方式

<script type="text/babel">
  class MyComponent extends React.Component {
    
    handleAlert = () => {
      // 直接从组件实例上获取 myInput
      console.log(this.myInput); // <input type="text">
      alert(this.myInput.value);
    };

    render() {
      return (
        <div>
          {/* ref 直接定义成一个回调函数,参数就是节点本身,将它赋值给组件的一个 myInput 属性 */}
          <input ref={(ele) => (this.myInput = ele)} type="text" />
          <button onClick={this.handleAlert}>alert</button>
        </div>
      );
    }
  }

  ReactDOM.render(<MyComponent />, document.getElementById("test"));
</script>

React官方提示:

如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。

createRef -官方推荐使用

<script type="text/babel">
  class MyComponent extends React.Component {
    // 创建 ref
    myInput = React.createRef();

    handleAlert = () => {
      console.log(this.myInput.current); // 这里需要注意,元素是在 current 属性上
      alert(this.myInput.current.value);
    };

    render() {
      return (
        <div>
          {/* 将创建好的 ref 附加到元素上 */}
          <input ref={this.myInput} type="text" />
          <button onClick={this.handleAlert}>alert</button>
        </div>
      );
    }
  }

  ReactDOM.render(<MyComponent />, document.getElementById("test"));
</script>

上面就是使用 React.createRef() 方法创建 ref 的方式,特别需要注意的是,创建出来的 ref 的值是一个对象,我们需要的 DOM 元素是放在对象的 current 属性上,如上面的 this.myInput.current。

总结

以上就是React面向组件编程中的一部分。希望本篇文章能够帮助到你,若有错误欢迎指出,不懂得可以评论区或者私信问我,我也会一 一解答。谢谢观看!
我的其他文章:https://blog.csdn.net/m0_60970928?type=blog

有关React面向组件编程(上)的更多相关文章

  1. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  2. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  3. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  4. ruby - 如何以编程方式删除实例上的 "singleton information"以使其编码(marshal)? - 2

    我创建了一个由于“在运行时执行的单例元类定义”而无法编码的对象(这段代码的描述是否正确?)。这是通过以下代码执行的:#defineclassXthatmyusesingletonclassmetaprogrammingfeatures#throughcallofmethod:break_marshalling!classXdefbreak_marshalling!meta_class=class我该怎么做才能使对象编码正确?是否可以从对象instance_of_x的classX中“移除”单例组件?我真的需要一个建议,因为我们的一些对象需要通过Marshal.dump序列化机制进行缓存。

  5. Ruby 元编程问题 - 2

    我正在查看Ruby日志记录库Logging.logger方法并从sourceatgithub提出问题与这段代码有关:logger=::Logging::Logger.new(name)logger.add_appendersappenderlogger.additive=falseclass我知道类 最佳答案 这实际上删除了方法(当它实际被执行时)。这是确保close不会被调用两次的保障措施。看起来好像有嵌套的“class 关于Ruby元编程问题,我们在StackOverflow上找到一

  6. ruby - Paperclip:以编程方式分配图像并设置其名称 - 2

    使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案

  7. ruby - 如何以编程方式检查证书是否已被吊销? - 2

    我正在开发一个xcode自动构建系统。在执行一些预构建验证时,我想检查指定的证书文件是否已被撤销。我了解securityverify-cert验证其他证书属性但不验证吊销。我如何检查撤销?我正在用Ruby编写构建系统,但我对任何语言的想法都持开放态度。我阅读了这个答案(Openssl-Howtocheckifacertificateisrevokedornot),但指向底部的链接(DoesOpenSSLautomaticallyhandleCRLs(CertificateRevocationLists)now?)进入的Material对我的目的来说有点过于复杂(用户上传已撤销的证书是一

  8. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  9. ruby - 如何保持我不常用的编程语言技能 - 2

    关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby​​-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby​​有很大不同。由于我与ruby​​之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?

  10. ruby - 如何以编程方式将 mp3 转换为 itunes 可播放的 aac/m4a 文件? - 2

    我一直在寻找一种以编程方式或通过命令行将mp3转换为aac的方法,但没有成功。理想情况下,我有一段代码可以从我的Rails应用程序中调用,将mp3转换为aac。我安装了ffmpeg和libfaac,并能够使用以下命令创建aac文件:ffmpeg-itest.mp3-acodeclibfaac-ab163840dest.aac当我将输出文件的名称更改为dest.m4a时,它无法在iTunes中播放。谢谢! 最佳答案 FFmpeg提供AAC编码功能(如果您已编译它们)。如果您使用的是Windows,则可以从here获取完整的二进制文件。

随机推荐