那时候刚好下着雨,柏油路面湿冷冷的,还闪烁着青、黄、红颜色的灯火。



React-当页面触发一个事件的时候都发生了什么(一)


React-当页面触发一个事件的时候都发生了什么(一)

上一篇文章写了一个《使用React做一个后台界面》,对React做了一个简单的介绍。本章依然秉持着实用的原则进行讲解,并只做前一部份的主要介绍,比较简单,后几期将会讲解routers, models, services 等相关的讲解,若有时间会利用这些知识实现一个简单的页面及服务端交互,干货较多。

React的写法比较多,这里只讲我推荐的写法

先看看一个组件的基本结构

既然都用JSX了,自然我们的写法也要高大上一些,要跟上潮流。

以下列出了简单的伪代码,进行分析。

组件若要实现相关功能需要继承React.Component这个类,并对基中的一些方法或属性进行复写。

import React from 'react';
export default class Hello extends React.Component {
    state = {};
    props = {};
    context = {};
    refs = {};
    updater = {};
    // 构造函数
    constructor(props) {
        super(props);
    };
    // 组件将挂载
    componentWillMount() {};
    // 组件没有挂载
    componentDidMount() {};
    // 组件卸载
    componentWillUnmount() {};
    // 给出结果 必须要有一个返回结果
    render () {};
}

以上代码可以看到,一个类(组件)的基本结构由4个函数及5个成员属性组成。若定义了那就是对上父类的属性或方法进行复写,若不定义那将会复用父类的默认方法。当然render()是必须要有返回值的。

执行顺序

我们分别在每个函数上打印一串字符串来标识它的运行顺序。

    constructor(props) {
        console.log(props);
       console.log("constructor...")
       super(props);
    };
    componentWillMount() {
        console.log("component will mount...")
    };
    componentDidMount() {
        console.log("component did mount...")
    };
    componentWillUnmount() {
        console.log("component will ummount...")
    };
    render () {
        console.log("render...")
    }

执行结果如下:

从运行的结果可以看出好述函数的执行顺序是:

  1. constructor() 构造函数
  2. componentWillMount() 挂载前
  3. render() 给出结果
  4. componentDidMount()

从上可以看出 componentDidMount() 函数是最后才执行的,componentWillMount() 函数是在 render() 执行之前运行的,构造函数由于它的特殊性,不建议是构造函数里进行一些业务逻辑处理。

成员属性

成员属性主要有以下五个:

  • state
  • props
  • context
  • refs
  • updater

可自己行定义本类中自己需要的属性不会影响上层。

由于篇幅问题,本章只会讲解一部份属性的使用

state - 共享状态

有MVVM设计模式的框架经验的都知道,数据双向绑写这个东西。它实现了模型数据动则页面动,模型数据不动页面不动的一个模式。

而当前类的state属性的使用就是用于当前类的状态工享,通过状态共享来实现数据与页面的互通。state是一个object类型,默认是null,咱们可以自定义一些值供页面使用。

举个栗子

来一个简单的例子,点击一个按钮改变页面的的文字。

为了方法观看我们设置一个变量i来观察render()所执行的次数

import {Button} from 'antd';

// 部分伪代码

i = 0;

state = {
   title: "Hello World!"
};

onChangeTitle = (e) => {
   const text = "Hello Dudulu!";
   this.setState({
       title: text
   });
   
   // this.forceUpdate();
};

render() {
   console.log(this.i);
   this.i = ++this.i;
   return (<div>
       <h1>{this.state.title}</h1>
       <Button onClick={this.onChangeTitle}>点我点我!</Button>
   </div>)
}

共享状态里的title默认给个"Hello world!",render()方法输出一个h1标签与一个Button按钮(按钮使用的是ant.design提供的UI组件。)并组它赋予一个onClick事件,当点击按钮后,调用方法对共享状态里的title进行改变。这里使用了一个父类函数setState()(还有forceUpdate(), 下次说),这个函数就是对当前共享状态进行修改。

效果图:

再来看看 render() 函数,里面输出了个日志console.log(this.i)i的默认值是"0",当渲染完这个页面后控制台会输出"0",并且对i进行自增"1",这没毛病。

当我点击Button按钮后调用了onChangeTitle方法,对共享状态的title进行重新设置值的时候,render()函数又执行了一次,这个时候h1标签里的值变成了"Hello Dudulu!"了,控制台输出了"1",再次点击按钮,控制台输出了"2"...

从上面实现我们可以发现,只要render()所输出的页面有使用共享状态里的值,当共享状态里的值发生变化的时候,render()会重新渲染一次,从而改变页上的效果。当然还有事件传参,这里暂没用上先不写,后面将会一一介绍。

props - 道具

我们先打印一下this.props看看它都有什么。

从上打印的结果来看就是上层Route注入进来的一些参数。

这里先不对它进行详细的说明,简单来个例子说明它是怎么实现的。我们可以把它看成一个标签所传进来的一些参数。

举个栗子:

import React from 'react';

class Hello extends React.Component {
    render() {
        console.log(this.props)
        return (
            <div>
                看我看我看我......
            </div>
        )
    }
}

export default class Index extends React.Component {
    render() {
        return (<span>
            <Hello />
        </span>)
    }
}

从上面代码看,我们定义了一个Hello类,我们把它当作标签使用,注意: 标签的首字母必须是大写

页面会输出"看我看我看我......", 这也没啥毛病,我们看看控制台输出的this.props有什么。

对,一个空对象,因为我上层什么也没传给它。那我对代码一进行一个小修改,传入几个参数进去:

render() {
   const helloProps = {
       onClick: function () {

       },
       width: 100
   };
   return (<span>
       <Hello {...helloProps} height={50}/>
   </span>)
}

修改完后,再来看Hello里面的render()方法输出是怎样的props

是的,看完这个例子应该都理解了吧,其实props就是上层所传的参数。当你不传的时候就是空对象,你传什么就是什么。

当然还有其他方法不需要手动去传参,比如PropTypes, dva的 connect() 方式注入等。后面使用model的时候会再次提到。

由于篇幅的原因, 本节就先写到这吧, 其他属性后面再慢慢填上

尾巴

这是一个伪前端对React的一些浅薄理解,若有写错的地方也欢迎各个大神指点指点,本人虚心接受。

由于时间问题,可能更新会比较慢,希望理解。

最后,本文纯属原创,若要转载请注明出处, 谢谢合作。

深情按压, 小额赞赏, 您的赞赏就是我更新的动力。


 标签 , TAG , 啦啦