模块开发之React入门使用(五)
发布日期:2021-06-29 14:16:11 浏览次数:2 分类:技术文章

本文共 8370 字,大约阅读时间需要 27 分钟。

模块开发之React入门使用(五)

前言

React有2个特点值得我点出来.

  • 组件:通过 React 构建组件,大页面拆分成小组件
  • 单向响应的数据流:React 实现了单向响应的数据流,从而减少了重复代码,比Vue的数据绑定更简单.这个后面会特别介绍.

当你初次接触React时,React 官方文档极其详尽,是你的首选.

推荐

引入模块

ES6引入方式:import React from 'react'

ES5引入方式:var React = require('react')

渲染标签和组件

React即可以渲染标签也可以渲染React组件,

渲染标签变量使用首字母小写,渲染React组件变量首字母使用大写.

渲染标签

var testDivElement = 
;ReactDOM.render(testDivElement, document.getElementById('example'));

这种有趣的标签语法既不是字符串也不是HTML。是JSX语法标签.

渲染React组件:

var TestComponent = React.createClass({/*...*/});var testElement = 
;ReactDOM.render(testElement, document.getElementById('example'));或var TestComponent = React.createClass({/*...*/});ReactDOM.render(
, document.getElementById('example'));

React 的 JSX 使用大、小写的约定来区分本地组件的类和标签。

由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。

React创建组件的3种方式

函数式(Functional)“组件

最简单的方式,也是最不灵活的方式,它是无状态的,官方提倡使用这种写法,无状态组件被鼓励在大型项目中尽可能以简单的写法来分割原本庞大的组件

例如

import { render } from 'react-dom'function Welcome(props, /* context */) {
return

Hello, {props.name}

;}const element =
;ReactDOM.render( element, document.getElementById('root'));

特点:

  • 写法简单,只能一个render方法
  • 组件不会被实例化,无状态组件就不会在有组件实例化的过程,不会占用多余内存,整体渲染性能得到提升.
  • 不能使用this访问属性
  • 不能访问生命周期方法
  • 只能访问props

React.createClass方式

是ES5的原生的JavaScript来实现的React组件,是有状态的组件.

方法能创建组件类,通过实现render()方法返回一个组件实例,你不需要使用new创建组件,像正常的HTML标签一样使用即可。

简单的组件定义

var Root = React.createClass({    render:function(){        return (            
); },});ReactDOM.render(
, document.getElementById('content'));
  • 变量名必需大写
  • ReactDOM.render方法里的组件只能有一个根结点,根结点下可以有若干子结点.

复杂的组件定义

var InputControlES5 = React.createClass({    propTypes: {
//定义传入props中的属性各种类型 initialValue: React.PropTypes.string }, defaultProps: { //组件默认的props对象 initialValue: '' }, // 设置 initial state getInitialState: function() {
//组件相关的状态对象 return { text: this.props.initialValue || 'placeholder' }; }, handleChange: function(event) {
this.setState({ //this represents react component instance text: event.target.value }); }, render: function() {
return (
Type something:
); }});InputControlES5.propTypes = { initialValue: React.PropTypes.string};InputControlES5.defaultProps = { initialValue: ''};
  • 函数this自动绑定,这种方式创建的组件,其每个成员属性和方法的this都与React自动绑定,直接使用this.methodthis.props即能访问方法或属性
    例如
const Contacts = React.createClass({    handleClick() {    console.log(this); // React Component instance  },  render() {    return (      
); }});

能直接使用this.handleClick获得函数

- propTypes和defaultProps属于组件实例,类似于java里对象的属性,而不是类的属性,defaultProps是使用getDefaultProps的方法来获取默认组件属性的
例如:

onst TodoItem = React.createClass({    propTypes: {
// as an object name: React.PropTypes.string }, getDefaultProps(){ // return a object return { name: '' } } render(){ return
}})
  • 其状态state是通过getInitialState方法来配置组件相关的状态
    例如:
const TodoItem = React.createClass({    // 返回一个对象    getInitialState(){         return {            isEditing: false        }    }    render(){        return 
}})

React.Component方式

以ES6的形式来创建react的组件的

- 是React目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式
- 相对于 React.createClass可以更好实现代码复用。

例子:

class TestComponent extends React.Component {
constructor(props) { super(props); // 设置 initial state this.state = { text: props.initialValue || 'placeholder' }; // ES6 类中函数必须手动绑定 this.handleChange = this.handleChange.bind(this); } static propTypes = {
//类的静态属性 name: React.PropTypes.string }; static defaultProps = {
//类的静态属性 name: '' }; handleChange(event) { this.setState({ text: event.target.value }); } render() { return (
Type something:
); }}TestComponent.propTypes = { initialValue: React.PropTypes.string};TestComponent.defaultProps = { initialValue: ''};

-成员函数不会自动绑定this,需要手动绑定,否则this不能获取当前组件实例对象。

因为执行函数的上下文环境并不是当前组件而是window对象,如果不指定this是不知道this是哪个对象的。
3种方式实现
第一种

constructor(props) {       super(props);       this.handleClick = this.handleClick.bind(this); //构造函数中绑定  }

第二种

//使用bind来绑定

第三种:

this.handleClick()}>
//使用arrow function来绑定
  • propTypes和defaultProps属于组件类,类似于静态属性
  • 状态state是在constructor中像初始化组件属性一样声明的,直接赋值,
    例如
