React-引领未来的用户界面开发框架-读书笔记(八)

前端之家收集整理的这篇文章主要介绍了React-引领未来的用户界面开发框架-读书笔记(八)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

第16章 架构模式

React主要功能在于渲染HTML。可以将其看成是MVC中的V,它不会影响到组件中直接调用AJAX请求之类的操作:

var TakeSurvey=React.CreateClass({
    getInitialData:function(){
        return{
            survey:null
        };
    },componentDidMount:funciton(){
        $.getJSON('/survey/'+this.props.id,function(json){
            this.setState({survey:json});
        });
    },render:function(){
        return <div>{this.state.survey.title}</div> } });

路由

路由在单页面应用里为URL指定处理器函数。假设要为URL/surveys运行一个函数函数功能是从服务器加载用户,然后渲染<LIstSurveys>组件。

路由有很多种,在服务器端也存在路由,有一些路由可以在客户端和服务器端运行。

React仅仅是一个一个的渲染类库,没有路由的功能,不过有很多路由模块可以搭配React使用。

Backbone.Router:

Backbone是单页面应用类库,采用了MVX(Model-View-Whatever)架构。其中X指代控制器(Controller),通常指代的是路由。对Backbone来说就是如此。

Backbone是模块化的,你可以只用它的路由功能。它可以和React很好的搭配在一起使用。例如:

var SurveysRouter =Backbone.Router.extend({
    routes:{
        "surveys":"list"
    },list:function(){
        React.renderComponent(
            <ListSurveys />,document.querySelector('body')
        );
    }
});

路由需要处理URL中动态的部分和queryString。Backbone.Router具备这样的功能,示例如下:

@H_301_85@// surveys_routers.js
varSurveysRouter=Backbone.Router.extend({
    routes:{
        "list","surveys/:filter":list:function(filter){
        React.renderComponent(
            <ListSurveys filter={filter}/>,0)">'body) ); },});

在上面的例子中,给定一个比如/surveys/active这样的URL地址,那SurveysRouter#list的参数filter就是active。

Aviator

与Backbone.Router不同,Aviator是一个独立的路由类库。

在Aviator中,路由定义与RoutetTarget是相互独立的。即Aviator不关心RouteTarget的实现和行为,仅试着调用赋值在它上面的方法

比如这样一个RouteTarget:

// surveys_route_target.js
varSurveysRouteTarget={
    list:function(){
        React.renderComponent(
            <ListSurveys>,docment.querySelector('body');
        );
    }
};

与这个对象对应,需要有一份路由的配置(整个应用只能有一个唯一的路由配置),这个配置通常写在另一个独立的文件中。

// routes.js
Aviator.setRoutes({
    '/surveys':{
        target:UsersRouteTarget,0)">'/':'list'
    }
});
@H_301_85@//让Aviator把url分派到RouteTarget
Aviator.dispatch();

设置RouteTarget处理函数

// route.js
Aviator.setRoutes({
    '/surveys':{
        target:usersRouteTarget,0)">'list',0)">'/:filter':'list'
        }
});

@H_301_85@// surveys_route_target.js
varSurveysRouteTarget={
    list:function(request){
        React.renderComponent(
            <ListSurveys filter={request.param.filter}/>,doucument.querySelector('body')
        );
    }
}

Aviator有一个很棒的特性就是可以使用多个RouteTarget,例如下main这样的路由配置:

// route.js
Aviator.setRoutes({
    target:AppRouteTarget,0)">'/*':beforeAll,0)">'list'
        'list'
    }
});

对于'/surveys/active'这样的URL,Aviator会先调用appRouteTarget.beforeAll在调用UsersRouteTarget.list——只要匹配,Action的数量并不受限制。你还可以定义路由离开时的执行函数,当用户从匹配的路由离开时,定义过的执行函数会从内到外依次执行。

react-router

react-router不同于其他的路由,它完全是有ReactComponent构成的。

路由被定义成了组件,路由的处理器也是组件。

按照react-router的写法路由是这样的:

var appRouter=(
    <Routes location="history">
        <Route title="SurveyBuilder" handler={App}>
            <Route name="list" path="/"handler={ListSurveys}/}
            <Route title ="Add Survey to SurveyBuilder"name="add" path="/add_survey" handler={AddSurvey}/>
            <Route name ="edit" path="/surveys/:surveyId/edit" handler={EditSurvey}/>
            <Route name="take" path="/surveys/:surveyId"handler={TakeSurveyCtrl} />
            <NotFound title="page Not Found"handler={NotFoundHandler}/>
        </Route>
    </Routes>
);

每一个处理器就是一个对应着特定页面的组件。把上面的路由作为顶层的组件渲染来启动它。

React.renderComponent(
    appRouter,document.querySelector('body')
);

就像其他的路由一样,react-router也有类似的参数概念。 比如路由'/surveys/:surveyId'会把surveyId属性传给TakeSurveyCtrl组件。

