React——创建组件和封装组件

第一种创建组件的方式:函数组件

函数组件是简单组件,因为他没有状态(hooks 出现之前)

import React from 'react'
import ReactDOM from 'react-dom'

const cat = {
	name:'Kitty',
	age:2,
	gender:'雌'
}

function Hello(props){ //组件名称首字母必须大写,注意这个 props 是只读的,不能被重新赋值,这点和 vue 一样
console.log(this) // undefined 因为 bebal 转换的时候开启了严格模式,它不让自定义的函数里的
//this 指向 window,所以是 undfined
	return ( <> <div>我是一个hello函数组件  ---{props.name} ----{props.age} ---{props.gender}</div> </>) 
	// 在组件中必须要 return null 表示这是一个空组件,一般会 return 一个合法的 jsx 虚拟 dom 元素
}

ReactDOM.render(<div>
//<Hello name={cat.name} age={cat.age} gender={cat.gender}></Hello>  
// 为组件传递数据,组件内部使用 props 接收
// 使用 ES6 展开运算符简化组件的数据传递
<Hello {...cat}></Hello>
</div>,document.getElementById('app'))

第二种创建组件的方式:类组件

类组件是复杂组件,因为它有状态(state)和生命周期钩子

import { Component } form 'react'
import ReactDOM from 'react-dom'

const dog = {
	name: '大黄'age: '3'
}

// 在类组件中,如果想要拿到外界传过来的 props 参数,不需要接收,直接使用 this.props.xxx 就可以直接访问即可
class Hello extends Component{ // 类组件内部必须有 render 函数
	construct(){ // 因为 Hello 继承了 Component这个组件,所以自定义构造器中必须调用
	//super,construct只调用一次,对 state 进行初始化
		super() // 调用 super 后才能在 construct 函数中使用 this 关键字
		this.state = {  // 这里的 state 就相当于 vue 中的 data(){ return {...}}
			mes:'我是类组件里的私有属性'
		}
		//this.changeSomething = this.changeSomething.bind(this) 下面用箭头函数解决 this 指向问题 
		//因为 onClick 回调时相当于是 window 调用 changeSomething 方法,而不是实例调用
		// changeSomething 方法,又因为开启了严格模式,所以 changeSomething 方法里 this 不是 window 而是 undefinded,所以使用 bind 改变
		//changeSomething 方法的 this 指向,并且返回一个新函数
	}
//this.props.name = '小黑'  
// 报错,因为无论是 class 组件还是 function 组件的 props 都是只读的。

// render 渲染 1+n 次(n 是 state 改变的次数),换句话说,state 里的状态一改变,render 就会调用重新
//渲染页面上对应 state 的部分(只更新修改的部分,这就是虚拟 dom 的魅力,减少重绘重排)
	render(){ // render 函数必须返回一个合法的 jsx 虚拟 dom
		return <div>我是一个类组件 --- {this.props.name} --- {this.props.age} --- {this.state.mes}</div>
		// this 是当前组件的实例对象
	}
	//这里我们直接写 changeSomething 没有用 const、let 等定义,因为类中直接写赋值语句表示直接
	//向类的实例身上添加属性或方法,但是写在 construct 构造函数中代表向原型对象上添加方法,而不是
	//在实例对象上添加的,实例需要通过原型链找到对应的方法
	changeSomething = ()=>{ // 箭头函数中的 this 固定指向当前定义函数的作用域,不会改变,就能解决 onClick 时回调 changeSomething 的 this 指向问题
		this.setState({mes:'新信息'})
	}
}

//这里的 <Hello /> 标签其实就是 Hello 类的一个实例对象 ps:标签里的{}代表我们要写 js 表达式了,console.log(...obj)
// 报错,因为一个对象不能直接展开(但是数组可以,数组有展开运算符),这里
//是因为引入了 react 和 babel 才能在标签里写 ...dog 的,一般在标签外不能随意这样写。另外 es6 有个
//新语法:const newObj = {...obj}表示拷贝了一个对象,修改 newObj 里的属性 newObj 不跟随更
//改,my god,我现在才弄清楚。。。
ReactDOM.render(<div><Hello {...dog}></Hello></div>,document.getElementById('app'))

两种创建组件的对比

