[react002] component基本用法
1 什么是component
设计接口的时候,把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件。 这样,下次开发相同界面程序时就可以写更少的代码,也意义着更高的开发效率,更少的 Bug 和更少的程序体积。 Thinking in react 里面举了一个React 构建可搜索的商品数据的例子。
接下来我们将创建一个好玩的component来全面了解它的组成和运行机制, 回顾一下我们在001中的 public/index.html 它是直接引用了webpack生成的client.min.js(console里面打印文字)。 这样一点都不好玩,接来下我们从头开始构造一个完成的index.hmtl页面.
2. 定义html和引用的js入口
<html>
<head>
<meta charset="utf-8">
<title>React's Component Example</title>
</head>
<body>
<div id="app"></div>
<script src="client.min.js" type="text/javascript"></script>
</body>
</html>
在html里面定义一个id= "app" 的 div标签并引用client.min.js,这个html就是我们的入口。 时刻记得client.min.js是来自于webpack的entry: src/client.js 里面生成的。 所以我们就通过client.js来操作html中的div构建页面。
import React from 'react';
import ReactDom from "react-dom";
import Layout from "./component/Layout";
const app = document.getElementById("app");
ReactDom.render(<Layout />, app);
. 为什么要使用JSX语法?
. JSX和HTML的差异是什么?
这里你只需要知道 <Layout /> 是引用Layout Component。
页面的构成应该是(页面就是一个Tree,不要什么都堆在一起)
–Layout
-—Header
–title
-—Body
-—Footer
2.1. 定义最上层的Layout
import React from 'react';
import Footer from "./Footer";
import Header from "./Header"; export default class Layout extends React.Component {
render() {
return (<div>
<Header />
<Footer />
</div>);
};
}
component 必须要定义的render函数,render是核心, 它组装生成这个组件的HTML结构(使用原生HTML标签或者子组件)。
当调用的时候,会检测 this.props 和 this.state,返回一个单子级组件(注意只能是单个,所以我们用div把header和footer包了一层)。
该子级组件可以是虚拟的本地 DOM 组件(比如 <div /> 或者 React.DOM.div()),也可以是自定义的复合组件。
你也可以返回 null 或者 false 来表明不需要渲染任何东西。 实际上,react 渲染一个 <noscript> 标签来处理当前的差异检查逻辑。当返回 null 或者 false 的时候,this.getDOMNode() 将返回 null。
render() 函数应该是纯粹的,也就是说该函数不修改组件state, 每次调用都返回相同的结果,不读写 DOM 信息,也不和浏览器交互(例如通过使用setTimeout)。 如果需要和浏览器交互,在 componentDidMount() 中或者其它生命周期方法中做这件事。保持 render() 纯粹,可以使服务器端渲染更加切实可行,也使组件更容易被理解。
2.2. 定义Footer
import React from "react";
export default class Footer extends React.Component {
render() { return(<div> <h3> Footer: Building UI is a funny thing </h3> </div>);}
}
只是简单的把自己用h1显示出来
2.3. 定义Header
import React from "react";
import Title from "./Title";
export default class Header extends React.Component {
render() {
return(<div>
<Title />
<h3> Header: Component create a new world </h3>
</div> );
}
}
我们就可以看到它引用了Title
2.4. 定义Title
import React from "react";
export default class Title extends React.Component {
render() {
return(<div>
<h2> Title: Everything is Component </h2>
</div>
);
}
}
这上面都是静态的东西,根本就看不出component有什么值得炫酷的地方,只是显示了 title header footer。 离标题Title随着我们给定的输入框的文字变化还差得远 不过在开始之前, 应该先预习一下component api弄明白它的state和prop。
1. props就是component的属性,由外部通过JSX属性传入设置,一旦初始设置完成,就可以认为this.props是不可更改的,
所以不要轻易更改设置this.props里面的值(虽然对于一个JS对象你可以做任何事)。
2. state是component的当前状态,可以把component简单看成一个“状态机”,根据状态state 呈现不同的UI展示。
一旦状态(数据)更改,component就会自动调用render重新渲染UI,这个更改的动作会通过 this.setState方法来触发。
3. 一条原则:让component尽可能地少状态。这样组件逻辑就越容易维护。当更改这个状态(数据)需要更新组件UI的就可以认为是state
4. 无状态compoent, 我们上面的4个就是这种无状态的。
你也可以用纯粹的函数来定义无状态的组件(stateless function), 这种组件没有状态,没有生命周期,只是简单的接受props 渲染生成DOM 结构。无状态组件非常简单,开销很低,如果可能的话尽量使用无状态组件。
3. 有状态的component
3.1 父子间通信就是通过props属性来传递, 在父component中给子component设置props,然后子component就可以访问到父component的数据和方法.
3.2 非父子间通信使用全局事件Pub/Sub模式,在componentDidMount里面订阅事件,在 componentWillUnmount里面取消订阅,当收到事件触发的时候调用setState更新UI。
在Layout中把title和changetitle的函数都传给header component, 注意传给下一级方法时一定要显示的表明这个方法来自己于哪里 — bind(this)操作。
import React from 'react';
import Footer from "./Footer";
import Header from "./Header"; export default class Layout extends React.Component {
constructor(){
super();
this.state = {title: "welcome"};
}
changeTitle(title){
this.setState({title: title});
}
render() {
return (<div>
<Header changeTitle={this.changeTitle.bina(this)} title={this.state.title}/>
<Footer />
</div>);
};
}
Header接收到这个Title后如何处理
import React from "react";
import Title from "./Title";
export default class Header extends React.Component {
handleChange(e) {
const title = e.target.value;
this.props.changeTitle(title);
}
render() {
return(<div>
<Title title={this.props.title}/>
<input value={this.props.title} onChange= {this.handleChange.bind(this)}/>
<input value={this.props.title} onChange= {this.handleChange.bind(this)}/>
</div> );
}
}
Header把title又往下传递给应该处理的Title Component, 自己又建了两个输入框,初始值为title,然后再定义一个onChange事件
Title接到title后只需要把它显示成title就行了,这就是它要做的事!
import React from "react";
export default class Title extends React.Component {
render() {
return(<div>
<h2> {this.props.title} </h2>
</div>
);
}
}
总结上面的流程就是Layout把自己changeTitle的方法和title的属性先传给Header,Header再把他们传给Title。
这里发生了一件非常奇妙的事,我们在Layout Header Title 里都有state, 我们通过input输入框输入文字触发Layout的SetState方法, 结果所有的State里面的title都跟着变化啦,这就是virtual DOM的好处,react把操作真实DOM的操作又封装了一层,让我们不用操心哪一个DOM应该更新这种事。 JS很快,慢的只是刷新DOM里面的tree, 而且繁锁, 但是react把刷新DOM的操作透明了,简直太贴心啦。
我们打开chrome developer tool 里面timeline的 Rendering下的Enable paint flashing,看看我们在输入的时候是哪一些DOM刷新啦。
可以看出它只是刷新应该刷新的Title Header和input
通过这一章节我们掌握到了什么是component, component的state props及他们之前的区别,父子component之间如何通信。
4 扩展阅读
[react002] component基本用法的更多相关文章
- salesforce 零基础学习(六十一)apex:component简单使用以及图片轮转播放的实现
有的时候,我们项目有可能有类似需求:做一个简单的图像轮转播放功能,不同的VF页面调用可以显示不同的图片以及不同的图片描述.这种情况,如果在每个页面单独处理相关的图像轮转播放则显得代码特别冗余,此种情况 ...
- spring 组件自动装载示例(@ComponentScan,@Component,@Scope)
今天学习spring的bean组件装载功能,个人不太喜欢xml文件一个个配置bean的方式,所以主要学习测试注解式的自动装载方式.下面将简单说明下@Component的用法,简单入门示例献给大家. ...
- 四、Spider用法
本文转载自以下链接: https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/spiders.html https://doc.scrapy.org ...
- Play1+angularjs+bootstrap ++ (idea + livereload)
我的web开发最强组合:Play1+angularjs+bootstrap ++ (idea + livereload) 时间 2012-12-26 20:57:26 Freewind.me原文 ...
- JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)
前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...
- vue中动态加载组件+开发者模式+JS参数值传递和引用传递
今天写vue里面通过接口反参动态加载组件时候 跟着同学...学习到了 一.先说说vue 内置组件 component 的用法 component组件可以来专门用来进行组件的切换,使用is来绑定你的组件 ...
- 微软BI SSIS 2012 ETL 控件与案例精讲课程学习方式与面试准备详解
开篇介绍 微软BI SSIS 2012 ETL 控件与案例精讲 (http://www.hellobi.com/course/21) 课程从2014年9月开始准备,到2014年12月在 天善BI学院 ...
- DDD中的值对象如何用NHibernate进行映射
原文:DDD中的值对象如何用NHibernate进行映射 <component/>是NHibernate中一个有趣的特性,即是用来映射DDD(Data-Display-Debuger)概念 ...
- 从零开始的vue学习笔记(四)
组件注册 组件名 Vue.component('my-component-name', { /* ... */ }) 这里的my-component-name就是组件名,组件名的取法可以参考指南 ke ...
随机推荐
- EqualsBuilder 类的使用
apache的commons-lang包提供了一个EqualsBuilder类,提供了基本属性.数组.对象等比较操作的封装,可以辅助实现对象的equals(Object)方法. 这个类的使用比较简单, ...
- CentOS iptables防火墙的基本应用讲解
iptables是Linux下不错的防火墙软件,本文主要给大家介绍下iptables的安装.规则增加和清除.开放指定端口.屏蔽指定ip和ip段等CentOS下iptables的基本应用. 一.ipta ...
- 关于在github上 下载源码 clone 非 master 分支的代码
https://blog.csdn.net/u012302552/article/details/80680497
- SpringBoot入门(2)
一.上一篇 上一篇最后说到,可以把启动类放到非上级目录“@Componentscan这个注解后面指定扫描的包名(value=“com.zbb”)”,这里的value是一个数组,我们可以写多个目录,进行 ...
- c#二维码建立与识别
QrCodeEncodingOptions options = new QrCodeEncodingOptions(); options.CharacterSet = "UTF-8" ...
- vb.net 与 c# 运算符区别
vb.net vs c# 详细的Operators运算符区别 vb.net ===================== Comparison = < > <= >= <& ...
- Linux学习---linux系统下安装配置Jenkins
1.首先准备java环境,安装JDK 2.下载jenkins至Linux服务器 下载地址:https://wiki.jenkins-ci.org/display/JENKINS/Installing+ ...
- 54. Spiral Matrix (Graph)
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...
- MYSQL 存储过程通用
返回随机时间 函数 )) ) CHARSET utf8 BEGIN )); -- 随机天数 60天以内随机天数 )); -- 随机小时 ));-- 随机分 ));-- 随机秒 ); IF type = ...
- UNITY录制视屏解决方案 - ShareREC For Unity3D
注意buildSetting里面,AutoGraphic改成opengl es2,否则魅蓝手机上容易出现1/4屏 一.导入项目 1.到Mob官网下载ShareREC For Unity3D 的SDK包 ...