React 面向组件编程(上)

news2025/1/21 12:07:49

目录

  • 前言:
  • 一、组件的基本理解和使用
    • 1. 函数式组件
    • 2. 类式组件
    • 3. 注意事项
    • 4. 渲染函数式组件标签的基本流程
    • 5. 渲染类组件标签的基本流程
  • 二、组件三大核心属性 1:state
    • 1. 代码示例
    • 2. 效果展示
    • 3. 注意
    • 4. 设置状态:setState
  • 三、 组件三大核心属性 2:props
    • 1. 函数式组件代码示例
    • 2. 类式组件代码示例
    • 3. 效果展示
    • 4. props 属性的特点:
    • 5. 对 props 进行限制
  • 四、组件三大核心属性 3:refs与事件处理
    • 1. 字符串形式的代码示例
    • 2. 回调函数形式的代码示例
    • 3. createRef 代码示例
    • 4. 效果展示
    • 5. refs 使用场景
  • 总结:

前言:

在React中,组件实例的三大核心属性包含state、props、ref,通过这三大核心属性的使用,我们能够实现对组件的状态进行更新。


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

1. 函数式组件

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

2. 类式组件

class MyComponent extends React.Component{
    render(){
        return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
    }
}
ReactDOM.render(<MyComponent />,document.getElementById('test'))

3. 注意事项

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

4. 渲染函数式组件标签的基本流程

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

5. 渲染类组件标签的基本流程

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

二、组件三大核心属性 1:state

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。


1. 代码示例

<script type="text/babel">
   // 1. 创建一个类式组件
   class Weather extends React.Component{
      // 构造器调用了几次? --- 实例化了几次,调用几次 --- 1次
      constructor(){
          super();
          // console.log(this)
          this.state = {isHot:false,wind:"微风"}

          this.changeWeather = this.changeWeather.bind(this)
      }
      // render方法是放在原型上的
      // render中的this是谁? -- 实例对象 <===> Weather组件实例对象
      // render方法调用了几次? --- 1 + N
      // 调用的流程:
          // 1. 页面状态发生改变时,重新调用render方法来生成一个新的虚拟DOM
          // 2. 通过diff算法来 对比 新旧虚拟DOM之间的差别,从而进行合并
          // 3. 将对比合并过后的虚拟DOM 转换为真实DOM,挂载到页面的指定位置
      render(){
          // console.log('render中的this',this)
          // onClick事件:首字母需要大写,由于changeWeather是作为onClick的事件回调,所以这里需要一个函数体,而不是函数执行后的结果
          let {isHot,wind} = this.state
          return <h2 onClick={this.changeWeather}>今天的天气很 {isHot? '炎热' : '凉爽' }{wind}</h2> // isHot
      }
      // changeWeather调用几次?  --- 点几次调用几次
      changeWeather(){
          // 因为Babel编译,所以导致类中的方法默认开启局部的严格模式,所以这里的this是undefined
          // console.log('changeWeather',this.state)
          // 严重注意:状态(state)不可直接修改
          // this.state.isHot = !this.state.isHot // 这里是一种错误写法
          let {isHot} = this.state
          this.setState({ isHot:!isHot }) // 这里的修改是一种合并,对比属性的变化,如果有赋新值,如果没有跳过;
      }
  }
  // 2. 渲染到页面中的指定 DOM
  // ReactDOM.render(虚拟DOM,真实DOM)
  ReactDOM.render(<Weather />,document.getElementById('test'))
</script>

2. 效果展示

在这里插入图片描述


3. 注意

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

4. 设置状态:setState

setState(object nextState[, function callback])

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

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

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


三、 组件三大核心属性 2:props

react 中说的单向数据流值说的就是 props,根据这一特点它还有一个作用:组件之间的通信。props 本身是不可变的,但是有一种情形它貌似可变,即是将父组件的 state 作为子组件的 props,当父组件的 state 改变,子组件的 props 也跟着改变,其实它仍旧遵循了这一定律:props 是不可更改的。


1. 函数式组件代码示例

<script type="text/babel">
    function Person (props) {
        let {name,age,sex} = props
        return(
            <ul>
                <li>姓名:{name}</li>
                <li>性别:{sex}</li>
                <li>年龄:{age+1}</li>
            </ul>
        )
    }

    // 给指定的属性,添加默认值
    Person.defaultProps = {
        sex:'男'
    }
    // 1. 数据类型,是否应该有对应的限制?
    // 2. 数据的数量,批量性传输的时候,可以使用展开运算符
    // let speak = 'speak'
    ReactDOM.render(<Person name="tom" age="18" sex="男"/>,document.getElementById('test1'))
    ReactDOM.render(<Person name="jock" age="19" sex="女"/>,document.getElementById('test2'))
    
    const p = {name:'老王',age:22}
    ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))