Link是react-router提供的很酷的特性之一。你可以使用它来导航,它可以自己对应到路由上。而且它还能自动链接添加active样式,标记当前活动页面

使用react-router Link组件后组件看起来是这样的:

varMainNav=React.createClass({
    render:function(){
        retrun(
        <nav className='main-nav' role='navigation'>
            <ul className='nav navbar-nav'>
                <li><Link to='list'>All Surveys </link></li>
                <li><Link to="add" >AddSurvey</Link></li>
            </ul>
        </nav>
        );
    }
});

Om(ClojureScript)

Om是比较流行的React的ClojureScript接口。通过ClojureScript的不可变数据结构,Om可以飞快地重新渲染整个应用,而且每个操作都可以很容易地被存为快照,用来实现撤销等功能

Om组件看起来是这样:

(ns example
(:require [om.core :as om :include-macros true]
          [om.dom:as dom :include-macros true]))
(defn App[data owner]
    (reify
        om/IRender(render[this]
        (dom/h1 nil (:text data)))))
(om/rootApp {text "Survey Builder"}
    {:targer(. js/document (querySelector "body"))})

它将被渲染为<h1>SurveyBuilder</h1>

Flux

前面的架构模式都是随着React的开源而出现的。但Flux是React的原作者从一开始就设计好的。

Flux是Facebook引入的架构模式。它为React提供了一套单向数据流模式,这个模式很容易审查数据修改的过程和原因。实现Flux起来只需要很少的脚手架和代码

Flux由三个主要的部分组成:Store,Dispatcher和视图(即React Component)。Action作为创建Dispatcher的语义化接口的辅助方法,可以当做Flux模式的第四部分。

顶层的React组件类似于一个控制视图(Controller-View)。控制视图的组件与Store进行交流并协助其与子组件进行通信。这与iOS开发中的控制视图差别不大。

Flux模式里的每个部分都是独立的,强制进行了严格的隔离,通过隔离来保证每个部分都易于测试。

Flux的数据流

Flux使用的是单向数据流。这在已有的MVC框架中显得很特别,但也带来了一些独特的好处。因为Flux没有用双向绑定,所以他的应用很容易审查问题。状态是在Store(Store是Flux中数据的拥有者)中维护的,因此很容易跟踪。Store通过change方法传送数据,触发视图的渲染。用户的输入行为会出发Action通过Dispatcher进行分派,以此传送数据到专门处理特性Action的Store中。

Flux各个部分

Flux由实现特定功能的几个部分组成。在单向数据流中,Flux的每个部分获取上游输入的内容进行处理,然后向下游发送它的输出内容

  • Dispatcher——应用的中心仓库
  • Action——应用的DSL(Domain Specific Language)
  • Store——业务逻辑和数据交互
  • 视图——渲染应用组件树

Dispatcher

我们从Dispatcher开始,因为他是所有用户交互和数据流的中心仓库。在Flux模式当中Dispatcher是一个单例。

Dispatcher负责在Store上注册回调以及管理它们之间的依赖关系。用户的Action会流入Dispatcher。数据会传送到注册过Action的Store当中。

我们的Survey Builder中包含了一个相对简单但有效地管理单个Store的Dispatcher。然而,随着应用的扩张,你一定会遇到需要管理多个Store和他们之间依赖的情况。这种情况我们会在后面讨论。

Action

用户的角度看,这是Flux的起点。每个在UI上的行为都会创建一个被发送到Dispatcher的Action。

尽管Action不是Flux模式真正的部分,但他们构成了应用的DSL。用户操作被转化成为有含义的Dispatcher Action——Store可以依次调用相应的行为。

Store

Store负责封装应用的业务逻辑与应用数据交互。Store通过注册Action来选择相应哪些Action。Store把内部的数据通过更改时的change事件发送到React的组件当中。

保持Store严格的独立非常重要。

  • Store中包含应用的所有数据
  • 应用其他任何部分都不知道怎么操作数据——Store是应用中唯一的数据发生改变的地方
  • Store没有赋值——所有的更改都是由Dispatcher发送到Store的。新的数据随着Store的更改事件传送回到应用中。

控制视图

应用的组件层级一般会有一个顶层的组件负责与Store交互。简单的应用只有一个控制视图,复杂一些的应用可能会有多个。

管理多个Store

当一个Store依赖另一个的时候,数据的关系会变得复杂,比如一个Store要在另一个Store响应同一个Action之前先完成自身的调用

第17章 其他使用场景

React不仅是一个强大的交互式UI渲染类库,而且提供了一个用于处理数据和用户输入的绝佳方法。它倡导可重用并且易于测试的轻量级组件。不仅在Web应用中,这些重要的特性同样适用于其他的技术场景。例如:

  • 桌面应用
  • 游戏
  • 电子邮件
  • 绘图

本系列文章转自http://me.molinblog.com/,感谢作者。
http://me.molinblog.com/blog/developing-a-react-edge-8.html

猜你在找的React相关文章