用TypeScipt和AMD模块化理念实现React官方教程(三)静态页面

来源:互联网 发布:在美国程序员的工资 编辑:程序博客网 时间:2024/06/01 16:39

现在我们可以象用C#开发那样来开发React应用了,我们的目的就是将 React官方教程整个迁移到typescript上实现:

创建第一个组件

在IDE的新建项中,我们可以找到TypeScript JSX文件,扩展名为tsx,如图:
这里写图片描述
在js目录下创建如下文件:
CommentBox.tsx
现在我们不需要象原教程那样命名.js文件了。完全可以按类来命名文件,这就是发挥TypeScript中Type 的力量的时候了!
文件内容如下:

/// <reference path="../typings/react/react-global.d.ts"/>export =CommentBox;class CommentBox extends React.Component<any, any> {    render() {        return <div className="commentBox">我是一个评论框。 </div>;    }}

注意HTML元素我们用小写字母开头,而自定义的Ract类我们用大写字母开头。
另外创建如下文件作为主文件:
main.tsx
文件内容如下:

/// <reference path="../typings/react/react-global.d.ts"/>import CommentBox = require("./CommentBox");ReactDOM.render(<CommentBox />, document.getElementById('content'));

这时点按运行,不出意外的话,浏览器将显示正常结果,内容为:我是一个评论框。

组合组件

让我们跟随示例创建CommentList 和 CommentForm如下:

CommentList.tsx
文件内容如下:

/// <reference path="../typings/react/react-global.d.ts"/>export =CommentList;class CommentList extends React.Component<any, any> {    render() {        return <div className="commentList">你好,我是一个评论列表。</div>;    }}

CommentForm.tsx

文件内容如下:

/// <reference path="../typings/react/react-global.d.ts"/>export =CommentForm;class CommentForm extends React.Component<any, any> {    render() {        return <div className="commentForm">你好,我是一个评论表单。</div>;    }}

接下去修改CommentBox.tsx,如下:

/// <reference path="../typings/react/react-global.d.ts"/>import CommentList = require("./CommentList");import CommentForm = require("./CommentForm");export =CommentBox;class CommentBox extends React.Component<any, any> {    render() {        return (            <div className="commentBox">                <h1>评论</h1>                <CommentList />                <CommentForm />            </div>        );    }}

使用props

现在让我们他建Comment组件,它将使用从父组件那里传入的数据。从父组件那里传入的数据将作为”属性(propery)”存在于子组件中。这些属性(properties)通过this.props访问。使用props,我们可以从CommentList传入的数据读取到Comment中,将生成一些标记:

Comment.tsx
文件内容如下:

/// <reference path="../typings/react/react-global.d.ts"/>export =Comment;class Comment extends React.Component<any, any> {    render() {        return (            <div className="comment">                <h2 className="commentAuthor">                    {this.props.author}                    </h2>                {this.props.children}            </div>        );    }}

组件属性

上面我们已经定义好了Comment 组件,我们想要将作者名字和评论文本传入。这样可以让我们为每个单独的评论重用想同的代码。现在让我们在CommentList中添加一些评论:
CommentList.tsx

/// <reference path="../typings/react/react-global.d.ts"/>import Comment = require('./Comment');export =CommentList;class CommentList extends React.Component<any, any> {    render() {        return (            <div className="commentList">            <Comment author="Eureka Chen">这是其中一个评论</Comment>            <Comment author="Jordan Walke">这是 *另一个* 评论</Comment>            </div>        );    }}

添加Markdown解析

在index.html我们引用了第三方的marked库,将Markdown文件转化为Html。将comment.tsx改写成:

/// <reference path="../typings/react/react-global.d.ts"/>/// <reference path="../typings/marked/marked.d.ts"/>export =Comment;class Comment extends React.Component<any, any> {    render() {        return (            <div className="comment">                <h2 className="commentAuthor">                    {this.props.author}                </h2>                { marked(this.props.children.toString())}            </div>        );    }}

注意在html中添加对maked.js的引用。
现在我们得到如图示的结果:
这里写图片描述

但是这里有个问题!从如图的输出中,直接输出了Html标签。我们需要他们生成Html。这是因为React防止XSS攻击,这里有个方法,但框架警告你不要这样。

/// <reference path="../typings/react/react-global.d.ts"/>/// <reference path="../typings/marked/marked.d.ts"/>export =Comment;class Comment extends React.Component<any, any> {    rawMarkup() {        var rawMarkup = marked(this.props.children.toString(), { sanitize: true });        return { __html: rawMarkup };    }    render() {        return (            <div className="comment">                <h2 className="commentAuthor">                    {this.props.author}                </h2>                <span dangerouslySetInnerHTML={this.rawMarkup() } />            </div>        );    }}

这是API特意让原生HTML难以插入,但marked可以利用这个后门。

挂接到数据模型

到现在我们是直接在源代码中插入评论。现在,让我们使用JSON数据插入评论中。最终这些数据会来自服务器,但现在,我们写在源码中:

我们在main.tsx中加入data,如下:

/// <reference path="../typings/react/react-global.d.ts"/>import CommentBox = require("./CommentBox");var data = [    { id: 1, author: "Eureka Chen", text: "这是一个评论" },    { id: 2, author: "Jordan Walke", text: "这是 *另一个* 评论" }];ReactDOM.render(<CommentBox data={data} />, document.getElementById('content'));

然后在CommentBox.tsx中改为:

/// <reference path="../typings/react/react-global.d.ts"/>import CommentList = require("./CommentList");import CommentForm = require("./CommentForm");export =CommentBox;class CommentBox extends React.Component<any, any> {    render() {        return (            <div className="commentBox">                <h1>评论</h1>                <CommentList data={this.props.data} />                <CommentForm />            </div>        );    }}

现在数据传到了CommentList,让我们动态生成评论,CommentList.tsx如下:

/// <reference path="../typings/react/react-global.d.ts"/>import Comment = require('./Comment');export =CommentList;class CommentList extends React.Component<any, any> {    render() {        var commentNodes = this.props.data.map(            function (comment) {                return (                    <Comment author={comment.author} key={comment.id}>                    {comment.text}                    </Comment>                );            });        return (            <div className="commentList">                {commentNodes}            </div>        );    }}

最终结果如下:
这里写图片描述

下一次我们开始讲从服务器获取数据。

1 0