</script>

2. 类式组件代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Props基本使用</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>
    <!-- 引入 React 核心库 -->
    <script src="../js/react.development.js"></script>
    <!-- 引入 react-dom 用于支持 react 操作 DOM -->
    <script src="../js/react-dom.development.js"></script>
    <!-- 引入babel:1. ES6 ==> ES5	2. jsx ==> js-->
    <script src="../js/babel.min.js"></script>
    <script type="text/babel">
        class Person extends React.Component{
            render(){
                let {name,age,sex} = this.props
                console.log(this)
                return(
                    <ul>
                        <li>姓名:{name}</li>
                        <li>性别:{sex}</li>
                        <li>年龄:{age+1}</li>
                    </ul>
                )
            }
        }
        // 1. 数据类型,是否应该有对应的限制?
        // 2. 数据的数量,批量性传输的时候,可以使用展开运算符
        ReactDOM.render(<Person name="tom" age="18" sex="男"/>,document.getElementById('test1'))
        ReactDOM.render(<Person name="jock" age="19" sex="女"/>,document.getElementById('test2'))
        
        const p = {name:'老王',age:22,sex:'男'}
        // console.log("@",{...p})
        ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))
    </script>
</body>
</html>

3. 效果展示

需求: 自定义用来显示一个人员信息的组件

  1. 姓名必须指定,且为字符串类型;
  2. 性别为字符串类型,如果性别没有指定,默认为男
  3. 年龄为字符串类型,且为数字类型,默认值为18

在这里插入图片描述


4. props 属性的特点:

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

5. 对 props 进行限制

  1. 引入 prop-type 库,这就是专门用于限制 props 属性的一个库
  2. 导入 prop-type 库,到当前页面
  3. 根据 Person.propTypes = {} 进行限制

参考官方文档所示

// cli 脚手架引入方式
import PropTypes from "prop-types";
// js 引入方式
<script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script>
// 类式组件
class index extends Component {
    static propTypes = {
        // 限制 list,为数组类型,必填
        list: PropTypes.array.isRequired,
        // 限制 changeitem,为一个函数,必填
        changeitem: PropTypes.func.isRequired,
        // 限制 onDelete,为一个函数,必填
        onDelete: PropTypes.func.isRequired,
    }
    render() {
        const { list, changeitem, onDelete } = this.props
        return (
            <ul className="todo-main">
                <Item list={list} changeitem={changeitem} onDelete={onDelete} />
            </ul>
        );
    }
}

注意:

在 React v15.5 中PropTypes是react的内置对象,在 React v15.5 开始已弃用以下方式。

Person.propTypes = {
	name: React.PropTypes.string.isRequired,
	age: React.PropTypes.number
}

四、组件三大核心属性 3:refs与事件处理

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


1. 字符串形式的代码示例

class Demo extends React.Component{
     showData=()=>{
         // console.log(this)
         // 专款专用:每一个ref都是唯一的,存在this.refs中
         let {ipt1} = this.refs
         alert(ipt1.value)
     }
     showData2=()=>{
         let {ipt2} = this.refs
         alert(ipt2.value)
     }
     render(){
         return(
             <div>
                 <input ref="ipt1" type="text" placeholder="请输入数据"/>
                 <button onClick={this.showData}>点我提示左侧的数据</button>
                 <input ref="ipt2" onBlur={this.showData2} type="text" placeholder="请输入数据" />
             </div>
         )
     }
 }

2. 回调函数形式的代码示例

class Demo extends React.Component{
    showData=()=>{
        let {input1} = this
        alert(input1.value)
    }
    showData2=()=>{
        let {input2} = this
        alert(input2.value)
    }
    render(){
        return(
            <div>
                {/* 这里是注释~ */}
                <input ref={ c=>this.input1 = c} type="text" placeholder="请输入数据"/>
                <button onClick={this.showData}>点我提示左侧的数据</button>
                <input ref={c=>this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
            </div>
        )
    }
}

什么是回调函数?

