01.RxSwift-初识
480 2023-04-03 03:16:25
在REACT工程化项目中(yscode),我们会把需要写REACT组件的JS命名为.jsx
目的 : 让创建的文件识别jsx语法,而在create-react-app 脚手架创建的项目中,已经包含了对.jsx文件的处理
REACT 中的组件:每一个组件都是一个单独的个体(数据私有,有自己完整的生命周期,有自己的视图)
只要返回一个JSX元素就可以(掌握props)
特点:
props.title = props.title || '我是标题' ×let title = props.title || ‘我是标题 √
// 只要在JS中使用jsx,则必须引入REACT(因为需要用到CREATE-ELEMNT)// React.Children.map 遍历传递进来的子JSX对象(子元素props.children)import React from 'react';export default function Vote(props) { console.log(props) // => {index: 10, title: "每天开心大笑~"} return <div> {props.title} {/* {props.children} */} {React.Children.map(props.children, (item, index) => { if (index === 0) { return <h2> {item} === {index} </h2> } })} </div>}================================== ReactDOM.render(<div> hello world~ <Vote index={10} title='每天都要开心大笑~'> <span>哈哈哈</span><span>呵呵呵</span> </Vote> <Vote title = 'REACT支持单闭和标签组件调用(VUE不支持)'/></div>, document.getElementById('root'))
我们先来看一下ES6中关于类的一些知识点
/* * 继承 * 1.原型继承 * 2.CALL继承 * 3.寄生组合继承 Object.create * 4.ES6中基于CLASS实现继承 */class Parent { }class Clock extends Parent {constructor() {super(); //=>Must call super constructor in derived class before accessing 'this' or returning from derived constructor 只要用到CONSTRUCTOR,第一行就要写SUPER(类似于CALL继承,会把父类当做函数执行,让函数中的THIS是子类的实例)this.x = 100;}y = 200; //=>新增的语法:给实例设置的私有属性 和 CONSTRUCTOR中的 this.y=200效果一样AAA() {// Clock.prototype.AAA}static CCC = 300; //=>ES7新增的语法:直接在类上设置静态属性(REACT脚手架中给我们设置了关于这种语法的处理:@babel/plugin-proposal-class-properties)static BBB() {// Clock.BBB}}let c = new Clock();console.dir(c);console.dir(Clock);
class Xxx extends React.Component/React.PureComponent
当REACT-DOM.RENDER渲染的时候,如果发现虚拟DOM中TYPE是一个类组件,会创建这个类的一实例,并且把解析出来的PROPS传递给这个类:new Clock(props)
=>先执行CONSTRUCTOR(此时PROPS并未挂载到实例上,基于THIS.PROPS不能获取到值,但是可以直接使用形参中的PROPS;
=>当CONSTRUCTOR执行完,REACT会帮我们继续处理
->把PROPS/CONTEXT...挂载到实例上(后期在其它的钩子函数中可以基于THIS.PROPS获取传递的属性值)
->REACT帮我们把RENDER方法执行
类组件有自己的生命周期(lifecycle)
getDefaultProps
getInitialState
static childContextTypes={}
component
class Clock extends React.Component{ constructor(props){ // props:调取组件传递进来的属性 没有执行super() console.log(props,this.props) // {title: "今天天气真好"} undefined(如果super(props)会读取到传递的属性 super(); //SUPER执行,相当于把React.Component当做普通函数执行,让方法中的THIS是当前实例:this=>{props:xxx,constructor:xxx,refs:{},updater:{...}} } // 必须要有render函数,它返回的内容使我们当前组件要渲染的视图 render(){ return <div> <h2>{this.props.title}</h2> </div> }}ReactDOM.render(<div><Clock title='今天天气真好'></Clock></div>, document.getElementById('root'))
基于第三方插件prop-types设置属性的规则:默认值和其它规则
使用网址 github.com/facebook/pr…
/*1.安装 $ yarn add prop-types*//*2.设置默认值*/static defaultProps={ xxx:xxx}/*3.设置一些其它规则*/static propTypes = {title: PropTypes.string.isRequired}/**PropTypes.isRequired 必须传递*PropTypes.string/bool/number/func/object/symbol/node(元素对象)/element(JSX元素)/instanceOf(Xxx)必须是某个类的实例/oneOf(['News', 'Photos'])多个中的一个/oneOfType([PropTypes.string,PropTypes.number,PropTypes.instanceOf(Message)])多个类型中的一个*/
和VUE一样,我们设定的规则不会阻碍内容的渲染,不符合规则的在控制台报错
setState 在合成时间或者生命周期函数中都是异步操作
把setState 放到一个异步操作中,此时它就没必要异步了,走的是同步处理;
- 定时器
- 原生JS事件
- ajax异步请求
合成事件:
React有一个类似于浏览器的渲染队列机制,它会在多次执行set-state的情况下,如果是异步操作,React把其合成一次进行重新渲染,如果修改的状态一样,以最后一次为主;
`handle = ev => {
* SET-STATE在合成事件或者生命周期函数中都是异步操作 this.setState({ n: 100 }); this.setState({ m: 100 });
}`
默认是get/set 看不到数据,
可以通过ev.persist(); 或者ev.pageX直接获取
import React from 'react';import ReactDOM from 'react-dom';import propTypes from 'prop-types'class Clock extends React.Component {static defaultProps = {title: '北京时间'};static propTypes = {title: propTypes.string};constructor(props) {super(props);//=>初始化状态(和VUE中的DATA一样),要求后期需要在组件中使用的状态都要在这里初始化一下this.state = {time: new Date().toLocaleString(),m: 100};}render() {return <div><h2>{this.props.title}</h2><p>{this.state.time}</p></div>; }//第一次加载组件渲染完毕 等价于 VUE中的MOUNTED componentDidMount(){ // this.state.time = "哈哈哈"; //=>这样确实可以修改状态信息,但是不会通知组件重新渲染// this.forceUpdate();/可以配合使用,让视图强制渲染 => componentWillUpdate(跳过should步骤) //=>每一次修改状态应该基于:setState方法(相对于this.state.xxx=xxx来说,不仅更改了状态,还会通知视图重新渲染)// partialState:部分状态(对象),我们初始化的状态有很多,想修改谁,这块只写谁即可(REACT内部是把之前的状态和传递的partialState进行合并替换的) Object.assign(this.state,partialState)// callback:setState在某些情况下是异步操作,此回调函数代表,通知视图重新渲染后执行的//=>shouldComponentUpdate()=>componentWillUpdate() this.setState({ time:'不知道现在时间哦~' },() => {//=>通知视图已经重新渲染完成了console.log('C');}); }}ReactDOM.render(<> <Clock></Clock></>, document.getElementById('root'))
我们把基于状态(或者属性)的更新来驱动视图渲染=>'受控组件'(受状态管控的组件)
属性什么时候可以改?
- 设置默认值
- 父组件调取子组件,重新传递不同的属性;
- 把获取的属性传递给组件的状态,后期修改状态
基于prop-types设置默认值
class Clock extends React.Component {static defaultProps = {title: '北京时间'};static propTypes = {title: PropTypes.string};constructor(props) {super(props);this.state = {time: new Date().toLocaleString()};}render() {return <div><h2>{this.props.title}</h2><p>{this.state.time}</p></div>;}componentDidMount() {setInterval(() => {this.setState({time: new Date().toLocaleString()});}, 1000);}}ReactDOM.render(<div><Clock></Clock></div>, document.getElementById('root'));
非受控组件:不受状态管控(直接操作DOM)
class Clock extends React.Component {static defaultProps = {title: '北京时间'};static propTypes = {title: PropTypes.string};constructor(props) {super(props);}render() {return <div><h2>{this.props.title}</h2>{/* <p ref='timeBox'>{new Date().toLocaleString()}</p> */}<p ref={element => {//=>REF真实项目中应用最多的是函数的模式// element代表当前元素对象// 直接把元素对象挂载到实例上了this.timeBox = element;}}>{new Date().toLocaleString()}</p></div>;}componentDidMount() {//=>可以获取到DOM元素// this.refs={timeBox:p} setInterval(() => {this.timeBox.innerHTML = new Date().toLocaleString();// this.refs.timeBox.innerHTML = new Date().toLocaleString();}, 1000);}}ReactDOM.render(<div><Clock></Clock></div>, document.getElementById('root'));