1、函数组件:只有 props(只读的,不会变的),没有自己的私有数据和生命周期;类组件:有 props(只读的),也有自己的私有数据 state(可读可写的)和自己的生命周期;所以函数组件也叫无状态组件,类组件也叫有状态组件
2、什么时候适合用函数组件、什么时候适合用类组件?
答:当一个函数需要有自己的私有数据的时候适合用 class 组件,反之使用函数组件。
3、函数组件和类组件的本质区别:有无 state 与有无生命周期函数
4、函数组件由于没有状态和生命周期,运行效率要高一些,但是如果哪一天这个页面需要有自己的 state 了,就需要重构为 class 组件,比较麻烦,所以在 hooks 没出现之前,函数组件用得不多,基本都用类组件。

组件中的 props 和 state/data 之间的区别?

1、props 的数据都是外界传过来的;state/data 都是组件内部私有的(通过 ajax 传递过来的数据都是私有的)
2、props 传递过来的值是只读的;state/data 中的数据都是可读可写的(可改变的)。

组件的生命周期:
https://www.bilibili.com/video/BV11t411S7iG?p=52

一个组件应该具备的特点

一、高内聚,低耦合,一方面我们应该把逻辑紧密相关的内容放在一个组件内,类似于 vue 可以在一个 .vue 文件内写 html、css、js,另一方面,组件之间尽量不要有依赖关系,组件与组件彼此之间应该一无所知。
低耦合的好处:修改一个组件时,不会影响到另一个组件,一个组件可以随时被替换掉,而高耦合的话,就很难去修改一个依赖了很多其他组件的组件

二、通过 props 控制其行为,隐藏内部结构:降低耦合,方便调用,其他组件不应该知道该组件的内部细节,调用者只需要通过 props 传参就能实现相应的功能

三、职责单一:一个组件只应该做一个事情,并把这一件事做好,若处理的任务过多,那么修改一个任务的时候可能会影响另一个任务

封装一个组件前的思考

一、这个组件是做什么的
二、这个组件至少应该知道哪些东西
三、这个组件会反馈什么东西

例如碰到一个轮播图组件的时候:
一、这个组件是做什么的
1、可以展示多张图片
2、可以向左向右翻页,或者是向上向下翻页
3、pageControl 状态会根据图片的滚动有相应的变化
4、是否支持手动滑动
5、是否支持无限滚动
6、图片有点击事件,点击之后有相关的事件反应

二、这个组件至少应该有哪些东西
一个好的组件应该使用最少的参数,就能达到期望的效果
1、一个图片url数组
2、当图片不存在时的 url 占位符
3、默认自动滚动

三、这个组件会反馈哪些东西

1、一个可用的轮播图

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的React封装toast组件的示例: ```jsx import React, { useState, useEffect } from 'react'; import ReactDOM from 'react-dom'; import './toast.css'; const Toast = ({ message, duration = 3000, onClose }) => { const [visible, setVisible] = useState(false); useEffect(() => { setVisible(true); const timer = setTimeout(() => { setVisible(false); onClose && onClose(); }, duration); return () => clearTimeout(timer); }, [duration, onClose]); return visible ? ( <div className="toast"> <div className="toast-message">{message}</div> </div> ) : null; }; const showToast = (message, duration = 3000, onClose) => { const div = document.createElement('div'); document.body.appendChild(div); ReactDOM.render( <Toast message={message} duration={duration} onClose={() => { ReactDOM.unmountComponentAtNode(div); onClose && onClose(); }} />, div ); }; export default showToast; ``` 这个组件包含一个`Toast`组件和一个`showToast`函数。`Toast`组件接收`message`、`duration`和`onClose`作为属性,其中`message`表示要显示的消息,`duration`表示消息显示的时间(默认为3秒),`onClose`表示关闭消息时的回调函数。 `showToast`函数用于在页面上创建一个`Toast`组件并显示消息。它接收与`Toast`组件相同的属性,还有一个可选的`onClose`回调函数,用于在消息关闭时执行其他操作。 在使用时,可以像这样调用`showToast`函数: ```jsx import React from 'react'; import showToast from './toast'; const MyComponent = () => { const handleClick = () => { showToast('Hello, world!', 2000, () => console.log('Toast closed.')); }; return ( <button onClick={handleClick}>Show Toast</button> ); }; export default MyComponent; ``` 这个示例在点击按钮时显示一个消息框,显示2秒后关闭,并在关闭时输出一条消息到控制台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值