this.state = { // define this.state in constructor     isEditing: false }

创建组件方式选择

  • 尽量使用无状态组件创建形式
  • 由于React团队已经声明React.createClass最终会被React.Component的类形式所取代,故尽量使用React.Component

state与props使用

React有2种保存数据的对象,即state和props.

state是状态的意思,刚开始我理解不了state想表达的意思,原来state原本的意思是本地数据(只属于当前组件,且外部组件不能修改组件的state),同时它也有”状态”这个属性,这个状态意思是能与用户交互的数据,比如用户输入,后台请求数据,而state数据的改变会导致界面重新渲染.简单来说,state是保存数据的对象,而对象的修改会导致界面重新被渲染即状态
下面以React.Component创建方式为便

  • 初始化数据只能在constructor中,唯一的地方,且可以直接赋值state
    例如
class TestComponent extends React.Component {
constructor(props) { super(props); // 设置 initial state this.state = { text: props.initialValue || 'placeholder' }; } }
  • 修改state数据只能使用setState方法,通过这个方法才能调用render函数实现渲染组件.不能直接赋值this.state
    语法setState(object nextState[, function callback])
    nextState:将要设置的新状态,该状态会和当前的state合并
    callback:可选参数,回调函数。该函数会在setState设置成功,且组件重新渲染后调用。
    注意,setState调用后不保证即时更新,React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。
  • 使用setState传入的数据会与老数据合并,同名变量覆盖,没有的则保留,如果想整个取代state数据,则使用replaceState
    语法:replaceState(object nextState[, function callback])
    参数与setState一样.

setState其实也可以接收函数做为参数

第一个参数是state的前一个状态值,第二个参数是props值
例如
//箭头函数
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
// 普通函数
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});

props

数据必须从父组件流向子组件,而props即是传递数据的载体,数据流是单向的,区别与Vue里数据绑定.

  • props数据不能被内部组件修改,外部能通过修改props达到重新渲染组件的效果
  • 组件从概念上看就是一个函数,可以接受一个参数作为输入值,这个参数就是props,所以可以把props理解为从外部传入组件内部的数据。
  • 修改props使用setProps,这个方法必需由父组件调用.
    语法:setProps(object nextProps[, function callback]).
    当然nextProps与旧的props是合并的,如果想替换,则使用replaceProps
    语法:replaceProps(object nextProps[, function callback]).

调用这2个方法会触发组件重新渲染

state与props区别

  • state是组件自己管理数据,控制自己的状态,可变;
  • props是外部传入的数据参数,不可变;
  • 没有state的叫做无状态组件,有state的叫做有状态组件;
  • 多用props,少用state。也就是多写无状态组件。

单向数据流

这是React核心重点,数据是单向的从父组件传递到子组件的,传递数据的载体即props对象,对象值由外部提供,上面也说到组件类似函数,props类似函数里的参数,数据从父组件通过props传递到每个子组件.

同时每个子组件都可以(并不是一定要定义个state对象)维护一个叫state的本地数据,这个state只属于当前组件,外部无法修改,它用于本地界面的渲染.动态交互.

refs属性

类似dom里id的作用.通过指定ref属性值将引用添加到this.refs里,然后可以通过this.refs直接拿到对象的dom.

例如<input ref="myInput" />
然后取值方式:this.refs.myInput,直接拿到input.
refs有很简单的使用方式
完整例子:

var TestComponent = React.createClass({      handleClick: function() {        // this.refs.myInput引用拿到组件里的input标签        this.refs.myInput.focus();      },      render: function() {        return (          
{
/**ref 属性添加一个组件的引用于到 this.refs**/}
); } });

事件处理程序

增加监听事件

react里事件处理不是使用addEventListener在DOM上添加处理程序.而是React组件内部添加.

调用监听程序使用{this.监听处理程序},命令使用驼峰命名
例如

class Test extends React.Component {
constructor(props) { super(props); // 这个绑定是必要的,使`this`在回调中起作用,有几个绑几个 this.handleClick = this.handleClick.bind(this); } handleClick(e) { console.log("666"); e.preventDefault(); } render() { return ( ); }}ReactDOM.render(
, document.getElementById('root'));

阻止事件冒泡

js里使用return false,React里使用e.preventDefault();

事件绑定

一般情况下,如果你引用一个后面没跟 () 的方法,例如 onClick={this.handleClick} ,那你就应该 绑定(bind) 该方法。

3种方式
第一种

constructor(props) {       super(props);       this.handleClick = this.handleClick.bind(this); //构造函数中绑定  }

第二种

//使用bind来绑定

第三种:

this.handleClick()}>
//使用arrow function来绑定

参数传递给事件处理程序

上面两个例子中,参数 e 作为 React 事件对象将会被作为第二个参数进行传递。通过箭头函数的方式,事件对象必须显式的进行传递,但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

防止组件渲染

显示组件的隐藏和展示,render返回null即可.

例如:

class Test extends React.Component {
render() { return null; }}

纯函数与非纯函数

纯函数的返回值只由它调用时的参数决定,它的执行不依赖于系统的状态.概念比较难懂,举例说明

例如
function add(a,b){
return a + b;
}
返回结果只由传入的参数决定,它们不会试图改变它们的输入,并且对于同样的输入,始终可以得到相同的结果。
同样的输入必会有同样的输出。
只要不改变参数值,不依赖函数体作用域外的变量计算都是纯函数,反之为非纯函数.
所有 React 组件都必须是纯函数,并禁止修改其自身 props

转载地址:https://chenyuan.blog.csdn.net/article/details/80709906 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:模块开发之Redux基础入门(六)
下一篇:模块开发之react-router使用(八)

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月24日 10时27分58秒