如何学习用Typescript写Reactjs

React.js入门学习第一篇
作者:小蚊
字体:[ ] 类型:转载 时间:
这篇文章主要为大家介绍了React.js入门学习第一篇,详细解析React.js基础知识,全方位的了解React.js,感兴趣的小伙伴们可以参考一下
一、JSX介绍
JSX=Javascript XML,是一种在React组件内部构建标签的类XML语法。React在不使用JSX的情况下一样可以工作,但是使用JSX可以提高组件的可读性,增强JS语义,结构清晰,抽象程度高,代码模块化。因此推荐在React中使用JSX。
1、元素名首字母大写
2、符合嵌套规则
3、可以写入求值表达式
4、驼峰式命名
5、不能使用javascript原生函数的一些关键词,如for和class。需要替换成htmlFor和className
③使用方法
1、使用动态值:JSX将两个花括号之间的内容{...}渲染为动态值,花括号指明了一个javascript上下文环境,花括号里面可以是一个变量,也可以是函数。 例如:
var name=“winty”;
&p&{name}&/p&
function date(d){
d.getFullYear(),
d.getMonth()+1,
d.getDate()
].join('-);
&p&{date(new Date()}&/p&
2.注释:首先,在子节点中注释要用大括号包裹起来,然后就可以单行注释/**/,也可以多行注释//。
var Hello=React.createClass({
render:function(){
return &p name="winty"& //set name
Hello ,World
3.使用CSS内联样式
var style={
color:#000;
React.render(&div style={style}&....&/div&,document.body);
4.使用条件判断
//方法1,三目运算符
var Hello=React.createClass({
render:function(){
return &p&Hello,{this.props.name?this.props.name : "LuckyWinty"}&/p&
//方法2,if-else语句
var Hello1=React.createClass({
getName:function(){
if(this.props.name)
return this.props.
return "LuckyWinty";
render:function(){
return &p&Hello,{this.getName}&/p&
//方法3,使用逻辑||运算符
var Hello3=React.createClass({
render:function(){
return &p&Hello,{this.props.name||"LuckyWinty"}&/p&
④非DOM属性介绍
JSX中有3个非DOM属性,分别是:dangerouslySetInnerHTML、ref、key。
dangerouslySetInnerHTML:在JSX中直接插入HTML代码,但是如果能避免使用这个属性则尽量避免使用。
不合时宜的使用 innerHTML 可能会导致 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击 的原因之一。
在彻底的理解安全问题后果并正确地净化数据之后,生成只包含唯一 key __html 的对象,并且对象的值是净化后的数据。例如:
function createMarkup() {
return {__html: 'First & Second'};
&div dangerouslySetInnerHTML={createMarkup()} /&
ref:父组件引用子组件,你可以通过在属性中设置期望的引用名来定义一个引用。例如:
render:function(){
return &div&
&input ref="MyInput" .../&
//然后你就可以在组件中的任何地方使用this.refs.myInput获取这个引用了
key:是一个可选的唯一标识符,通过给组件设置一个独一无二的键,并确保它在一个渲染周期中保持一致,使得React能够更只能地决定应该重用一个组件还是销毁并重建一个组件,进而提高渲染性能。例如:
var Hello3=React.createClass({
render:function(){
return &ul&
&li key="1"&1&/li&
&li key="2"&2&/li&
&li key="3"&3&/li&
二、React组件生命周期详解
组件本质上就是状态机,输入确定,输出一定确定。状态和结果一一对应,从而使程序变得直观。状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出响应。可以用事件的思路来理解状态,但是事件与事件之间互相独立,但是不同状态之间可能会互相影响。
组件的所有状态结合起来就成了组件的生命周期。即:初始化阶段-&运行中阶段-&销毁阶段。&
不同生命周期内可以自定义的函数
初始化阶段:
①getDefaultProps:获取默认属性,只调用一次,是在createClass之后调用的。实例之间共享引用
②getInitialState:初始化每个实例的特有初始化状态
③componentWillMount:mout就是装载的意思,这个方法的意思就是说组件即将被装载到页面中,也是render之前最后一次修改状态的机会
④render:组件在render函数生成虚拟节点,最后由react将虚拟节点变成真正的节点渲染到页面上。只能访问this.props和this.state,只有一个顶层组件,最好不要修改状态和DOM输出。
⑤componentDidMount:组件被装载后才会被调用,也就是说调用这个方法的时候,组件已经被渲染到了页面上,这个时候可以修改DOM
这五个函数的执行顺序就是从上到下的。需要注意的是getDefaultProps只会在组件的第一个实例被初始化的时候被调用,也就是说第二个实例之后都是从getInitialState开始调用。同一个组件的所有实例的默认属性都是一样的。
主要测试代码:
&script type="text/babel"&
var Hello=React.createClass({
getDefaultProps:function(){
console.log("getDefaultProps, 1");
getInitialState:function(){
console.log("getInitialState, 2");
componentWillMount:function(){
console.log("componentWillMount, 3");
render:function(){
console.log("render, 4");
return &p&Hi,LuckyWinty!&/p&
componentDidMount:function(){
console.log("componentDidMount, 5");
React.render(&Hello&&/Hello&,document.body);
运行结果:
运行中阶段:
①componentWillReceiveProps:这个函数在组件即将接收到属性时触发的,或者是父组件的属性发生变化时,属性在传送到组件之前,开发者有机会通过这个函数去处理属性。比如修改,更新内部状态等。
②shouldComponentUpdate:当组件接收到新属性或者新状态的时候触发的。这个是一个疑问函数,也就是说我们可以告诉react不去更新某个组件。因为有时候属性或者状态并不会导致组件发生更新。在组件不需要更新的情况下,手动使shouldComponentUpdate返回false,这样react就不需要再经过render和diff算法去判断是否要更新,从而提高性能。
③componentWillUpdate:render触发之前触发,更新组件,不能修改属性和状态
④render:组件在render函数生成虚拟节点,最后由react将虚拟节点变成真正的节点渲染到页面上,只能访问this.props和this.state,只有一个顶层组件,最好不要修改状态和DOM输出。
⑤componentDidUpdate:render之后,真正的DOM被渲染之后调用
备注:这五个函数的执行顺序也是从上到下的。这个的测试代码已上传至:,欢迎参考!
&销毁阶段:
①componentWillUnmount:这个函数在销毁操作真正执行之前调用,给开发者最后的机会进行一些清理工作。
三、属性、状态的含义和用法
属性的含义:
props=properties,属性是不可以由组件自己进行修改的,组件的属性是由父组件传递进来的。
属性的用法:
一)、键值对
&Hello name="winty"/& 字符串
&Hello name={123}/& 大括号包裹的求值表达式
&Hello name={[1,2,3]}/& 传入数组
&Hello name={winty}/& 变量
二)、展开定义(个人认为就是对象式定义)
var props={
one:"123",
这样定义的话,理论上使用应该是one={props.one}这样调用,但是这样写起来比较繁琐,而且如果数据被修改,就需要对应修改相应的赋值,并且无法动态地设置属性,所以react中添加了一种展开语法:
&Hello {...props}/&&&& //也就是三个点加上对象名称。
这样使用展开语法,react就会自动把对象中的变量和值当作是属性的赋值,所以Hello实际上就拿到了one、two两个属性,如果没有三个点的话,Hello拿到的实际上就是props对象,使用的时候还需要自己从中取出变量和值
三)、调用react提供的setProps()函数(几乎不用)
var instance=React.render(&HelloWorld&&/HelloWorld&,document.body);
instance.setProps({name:"winty"});
状态的含义:
state,状态是由事物自行处理、不断变化的
状态的用法:
getInitialState:初始化实例的状态
setState:更新组件状态,一旦更新了状态,那么就会触发diff算法,检查内容是否发生变化,若有变化则更新组件,否则就不用。&
属性和状态对比
相似点:都是纯JS对象、都会触发render更新、都具有确定性。
属性和状态区分:组件在运行时需要修改的数据就是状态&
四、React中事件的用法
事件处理函数:React绑定事件处理器的方法和HTML语法非常类似,所有的事件在命名上与原生的javascript规范一致,并且会在相同的情境下触发。
handleClick:function(){
onClick={this.handleClick}&
各类事件详细说明:
①移动设备上的触摸事件:onTouchCancel、onTouchEnd、onTouchMove、onTouchStart
②键盘类事件:onKeyDown、onKeyPress、onKeyUp
③剪切类事件:onCopy、onCut、onPaste
④表单类:onChange//内容变化即触发、onInput//输入框、onSubmit//禁止表单默认跳转行为
⑤事件:onFocus、onBlur
⑥UI元素类:onScroll
⑦鼠标滚动事件:onWheel
⑧鼠标类型:onClick、onContextMenu//右键菜单、onDoubleClick //双击、onMouseDown、onMouseEnter、onMouseLeave、onMouseMove、onMouseOut、onMouseOver、onMouseUp
⑨拖拽事件:onDrop、onDrag、onDragEnd、onDragEnter、onDragExit、onDragLeave、onDragOver、onDragStart
事件对象介绍
使用方法:就是在编写事件对象处理函数的时候,添加一个参数。拿到这个对象之后,就通过对象的属性来可以获取一些信息。
handleChange:function(event){
console.log(event.target.value);
示例中,event就是事件对象,event.target就是事件对象的属性,就是对应的DOM元素,拿到这个元素之后再获取它的值。
事件对象属性
通用属性:
&其他不同类型的事件有不同的属性,简单了解一下
知道了事件的一些属性,我们就可以很方便地在React中获取这些属性,进行一些逻辑的处理,实现一些复杂的业务功能、页面效果等。
例如:我们可以利用鼠标事件属性,实时显示鼠标在某个区域的坐标:
&script type="text/jsx"&
var HelloWorld = React.createClass({
getInitialState: function () {
handleMouseMove: function (event) {
this.setState({
x: event.clientX,
y: event.clientY
render: function () {
return &div onMouseMove={this.handleMouseMove} style={{
height: '500px',
width: '500px',
backgroundColor: 'gray'
{this.state.x + ', ' + this.state.y}
React.render(&HelloWorld&&/HelloWorld&, document.body);
x组件协同使用的定义:组件的协同本质上就是对组件的一种组织、管理方式。
组件协同使用的目的:逻辑清晰、代码模块化、封装细节、代码可复用。
组件协同使用的方式:
①组件嵌套使用:也就是说,用一个父组件把子组件包裹起来,本质就是父子关系。如下图描述:
实例代码:
var React = require('react');
var CommentList=require('./CommentList.jsx');
var CommentForm=require('./commentFrom.jsx');
var CommentBox = React.createClass({
render: function() {
&div className="commentBox"&
&h1&Comments&/h1&
&CommentList /& //这是一个组件
&CommentForm /& //这是另一个组件
module.exports = CommentB
父子组件之间的通信:
父组件-&子组件:通过属性,父组件把数据通过属性来传递给子组件
子组件-&父组件:本质上,子组件不能向父组件通信。但是可以间接地通过触发事件来通信,也就是委托。
嵌套组合缺点:
父子关系的具体实现需要经过深思熟虑,贸然编写将导致关系混乱、代码难以维护
无法掌握所有细节,使用者只知道组件用法,不知道实现细节,遇到问题难以修复
②Mixin:也就是可以把相同的代码抽象出来,封装成一个函数,然后再调用。
Mixin的目的:横向抽离出组件的相似代码
相似概念:面向切向面编程、插件
实例代码:
var Time=React.createClass({
mixins:[IntervalMixin(1000)],
getInitialState:function(){
return {secondElapsed:0};
onTick:function(){
this.setState({secondElapsed:this.state.secondElapsed+1});
render:function(){
&div&Seconds Elapsed:{this.state.secondsElapsed}&/div&
mixin相当简单,它们就是混合进组件类中的对象而已。React在这方面实现得更加深入,它能防止静默函数覆盖,同时还支持多个mixin混合。但是这些功能在别的系统中可能引起冲突。例如:
React.createClass({
getInitialState:function(){ return {a:1}}
getInitialState:function(){ return {b:2}}
这样在mixin和组件类中同时定义了getInitialState方法,得到的初始state是{a:1,b:2}.如果mixin中的方法和组件类中的方法返回的对象中存在重复的键,React会抛出一个错误来警示这个问题。
&六、React中的双向绑定
React创立的理念跟angular那些框架就是不同的,React是单向数据绑定的。那么怎么实现像angular那样的双向绑定效果呢?看代码:
&!DOCTYPE html&
&html lang="zh-cn"&
&meta charset="UTF-8"&
&title&React中的双向数据绑定&/title&
&script src="./react-0.13.2/react-0.13.2/build/react-with-addons.js"&&/script&
&script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"&&/script&
&script type="text/jsx"&
var BindingMixin = {
handleChange: function(key) {
var that = this
var newState = {}
return function(event) {
newState[key] = event.target.value
that.setState(newState)
var BindingExample = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
comment: '',
render: function() {
return &div&
&input type="text" placeholder="请输入内容" valueLink={this.linkState('text')} /&
&textarea valueLink={this.linkState('comment')}&&/textarea&
&h3&{this.state.text}&/h3&
&h3&{ment}&/h3&
React.render(&BindingExample&&/BindingExample&, document.body);
效果图(没有CSS样式,有点不优雅,见谅):
以上就是本文的全部内容,希望对大家的学习有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具课程加载中...
服务热线:400-678-8266TypeScript 基本语法
1.基本数据类型
interface ICar {
class Bus implements ICar {
constructor() {
this.color = &Blue&;
var bus = new Bus();
alert(bus.color);
//继承接口
interface Shape {
interface PenStroke {
interface Square extends Shape, PenStroke {
sideLength:
interface ICar {
safetyDevice?://实现类无需实现
function MoveCar(car:ICar){
if(car.safetyDevice)
alert(&The car is safe&);
alert(&The car is not safe&);
interface ICar {
class Bus implements ICar {
constructor() {
this.color = &Blue&;
var bus = new Bus();
alert(bus.color);
//继承接口
interface Shape {
interface PenStroke {
interface Square extends Shape, PenStroke {
sideLength:
interface ICar {
safetyDevice?://实现类无需实现
function MoveCar(car:ICar){
if(car.safetyDevice)
alert(&The car is safe&);
alert(&The car is not safe&);
interface ICar {
class Bus implements ICar {
constructor() {
this.color = &Blue&;
var bus = new Bus();
alert(bus.color);
//继承接口
interface Shape {
interface PenStroke {
interface Square extends Shape, PenStroke {
sideLength:
interface ICar {
safetyDevice?://实现类无需实现
function MoveCar(car:ICar){
if(car.safetyDevice)
alert(&The car is safe&);
alert(&The car is not safe&);
4.模块(Modules)
作用:1.防止命名空间冲突;2.将一个功能模块很容易的划分到不同文件中,更容易维护;
module MyDemo {
export interface IDemo {
export class Demo implements IDemo {
module Shapes {
export module Polygons {
export class Triangle { }
export class Square { }
import polygons = Shapes.P
var sq = new polygons.Square(); // 类似于 'new Shapes.Polygons.Square()'
5.函数(Function)
function add(x:number, y:number):number {
return x +
var myAdd = function (x:number, y:number):number {
return x +
完整的函数类型
var myAdd:(x:number, y:number)=&number =
function (x:number, y:number):number {
return x +
为了增强可读性,给参数x、y具有实际的意义,可以这样写
var myAdd:(baseValue:number, increment:number)=&number =
function (x:number, y:number):number {
return x +
第二部分number 是一个返回类型,如果无需返回类型,请使用 'void'
第三部分的function 参数类型,根据上下文类型进行推断,可以省略
var myAdd:(baseValue:number, increment:number)=&number =
function (x, y) {
return x +
//可选参数
function buildName(firstName:string, lastName?:string) {
if (lastName)
return firstName + & & + lastN
else return firstN
var result1 = buildName(&Bob&);
//默认参数
function buildNameDefaultValue(firstName: string, lastName = &Smith&) {
return firstName + & & + lastN
var result1 = buildNameDefaultValue(&Bob&);
例如在C#中,方法参数定义使用param int[],调用方法时,就可以传递多个int类型的参数
在TypeScript中
function buildNameRest(firstName:string, ...restOfName:string[]) {
return firstName + & & + restOfName.join(& &);
var employeeName = buildNameRest(&Joseph&, &Samuel&, &Lucas&, &MacKinzie&)
Lambads 和this关键字
var people={
name:[&张三&,&李四&,&王五&,&赵六&],
getName:function(){
return function(){
var i=Math.floor(Math.random()*4);
n:this.name[i]
var pname=people.getName();
alert(&名字:&+pname().n);
调用发现getName中的this关键字指向的是getName,访问不到外部的name属性
所以我们修改为:
var people = {
name: [&张三&, &李四&, &王五&, &赵六&],
getName: function () {
var i = Math.floor(Math.random() * 4);
n: this.name[i]
var pname = people.getName();
alert(&名字:& + pname().n);
function student(name:string):
function student(age:number):
function student(numberorage:any):any {
if (numberorage && typeof (numberorage) == &string&)
alert(&姓名&);
alert(&年龄&);
student(&Tom&);//alert(&姓名&)
student(15);//alert(&年龄&)
function identity&T&(arg: T): T {
//数组泛型
function identity&T&(arg: T[]): T[] {
console.log(arg.length);
泛型类型(通用的函数类型)
function identity&T&(arg:T):T {
var myIdentity:&T&(arg:T)=&T =//T也可使用其他字母表示
//也可以这么写
//var myIdentity:{&T&(arg:T): T} =
interface GenericIdentityFn {
&T&(arg:T): T;
function identity&T&(arg:T):T {
var myIdentity:GenericIdentityFn =
class GenericNumber&T& {
zeroValue:T;
add:(x:T, y:T) =& T;
var myGenericNumber = new GenericNumber&number&();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
return x +
interface Lengthwise {
function loggingIdentity&T extends Lengthwise&(arg:T):T {
console.log(arg.length);
loggingIdentity(3);//error
loggingIdentity({length: 10, value: 3});
//只要类型包含length属性即可
泛型类约束
class Findable&T&
function find&T&(n: T, s: Findable&T&) {
interface Box {
interface Box {
var box: Box = {height: 5, width: 6, scale: 10};
module Animals {
exportclass Zebra { }
module Animals {
exportinterface Legged { numberOfLegs: }
exportclass Dog { }
module Animals {
exportinterface Legged { numberOfLegs: }
exportclass Zebra { }
exportclass Dog { }
合并模块和类
class Album {
label:Album.AlbumL
module Album {
export class AlbumLabel {
合并模块和函数
function buildLabel(name:string):string {
return buildLabel.prefix + name + buildLabel.
module buildLabel {
export var suffix = &&;
export var prefix = &Hello, &;
alert(buildLabel(&Sam Smith&));
合并模块与枚举
enum Color {
green = 2,
module Color {
export function mixColor(colorName:string) {
if (colorName == &yellow&) {
return Color.red + Color.
else if (colorName == &white&) {
return Color.red + Color.green + Color.
else if (colorName == &magenta&) {
return Color.red + Color.
else if (colorName == &cyan&) {
return Color.green + Color.
类与类不能合并
接口与类不能合并
变量与类不能合并}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信