Code coverage report for lib/Page.js

Statements: 88.24% (30 / 34)      Branches: 100% (0 / 0)      Functions: 83.33% (10 / 12)      Lines: 88.24% (30 / 34)      Ignored: none     

All files » lib/ » Page.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227                1 1   1 1 1 1   1               1   6               1                                                 2         1                         2   2           2                                                               2                         2                                           3   3   2                                           3                                                       1   9   8   7   1 6     7   7       1    
/**
 * @file 页面
 * @author Leon(leon@outlook.com)
 *
 * @requires underscore
 * @requires react
 */
 
var u = require('underscore');
var React = require('react');
 
var ContextProvider = require('./component/ConextProvider');
var Context = require('./Context');
var componseReducer = require('./util/composeReducer');
var invariant = require('./util/invariant');
 
var events = require('./events');
 
/**
 * 页面
 *
 * @constructor
 * @param {*} initialState 初始数据状态
 */
function Page(initialState) {
 
    this.context = new Context(
        initialState,
        componseReducer(this.reducer)
    );
 
}
 
/** @lends Page.prototype */
var PagePrototype = {
 
    /**
     * 初始化
     *
     * 此方法只会被调用一次
     *
     * 处理请求的过程中,在页面实例化后,会被调用到此方法
     *
     * 此方法会派发一个init动作,并附带有getInitialState方法所返回的数据
     *
     * init动作提供给页面的初始数据剪裁的时机
     *
     * 但是只有在execute的情况下才会被调用,
     * 我们在bootstrap时传入的initialState是已经是剪裁好的数据
     * 也就是在server端预渲染后向client端同步数据状态的场景
     *
     *
     * @TODO 通过page的stage来保证此动作只能触发一次
     *
     * @public
     * @return {module:Page}
     */
    init: function () {
 
        this.dispatch({
            type: 'init',
            data: this.getState()
        });
 
        return this;
 
    },
 
    /**
     * 使用当前上下文中的数据,创建一个可提渲染使用的react元素
     *
     * @public
     *
     * @return {ReactElement}
     */
    createElement: function () {
 
        var view = this.view;
 
        return React.createElement(
            ContextProvider,
            {
                ei: this.context
            },
            function () {
                return React.createElement(view);
            }
        );
 
    },
 
    /**
     * 使用当前的上下文中的数据,将页面渲染到指定的元素
     *
     * 只能在客户端使用
     *
     * @public
     *
     * @param {Element} target DOM元素
     *
     * @return {module:Page}
     */
    render: function (target) {
 
        React.render(this.createElement(), target);
 
        return this;
    },
 
    /**
     * 使用当前的上下文中的数据,将页面渲染成字符串
     *
     * @public
     *
     * @return {string}
     */
    renderToString: function () {
        return React.renderToString(this.createElement());
    },
 
    /**
     * 返回当前上下文中的所有数据
     *
     * 此方法用于将服务器端的页面数据,同步到客户端上
     *
     * @public
     *
     * @return {*}
     */
    getState: function () {
        return this.context.getState();
    },
 
    /**
     * 派发一个动作,激活相应的数据剪切和视图更新
     *
     * @public
     *
     * @method module:Page#dispatch
     *
     * @param {(Object | Function)} action 动作
     *
     * @return {Object}
     *
     * @fires module:events~page-dispatch
     */
    dispatch: function (action) {
 
        /**
         * @event module:events~page-dispatch
         * @param {(Object | Function)} action 动作
         */
        events.emit('page-dispatch', action);
 
        this.context.dispatch(action);
 
        return action;
 
    },
 
    /**
     * 获取页面初始数据
     *
     * 页面在启动时,一般都会需要通过操作资源来获取数据作为初始数据
     *
     * 并且,这个过程一般还需要使用当前`请求`来完成决策
     *
     * 在app中接收到请求后会加载路由中指定的Page模块,将其实例化后,执行此方法
     *
     * @todo page需要有一个状态标识,new / inited / rendered / disposed
     *
     * @public
     *
     * @param {Object} request 请求
     *
     * @return {Promise}
     */
    getInitialState: function (request) {
        return {};
    },
 
    /**
     * 销毁页面
     *
     * @return {module:Page}
     */
    dispose: function () {
 
        /**
         * @event module:event~page-dispose
         */
        events.emit('page-dispose');
 
        // @TODO 补充销毁时的必要处理
 
        return this;
    }
 
};
 
/**
 * 生成Page子类
 *
 * @param {!Object} proto 扩展Page的配置
 * @return {Function}
 */
Page.extend = function (proto) {
 
    invariant(proto, 'create Page need options');
 
    invariant(proto.reducer, 'Pager must have a reducer');
 
    invariant(proto.view, 'Pager must have a view');
 
    function SubPage(initialState) {
        Page.call(this, initialState);
    }
 
    u.extend(SubPage.prototype, PagePrototype, proto);
 
    return SubPage;
 
};
 
module.exports = Page;