  1. 自己写的函数
  2. 不是自己调用的
  3. 这个函数最后执行了

3. createRef 代码示例

class Demo extends React.Component{
    /*
        React.createRef() 返回一个容器,容量为1,只能存一个,多余会覆盖前者
        这个容器中,可以去存储一个指定的DOM。
    */
    // 专款专用:每一个自定义的ref标记只能给唯一的DOM使用
    myRef = React.createRef() // 容量为1,只能存一个,多余会覆盖前者
    myRef2 = React.createRef()
    showData=()=>{
        alert(this.myRef.current.value)
    }
    showData2=()=>{
        alert(this.myRef2.current.value)
    }
    render(){
        return(
            <div>
                <input ref={ this.myRef} type="text" placeholder="请输入数据"/>
                <button onClick={this.showData}>点我提示左侧的数据</button>
                <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
            </div>
        )
    }
}

注意:

React 官方推荐使用 createRef 创建 ref 容器的方法

4. 效果展示

需求: 自定义组件, 功能说明如下:

  1. 点击按钮, 提示第一个输入框中的值
  2. 当第2个输入框失去焦点时, 提示这个输入框中的值

在这里插入图片描述


5. refs 使用场景

refs 通常适合在一下场景中使用:

  • 对DOM 元素焦点的控制、内容选择或者媒体播放;
  • 通过对DOM元素控制,触发动画特效;
  • 通第三方DOM库的集成。

避免使用 refs 去做任何可以通过声明式实现来完成的事情。例如,避免在Dialog、Loading、Alert等组件内部暴露 open(), show(), hide(),close()等方法,最好通过 isXX属性的方式来控制。


总结:

欢迎大家加入我的社区,在社区中会不定时发布一些精选内容:https://bbs.csdn.net/forums/db95ba6b828b43ababd4ee5e41e8d251?category=10003


以上就是 React 面向组件编程(上),不懂得也可以在评论区里问我或私聊我询问,以后会持续发布一些新的功能,敬请关注。
我的其他文章:https://blog.csdn.net/weixin_62897746?type=blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408553.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小程序问题:封装公共组件的onLoad方法不生效

素材编辑 | 宋大狮 排版运营 | 小唐狮 ONE 问题描述 因为许久没有接触小程序项目&#xff0c;今天在做小程序项目时&#xff0c;为了节省时间&#xff0c;将要修改的页面组件直接拿出来封装成了公共组件&#xff0c;同时也没多想就直接使用了。于是就出现了页面数据不能加载的…

模板字符串基本使用

模板字符串是ES6添加的一个新的字符串编写形式。 1.【模板字符串】之拼接 在ES6之前&#xff0c;如果我们想要将字符串和一些动态的变量拼接到一起&#xff0c;是很麻烦的。 const name "aaa" const age 18console.log("my name is "name".Im &q…

三个案例掌握this.$nextTick()方法的使用/Vue中的$nextTick()

this.$nextTick() 解释为在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的DOM. 也就是说&#xff0c;当dom元素发生改变&#xff0c;重新渲染dom树后&#xff0c;再执行vue.$nextTick()里面的内容。 其实用方法一般为 this.$n…

讲讲vue3下会造成响应式丢失的情况

题引&#xff1a; 在我们从vue2过渡到vue3的时候&#xff0c;对于数据响应式的变化其实是懵懵懂懂的。从以往直接在data函数里面定义变量到每一次都要使用ref/reactive时&#xff0c;是有些不适应的。但问题不大&#xff0c;毕竟在大前端时代中&#xff0c;如果不及时跟上时代…

TS中快速定义一个对象数组以及处理async await的异常

定义一个对象数组&#xff08;即数组成员为对象&#xff0c;对象的属性为我们所约束&#xff09; 方法一&#xff1a;接口字面量形式 export type Resource {_id: string,personID: {_id: stringage: stringidentifier: stringname: stringnation: stringgrade: stringscheme…

contentEditable属性

前言 我们最常用的输入文本内容便是input与textarea&#xff0c;但是有一个属性&#xff0c;可以让我们在很多标签中&#xff0c;如div,table,p,span,body等&#xff0c;可以像input输入框一样&#xff0c;实现文本编辑&#xff0c;这便是contentEditable属性 contentEditabl…

【vue2】近期bug收集与整理01

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;记录博主在vue2中遇到过的坑&#xff0c;本文是博主的学习使用总结 目录 1登陆token的问…

【学姐面试宝典】前端基础篇Ⅴ——JS深浅拷贝、箭头函数、事件监听等

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【前端面试专栏】 今天继续学习前端面试题相关的知识&#xff01; 感兴趣的小伙伴一起来看看吧~&#x1f91e; 文章目录什么是事件监听事件委托以及冒泡原理介绍一下 promise&#x…

uniapp 小程序嵌套H5开发总结

项目需求是在uniapp小程序项目中嵌套H5页面&#xff0c;H5返回小程序需要传值给小程序进行通信。 好,百度一查确实可以实现 用的uniapp提供的web-view&#xff08;https://uniapp.dcloud.io/component/web-view.html#web-view经验证实&#xff0c;做功能之前先看官网&#xff…

一天时间迅速准备前端面试|JavaScript——异步进阶

&#x1f308;本系列文章是博主精心整理的面试热点问题&#xff0c;吸收了大量的技术博客与面试文章&#xff0c;总结多年的面试经历&#xff0c;带你快速建立前端面试知识体系。抓住每一场面试的机会&#xff0c;知己知彼才能百战百胜&#xff01; 上期回顾 JS基础–异步 本系…

【中秋快乐】如何用three.js实现我的太空遐想3D网页

目录 创作背景 功能分解 创建3d地球 创建3d月球 创建3d小火箭

解决element-ui动态加载级联选择器默认选中问题(Cascader)

前言 最近在开发任务中碰到需要在新增和修改时使用动态加载级联选择器&#xff0c;但是当在修改时设置默认选中项&#xff0c;出现了后端数据返回较慢&#xff0c;导致无法选中和级联框选中了但input框不显示的问题&#xff0c;网上找到的方法也不是很有效&#xff0c;还得使用…

Vue - v-for 循环渲染多个 “重复“ 子组件(仅 ref 不同,this.$refs.xx 使用时依然能准确找到子组件)将子组件 ref 设为动态,这样每个子组件都是 “独立“ 的!详细教程

前言 本教程更多版本:uni-app | 微信小程序 我们会通过给组件绑定 ref 值,然后通过 this.$refs.xx 来获取这个组件上的方法和变量。 如果 在 v-for 中循环渲染组件(绑定固定 ref),那么这个 ref 就会 “一摸一样”,导致根本无法找到(this.$refs.xx 谁?), 要解决这个问…

【前端】vue模板语法知识了解一下,是不是只知道用element-ui组件?

vue写在前面Vue模板语法文本原始HTML属性开源Vue模板和主题框架集合BootstrapVueelement-ui最后总结写在前面 上一篇总结了在实操过程中如果遇到了nodejs版本的问题&#xff0c;我们该如何去解决的&#xff0c;还有就是总结了vue2和vue3生命周期的区别&#xff0c;如果感兴趣的…

【JavaScript】JS实用案例分享:动态生成分页组件 | 通过按键实现移动控制

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 &#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&am…

React 路由v6 - 超全详解

React router v6 路由 已经习惯了 v5 版本的路由 &#xff0c;那么 v6 版本的路由 该怎么应用呢&#xff1f; 文章目录React router v6 路由Ⅰ、路由 v6 (两种形式)Ⅱ、 动态路由Ⅲ、路由重定向Ⅳ、路由跳转 (两种形式)Ⅴ、路由懒加载Ⅰ、路由 v6 (两种形式) 方案一 &#xff…

JS原生——编写简易计算器

一个非常适合新手练习的小案例&#xff01;&#xff01;&#xff01; 使用JS的ES5语法HTMLCSS及企业级代码规范&#xff0c;方便后续良好的代码习惯养成&#xff01;&#xff01;&#xff01; 先来看一下样式吧&#xff01;&#xff01;&#xff01;&#xff08;后附代码&…

组件通信的6种方式

什么是组件通信 vue组件中关系说明: 如上图所示, A与B、A与C、B与D、C与E组件之间是父子关系&#xff1b; B与C之间是兄弟关系&#xff1b;A与D、A与E之间是隔代关系&#xff1b; D与E是堂兄关系&#xff08;非直系亲属&#xff09; 针对以上关系我们归类为&#xff1a; 父…

前端跨域解决方案

文章目录1.同源政策2.跨域解决方案2.1 CORS普通跨域请求&#xff1a;只需服务端设置Access-Control-Allow-Origin即可携带cookie跨域请求&#xff1a;前后端都需设置2.2 JSONP原理缺点数据格式jsonp跨域实现2.3 postMessage跨域2.4 WebSocket属性&#xff1a;事件&#xff1a;使…

vue3+vite:本地代理,配置proxy

一、项目&#xff1a;uniappvue3vitets 二、配置文件在vite.config.ts proxy: {/snow: { // 匹配请求路径&#xff0c;localhost:3000/snowtarget: https://www.snow.com/, // 代理的目标地址changeOrigin: true, // 开发模式&#xff0c;默认的origin是真实的 origin:localh…