├── .gitignore
├── README.md
├── flux-demo
├── README.md
├── flux-demo-server
│ ├── index.js
│ ├── package.json
│ └── route
│ │ └── index.js
└── flux-demo-static
│ ├── gulpfile.js
│ ├── package.json
│ └── src
│ ├── css
│ └── bootstrap.css
│ ├── index.html
│ └── js
│ ├── action
│ └── flux-demo.js
│ ├── component
│ ├── content.js
│ ├── dropdown.js
│ └── flux-demo.js
│ ├── dispatcher
│ └── dispatcher.js
│ ├── lib
│ ├── babel-external-helpers.js
│ ├── event-emitter.js
│ ├── fetch.js
│ ├── flux.js
│ ├── promise.js
│ └── react.js
│ └── store
│ └── flux-demo.js
└── react-router-demo
├── .gitignore
├── README.md
├── gulpfile.js
├── package.json
└── src
├── index.html
└── js
├── component
├── about.js
├── app.js
├── concat.js
└── list.js
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | flux-demo/flux-demo-static/node_modules/
2 | flux-demo/flux-demo-server/node_modules/
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Demo
2 |
3 | 我的博客中 [React 系列文章](http://stylechen.com/category/react) 中的 Demo 都在本项目中。
--------------------------------------------------------------------------------
/flux-demo/README.md:
--------------------------------------------------------------------------------
1 | # Flux Demo
2 |
3 | `flux-demo-server` 为 node 服务,提供测试数据。
4 |
5 | `flux-demo-static` 为前端部分,Demo 代码都在这个文件夹下。
6 |
7 | ### 启动项目
8 |
9 | 分别进入 2 个目录,执行 `npm install` 安装依赖,依赖安装结束后执行 `npm start` 就启动了项目,在浏览器中输入 `http://127.0.0.1:3001` 即可访问。
10 |
11 | 本 Demo 在 [React 应用的架构模式 Flux](http://stylechen.com/react-flux.html) 有详细的讲解。
12 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-server/index.js:
--------------------------------------------------------------------------------
1 | var koa = require( 'koa' );
2 | var logger = require( 'koa-logger' );
3 | var router = require( 'koa-router' )();
4 | var indexRoute = require( './route/index' );
5 |
6 | var app = koa();
7 |
8 | app.use( logger() );
9 |
10 | indexRoute( router );
11 |
12 | app.use(router.routes());
13 |
14 | app.listen( 3002, '127.0.0.1' );
15 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fulx-demo-server",
3 | "version": "0.1.0",
4 | "author": "chenmnkken@jumei.com",
5 | "engines": {
6 | "node": ">= 0.8.0"
7 | },
8 | "scripts": {
9 | "start": "DEBUG=koa* node --harmony index.js",
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "dependencies": {
13 | "koa": "1.0.0",
14 | "koa-logger": "1.3.0",
15 | "koa-router": "5.2.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-server/route/index.js:
--------------------------------------------------------------------------------
1 | var mockData = {
2 | react: 'React is a JavaScript library for building user interfaces.',
3 |
4 | angular: 'Angular is a development platform for building mobile and desktop web applications. This is the repository for Angular 2, both the JavaScript (JS) and Dart versions.',
5 |
6 | polymer: 'Polymer lets you build encapsulated, re-usable elements that work just like HTML elements, to use in building web applications.'
7 | };
8 |
9 | var index = function(router){
10 | router.get('/api/:browsers', function* (){
11 | this.set('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
12 | this.set('Access-Control-Allow-Origin', '*');
13 | this.type = 'application/json';
14 | this.body = {
15 | data: mockData[this.params.browsers]
16 | }
17 | });
18 | };
19 |
20 | module.exports = index;
21 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var gutil = require('gulp-util');
3 | var babelify = require('babelify');
4 | var browserify = require('browserify');
5 | var watchify = require('watchify');
6 | var cacheify = require('cacheify');
7 | var levelup = require('levelup');
8 | var source = require('vinyl-source-stream');
9 | var less = require('gulp-less');
10 | var connect = require('gulp-connect');
11 | var LessPluginAutoPrefix = require('less-plugin-autoprefix');
12 | var autoprefix= new LessPluginAutoPrefix({ browsers: ['last 2 versions'] });
13 | var db = levelup('./.cache');
14 |
15 | var srcRoot = 'src';
16 | var jsSrcPath = './src/js/component/flux-demo.js';
17 | var jsDestPath = './src/js';
18 |
19 | var browserOpts = {
20 | entries: [jsSrcPath],
21 | debug: true,
22 | insertGlobals: true,
23 | detectGlobals: false
24 | };
25 |
26 | gulp.task('connect', function () {
27 | connect.server({
28 | root: [srcRoot],
29 | port: 3001,
30 | livereload: true,
31 | fallback: 'src/index.html'
32 | });
33 | });
34 |
35 | gulp.task('watch-html', function () {
36 | gulp.watch(srcRoot + '/**/*.html', function () {
37 | return gulp.src(srcRoot + '/**/*.html')
38 | .pipe(connect.reload());
39 | });
40 | });
41 |
42 | var bundle = function () {
43 | return watcher.bundle()
44 | .on('error', function (err) {
45 | console.log(err.message);
46 | console.log(err.stack);
47 | })
48 | .pipe(source('bundle.js'))
49 | .pipe(gulp.dest(jsDestPath))
50 | .pipe(connect.reload());
51 | };
52 |
53 | var babelifyCache = cacheify(babelify.configure({
54 | externalHelpers: true,
55 | stage: 0
56 | }), db);
57 |
58 | var bundler = browserify(browserOpts)
59 | .transform(babelifyCache);
60 |
61 | var watcher = watchify(bundler)
62 | .on('update', bundle)
63 | .on('log', gutil.log);
64 |
65 | gulp.task('watch-js', bundle);
66 | gulp.task('watch', ['watch-js', 'watch-html'])
67 | gulp.task('default', ['connect', 'watch']);
68 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flux-demo-static",
3 | "version": "0.1.0",
4 | "description": "",
5 | "scripts": {
6 | "start": "gulp",
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "chenmnkken@gmail.com",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "babelify": "6.1.2",
13 | "browserify": "10.2.4",
14 | "cacheify": "0.4.1",
15 | "gulp": "3.9.0",
16 | "gulp-connect": "2.2.0",
17 | "gulp-less": "3.0.3",
18 | "gulp-util": "3.0.5",
19 | "less-plugin-autoprefix": "1.4.2",
20 | "leveldown": "1.4.1",
21 | "levelup": "1.2.1",
22 | "vinyl-source-stream": "1.1.0",
23 | "watchify": "3.2.2"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Flux Demo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/action/flux-demo.js:
--------------------------------------------------------------------------------
1 | import dispatcher from '../dispatcher/dispatcher';
2 |
3 | const fluxDemoActions = {
4 | fetchIntroduction (name, path) {
5 | const url = `http://127.0.0.1:3002${path}`;
6 |
7 | dispatcher.dispatchAsync(url, {
8 | request: 'FETCH_INTRODUCTION',
9 | success: 'FETCH_INTRODUCTION_SUCCESS',
10 | failure: 'FETCH_INTRODUCTION_ERROR'
11 | },{
12 | name
13 | });
14 | }
15 | };
16 |
17 | export default fluxDemoActions;
18 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/component/content.js:
--------------------------------------------------------------------------------
1 | import fluxDemoStore from '../store/flux-demo';
2 |
3 | class Content extends React.Component {
4 | constructor (props) {
5 | super(props);
6 |
7 | this.state = {};
8 | }
9 |
10 | componentDidMount () {
11 | fluxDemoStore.on('change', this.refreshContent);
12 | }
13 |
14 | componentWillUnmount () {
15 | fluxDemoStore.off('change', this.refreshContent);
16 | }
17 |
18 | refreshContent = () => {
19 | const introduction = fluxDemoStore.getIntroduction(this.props.name);
20 |
21 | this.setState({
22 | introduction
23 | });
24 | }
25 |
26 | render () {
27 | const boxStyle = {
28 | padding: '20px 0',
29 | fontSize: '14px'
30 | };
31 |
32 | return (
33 |
34 |
{this.state.introduction}
35 |
36 | );
37 | }
38 | };
39 |
40 | export default Content;
41 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/component/dropdown.js:
--------------------------------------------------------------------------------
1 | class Dropdown extends React.Component {
2 | constructor (props) {
3 | super(props);
4 | this.state = {
5 | visibile: false,
6 | btnText: this.props.btnText
7 | };
8 | }
9 |
10 | onBtnClick = () => {
11 | this.setState({
12 | visible: !this.state.visible
13 | });
14 | }
15 |
16 | onItemClick = (event) => {
17 | const target = event.target;
18 | const url = target.dataset.url;
19 | const text = target.textContent;
20 |
21 | this.setState({
22 | visible: false,
23 | btnText: text
24 | });
25 |
26 | if (this.props.selectCallback) {
27 | this.props.selectCallback(text);
28 | }
29 |
30 | event.preventDefault();
31 | }
32 |
33 | render () {
34 | const displayValue = this.state.visible ? 'block' : 'none';
35 |
36 | return (
37 |
38 |
39 |
40 | {
41 | this.props.items.map((item) => (
42 | -
43 | {item.text}
46 |
47 | ))
48 | }
49 |
50 |
51 | );
52 | }
53 | };
54 |
55 | export default Dropdown;
56 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/component/flux-demo.js:
--------------------------------------------------------------------------------
1 | import Dropdown from './dropdown';
2 | import Content from './content';
3 | import fluxDemoActions from '../action/flux-demo';
4 |
5 | class FluxDemo extends React.Component {
6 | constructor (props) {
7 | super(props);
8 |
9 | this.state = {};
10 | }
11 |
12 | static defaultProps = {
13 | dropdownBtn: 'JavaScript library',
14 | dropdownItems: [
15 | { text: 'React', url: '/api/react' },
16 | { text: 'Angular', url: '/api/angular' },
17 | { text: 'Polymer', url: '/api/polymer' }
18 | ]
19 | }
20 |
21 | selectCallback = (name) => {
22 | const path = `/api/${name.toLowerCase()}`;
23 |
24 | this.setState({
25 | selected: name
26 | }, () => {
27 | fluxDemoActions.fetchIntroduction(name, path);
28 | });
29 | }
30 |
31 | render () {
32 | return (
33 |
34 |
This is a Flux demo.
35 |
39 |
40 |
41 | )
42 | }
43 | };
44 |
45 | React.render(
46 | ,
47 | document.getElementById('root')
48 | );
49 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/dispatcher/dispatcher.js:
--------------------------------------------------------------------------------
1 | class Dispatcher extends Flux.Dispatcher {
2 | constructor (...args) {
3 | super(...args);
4 | }
5 |
6 | dispatch (type, action = {}) {
7 | if (!type) {
8 | throw new Error('You forgot to specify type.');
9 | }
10 |
11 | super.dispatch({type, ...action});
12 | }
13 |
14 | dispatchAsync (url, types, action = {}) {
15 | const { request, success, failure } = types;
16 | const promise = fetch(url).then((response) => response.json());
17 | this.dispatch(request, action);
18 |
19 | promise.then(
20 | (response) => {
21 | this.dispatch(success, {...action, response});
22 | },
23 |
24 | (error) => {
25 | this.dispatch(failure, {...action, error});
26 | }
27 | );
28 | }
29 | };
30 |
31 | export default new Dispatcher();
32 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/lib/babel-external-helpers.js:
--------------------------------------------------------------------------------
1 | (function (global) {
2 | var babelHelpers = global.babelHelpers = {};
3 |
4 | babelHelpers.inherits = function (subClass, superClass) {
5 | if (typeof superClass !== "function" && superClass !== null) {
6 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
7 | }
8 |
9 | subClass.prototype = Object.create(superClass && superClass.prototype, {
10 | constructor: {
11 | value: subClass,
12 | enumerable: false,
13 | writable: true,
14 | configurable: true
15 | }
16 | });
17 | if (superClass) subClass.__proto__ = superClass;
18 | };
19 |
20 | babelHelpers.defaults = function (obj, defaults) {
21 | var keys = Object.getOwnPropertyNames(defaults);
22 |
23 | for (var i = 0; i < keys.length; i++) {
24 | var key = keys[i];
25 | var value = Object.getOwnPropertyDescriptor(defaults, key);
26 |
27 | if (value && value.configurable && obj[key] === undefined) {
28 | Object.defineProperty(obj, key, value);
29 | }
30 | }
31 |
32 | return obj;
33 | };
34 |
35 | babelHelpers.createClass = (function () {
36 | function defineProperties(target, props) {
37 | for (var i = 0; i < props.length; i++) {
38 | var descriptor = props[i];
39 | descriptor.enumerable = descriptor.enumerable || false;
40 | descriptor.configurable = true;
41 | if ("value" in descriptor) descriptor.writable = true;
42 | Object.defineProperty(target, descriptor.key, descriptor);
43 | }
44 | }
45 |
46 | return function (Constructor, protoProps, staticProps) {
47 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
48 | if (staticProps) defineProperties(Constructor, staticProps);
49 | return Constructor;
50 | };
51 | })();
52 |
53 | babelHelpers.createDecoratedClass = (function () {
54 | function defineProperties(target, descriptors, initializers) {
55 | for (var i = 0; i < descriptors.length; i++) {
56 | var descriptor = descriptors[i];
57 | var decorators = descriptor.decorators;
58 | var key = descriptor.key;
59 | delete descriptor.key;
60 | delete descriptor.decorators;
61 | descriptor.enumerable = descriptor.enumerable || false;
62 | descriptor.configurable = true;
63 | if ("value" in descriptor || descriptor.initializer) descriptor.writable = true;
64 |
65 | if (decorators) {
66 | for (var f = 0; f < decorators.length; f++) {
67 | var decorator = decorators[f];
68 |
69 | if (typeof decorator === "function") {
70 | descriptor = decorator(target, key, descriptor) || descriptor;
71 | } else {
72 | throw new TypeError("The decorator for method " + descriptor.key + " is of the invalid type " + typeof decorator);
73 | }
74 | }
75 |
76 | if (descriptor.initializer !== undefined) {
77 | initializers[key] = descriptor;
78 | continue;
79 | }
80 | }
81 |
82 | Object.defineProperty(target, key, descriptor);
83 | }
84 | }
85 |
86 | return function (Constructor, protoProps, staticProps, protoInitializers, staticInitializers) {
87 | if (protoProps) defineProperties(Constructor.prototype, protoProps, protoInitializers);
88 | if (staticProps) defineProperties(Constructor, staticProps, staticInitializers);
89 | return Constructor;
90 | };
91 | })();
92 |
93 | babelHelpers.createDecoratedObject = function (descriptors) {
94 | var target = {};
95 |
96 | for (var i = 0; i < descriptors.length; i++) {
97 | var descriptor = descriptors[i];
98 | var decorators = descriptor.decorators;
99 | var key = descriptor.key;
100 | delete descriptor.key;
101 | delete descriptor.decorators;
102 | descriptor.enumerable = true;
103 | descriptor.configurable = true;
104 | if ("value" in descriptor || descriptor.initializer) descriptor.writable = true;
105 |
106 | if (decorators) {
107 | for (var f = 0; f < decorators.length; f++) {
108 | var decorator = decorators[f];
109 |
110 | if (typeof decorator === "function") {
111 | descriptor = decorator(target, key, descriptor) || descriptor;
112 | } else {
113 | throw new TypeError("The decorator for method " + descriptor.key + " is of the invalid type " + typeof decorator);
114 | }
115 | }
116 | }
117 |
118 | if (descriptor.initializer) {
119 | descriptor.value = descriptor.initializer.call(target);
120 | }
121 |
122 | Object.defineProperty(target, key, descriptor);
123 | }
124 |
125 | return target;
126 | };
127 |
128 | babelHelpers.defineDecoratedPropertyDescriptor = function (target, key, descriptors) {
129 | var _descriptor = descriptors[key];
130 | if (!_descriptor) return;
131 | var descriptor = {};
132 |
133 | for (var _key in _descriptor) descriptor[_key] = _descriptor[_key];
134 |
135 | descriptor.value = descriptor.initializer.call(target);
136 | Object.defineProperty(target, key, descriptor);
137 | };
138 |
139 | babelHelpers.taggedTemplateLiteral = function (strings, raw) {
140 | return Object.freeze(Object.defineProperties(strings, {
141 | raw: {
142 | value: Object.freeze(raw)
143 | }
144 | }));
145 | };
146 |
147 | babelHelpers.taggedTemplateLiteralLoose = function (strings, raw) {
148 | strings.raw = raw;
149 | return strings;
150 | };
151 |
152 | babelHelpers.toArray = function (arr) {
153 | return Array.isArray(arr) ? arr : Array.from(arr);
154 | };
155 |
156 | babelHelpers.toConsumableArray = function (arr) {
157 | if (Array.isArray(arr)) {
158 | for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
159 |
160 | return arr2;
161 | } else {
162 | return Array.from(arr);
163 | }
164 | };
165 |
166 | babelHelpers.slicedToArray = (function () {
167 | function sliceIterator(arr, i) {
168 | var _arr = [];
169 | var _n = true;
170 | var _d = false;
171 | var _e = undefined;
172 |
173 | try {
174 | for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
175 | _arr.push(_s.value);
176 |
177 | if (i && _arr.length === i) break;
178 | }
179 | } catch (err) {
180 | _d = true;
181 | _e = err;
182 | } finally {
183 | try {
184 | if (!_n && _i["return"]) _i["return"]();
185 | } finally {
186 | if (_d) throw _e;
187 | }
188 | }
189 |
190 | return _arr;
191 | }
192 |
193 | return function (arr, i) {
194 | if (Array.isArray(arr)) {
195 | return arr;
196 | } else if (Symbol.iterator in Object(arr)) {
197 | return sliceIterator(arr, i);
198 | } else {
199 | throw new TypeError("Invalid attempt to destructure non-iterable instance");
200 | }
201 | };
202 | })();
203 |
204 | babelHelpers.slicedToArrayLoose = function (arr, i) {
205 | if (Array.isArray(arr)) {
206 | return arr;
207 | } else if (Symbol.iterator in Object(arr)) {
208 | var _arr = [];
209 |
210 | for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
211 | _arr.push(_step.value);
212 |
213 | if (i && _arr.length === i) break;
214 | }
215 |
216 | return _arr;
217 | } else {
218 | throw new TypeError("Invalid attempt to destructure non-iterable instance");
219 | }
220 | };
221 |
222 | babelHelpers.objectWithoutProperties = function (obj, keys) {
223 | var target = {};
224 |
225 | for (var i in obj) {
226 | if (keys.indexOf(i) >= 0) continue;
227 | if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
228 | target[i] = obj[i];
229 | }
230 |
231 | return target;
232 | };
233 |
234 | babelHelpers.hasOwn = Object.prototype.hasOwnProperty;
235 | babelHelpers.slice = Array.prototype.slice;
236 | babelHelpers.bind = Function.prototype.bind;
237 |
238 | babelHelpers.defineProperty = function (obj, key, value) {
239 | if (key in obj) {
240 | Object.defineProperty(obj, key, {
241 | value: value,
242 | enumerable: true,
243 | configurable: true,
244 | writable: true
245 | });
246 | } else {
247 | obj[key] = value;
248 | }
249 |
250 | return obj;
251 | };
252 |
253 | babelHelpers.asyncToGenerator = function (fn) {
254 | return function () {
255 | var gen = fn.apply(this, arguments);
256 | return new Promise(function (resolve, reject) {
257 | var callNext = step.bind(null, "next");
258 | var callThrow = step.bind(null, "throw");
259 |
260 | function step(key, arg) {
261 | try {
262 | var info = gen[key](arg);
263 | var value = info.value;
264 | } catch (error) {
265 | reject(error);
266 | return;
267 | }
268 |
269 | if (info.done) {
270 | resolve(value);
271 | } else {
272 | Promise.resolve(value).then(callNext, callThrow);
273 | }
274 | }
275 |
276 | callNext();
277 | });
278 | };
279 | };
280 |
281 | babelHelpers.interopRequireWildcard = function (obj) {
282 | if (obj && obj.__esModule) {
283 | return obj;
284 | } else {
285 | var newObj = {};
286 |
287 | if (obj != null) {
288 | for (var key in obj) {
289 | if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
290 | }
291 | }
292 |
293 | newObj["default"] = obj;
294 | return newObj;
295 | }
296 | };
297 |
298 | babelHelpers.interopRequireDefault = function (obj) {
299 | return obj && obj.__esModule ? obj : {
300 | "default": obj
301 | };
302 | };
303 |
304 | babelHelpers._typeof = function (obj) {
305 | return obj && obj.constructor === Symbol ? "symbol" : typeof obj;
306 | };
307 |
308 | babelHelpers._extends = Object.assign || function (target) {
309 | for (var i = 1; i < arguments.length; i++) {
310 | var source = arguments[i];
311 |
312 | for (var key in source) {
313 | if (Object.prototype.hasOwnProperty.call(source, key)) {
314 | target[key] = source[key];
315 | }
316 | }
317 | }
318 |
319 | return target;
320 | };
321 |
322 | babelHelpers.get = function get(object, property, receiver) {
323 | if (object === null) object = Function.prototype;
324 | var desc = Object.getOwnPropertyDescriptor(object, property);
325 |
326 | if (desc === undefined) {
327 | var parent = Object.getPrototypeOf(object);
328 |
329 | if (parent === null) {
330 | return undefined;
331 | } else {
332 | return get(parent, property, receiver);
333 | }
334 | } else if ("value" in desc) {
335 | return desc.value;
336 | } else {
337 | var getter = desc.get;
338 |
339 | if (getter === undefined) {
340 | return undefined;
341 | }
342 |
343 | return getter.call(receiver);
344 | }
345 | };
346 |
347 | babelHelpers.set = function set(object, property, value, receiver) {
348 | var desc = Object.getOwnPropertyDescriptor(object, property);
349 |
350 | if (desc === undefined) {
351 | var parent = Object.getPrototypeOf(object);
352 |
353 | if (parent !== null) {
354 | set(parent, property, value, receiver);
355 | }
356 | } else if ("value" in desc && desc.writable) {
357 | desc.value = value;
358 | } else {
359 | var setter = desc.set;
360 |
361 | if (setter !== undefined) {
362 | setter.call(receiver, value);
363 | }
364 | }
365 |
366 | return value;
367 | };
368 |
369 | babelHelpers.classCallCheck = function (instance, Constructor) {
370 | if (!(instance instanceof Constructor)) {
371 | throw new TypeError("Cannot call a class as a function");
372 | }
373 | };
374 |
375 | babelHelpers.objectDestructuringEmpty = function (obj) {
376 | if (obj == null) throw new TypeError("Cannot destructure undefined");
377 | };
378 |
379 | babelHelpers.temporalUndefined = {};
380 |
381 | babelHelpers.temporalAssertDefined = function (val, name, undef) {
382 | if (val === undef) {
383 | throw new ReferenceError(name + " is not defined - temporal dead zone");
384 | }
385 |
386 | return true;
387 | };
388 |
389 | babelHelpers.selfGlobal = typeof global === "undefined" ? self : global;
390 |
391 | babelHelpers.defaultProps = function (defaultProps, props) {
392 | if (defaultProps) {
393 | for (var propName in defaultProps) {
394 | if (typeof props[propName] === "undefined") {
395 | props[propName] = defaultProps[propName];
396 | }
397 | }
398 | }
399 |
400 | return props;
401 | };
402 |
403 | babelHelpers._instanceof = function (left, right) {
404 | if (right != null && right[Symbol.hasInstance]) {
405 | return right[Symbol.hasInstance](left);
406 | } else {
407 | return left instanceof right;
408 | }
409 | };
410 |
411 | babelHelpers.interopRequire = function (obj) {
412 | return obj && obj.__esModule ? obj["default"] : obj;
413 | };
414 | })(typeof global === "undefined" ? self : global);
415 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/lib/event-emitter.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * EventEmitter v4.2.11 - git.io/ee
3 | * Unlicense - http://unlicense.org/
4 | * Oliver Caldwell - http://oli.me.uk/
5 | * @preserve
6 | */
7 |
8 | ;(function () {
9 | 'use strict';
10 |
11 | /**
12 | * Class for managing events.
13 | * Can be extended to provide event functionality in other classes.
14 | *
15 | * @class EventEmitter Manages event registering and emitting.
16 | */
17 | function EventEmitter() {}
18 |
19 | // Shortcuts to improve speed and size
20 | var proto = EventEmitter.prototype;
21 | var exports = this;
22 | var originalGlobalValue = exports.EventEmitter;
23 |
24 | /**
25 | * Finds the index of the listener for the event in its storage array.
26 | *
27 | * @param {Function[]} listeners Array of listeners to search through.
28 | * @param {Function} listener Method to look for.
29 | * @return {Number} Index of the specified listener, -1 if not found
30 | * @api private
31 | */
32 | function indexOfListener(listeners, listener) {
33 | var i = listeners.length;
34 | while (i--) {
35 | if (listeners[i].listener === listener) {
36 | return i;
37 | }
38 | }
39 |
40 | return -1;
41 | }
42 |
43 | /**
44 | * Alias a method while keeping the context correct, to allow for overwriting of target method.
45 | *
46 | * @param {String} name The name of the target method.
47 | * @return {Function} The aliased method
48 | * @api private
49 | */
50 | function alias(name) {
51 | return function aliasClosure() {
52 | return this[name].apply(this, arguments);
53 | };
54 | }
55 |
56 | /**
57 | * Returns the listener array for the specified event.
58 | * Will initialise the event object and listener arrays if required.
59 | * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
60 | * Each property in the object response is an array of listener functions.
61 | *
62 | * @param {String|RegExp} evt Name of the event to return the listeners from.
63 | * @return {Function[]|Object} All listener functions for the event.
64 | */
65 | proto.getListeners = function getListeners(evt) {
66 | var events = this._getEvents();
67 | var response;
68 | var key;
69 |
70 | // Return a concatenated array of all matching events if
71 | // the selector is a regular expression.
72 | if (evt instanceof RegExp) {
73 | response = {};
74 | for (key in events) {
75 | if (events.hasOwnProperty(key) && evt.test(key)) {
76 | response[key] = events[key];
77 | }
78 | }
79 | }
80 | else {
81 | response = events[evt] || (events[evt] = []);
82 | }
83 |
84 | return response;
85 | };
86 |
87 | /**
88 | * Takes a list of listener objects and flattens it into a list of listener functions.
89 | *
90 | * @param {Object[]} listeners Raw listener objects.
91 | * @return {Function[]} Just the listener functions.
92 | */
93 | proto.flattenListeners = function flattenListeners(listeners) {
94 | var flatListeners = [];
95 | var i;
96 |
97 | for (i = 0; i < listeners.length; i += 1) {
98 | flatListeners.push(listeners[i].listener);
99 | }
100 |
101 | return flatListeners;
102 | };
103 |
104 | /**
105 | * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
106 | *
107 | * @param {String|RegExp} evt Name of the event to return the listeners from.
108 | * @return {Object} All listener functions for an event in an object.
109 | */
110 | proto.getListenersAsObject = function getListenersAsObject(evt) {
111 | var listeners = this.getListeners(evt);
112 | var response;
113 |
114 | if (listeners instanceof Array) {
115 | response = {};
116 | response[evt] = listeners;
117 | }
118 |
119 | return response || listeners;
120 | };
121 |
122 | /**
123 | * Adds a listener function to the specified event.
124 | * The listener will not be added if it is a duplicate.
125 | * If the listener returns true then it will be removed after it is called.
126 | * If you pass a regular expression as the event name then the listener will be added to all events that match it.
127 | *
128 | * @param {String|RegExp} evt Name of the event to attach the listener to.
129 | * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
130 | * @return {Object} Current instance of EventEmitter for chaining.
131 | */
132 | proto.addListener = function addListener(evt, listener) {
133 | var listeners = this.getListenersAsObject(evt);
134 | var listenerIsWrapped = typeof listener === 'object';
135 | var key;
136 |
137 | for (key in listeners) {
138 | if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
139 | listeners[key].push(listenerIsWrapped ? listener : {
140 | listener: listener,
141 | once: false
142 | });
143 | }
144 | }
145 |
146 | return this;
147 | };
148 |
149 | /**
150 | * Alias of addListener
151 | */
152 | proto.on = alias('addListener');
153 |
154 | /**
155 | * Semi-alias of addListener. It will add a listener that will be
156 | * automatically removed after its first execution.
157 | *
158 | * @param {String|RegExp} evt Name of the event to attach the listener to.
159 | * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
160 | * @return {Object} Current instance of EventEmitter for chaining.
161 | */
162 | proto.addOnceListener = function addOnceListener(evt, listener) {
163 | return this.addListener(evt, {
164 | listener: listener,
165 | once: true
166 | });
167 | };
168 |
169 | /**
170 | * Alias of addOnceListener.
171 | */
172 | proto.once = alias('addOnceListener');
173 |
174 | /**
175 | * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
176 | * You need to tell it what event names should be matched by a regex.
177 | *
178 | * @param {String} evt Name of the event to create.
179 | * @return {Object} Current instance of EventEmitter for chaining.
180 | */
181 | proto.defineEvent = function defineEvent(evt) {
182 | this.getListeners(evt);
183 | return this;
184 | };
185 |
186 | /**
187 | * Uses defineEvent to define multiple events.
188 | *
189 | * @param {String[]} evts An array of event names to define.
190 | * @return {Object} Current instance of EventEmitter for chaining.
191 | */
192 | proto.defineEvents = function defineEvents(evts) {
193 | for (var i = 0; i < evts.length; i += 1) {
194 | this.defineEvent(evts[i]);
195 | }
196 | return this;
197 | };
198 |
199 | /**
200 | * Removes a listener function from the specified event.
201 | * When passed a regular expression as the event name, it will remove the listener from all events that match it.
202 | *
203 | * @param {String|RegExp} evt Name of the event to remove the listener from.
204 | * @param {Function} listener Method to remove from the event.
205 | * @return {Object} Current instance of EventEmitter for chaining.
206 | */
207 | proto.removeListener = function removeListener(evt, listener) {
208 | var listeners = this.getListenersAsObject(evt);
209 | var index;
210 | var key;
211 |
212 | for (key in listeners) {
213 | if (listeners.hasOwnProperty(key)) {
214 | index = indexOfListener(listeners[key], listener);
215 |
216 | if (index !== -1) {
217 | listeners[key].splice(index, 1);
218 | }
219 | }
220 | }
221 |
222 | return this;
223 | };
224 |
225 | /**
226 | * Alias of removeListener
227 | */
228 | proto.off = alias('removeListener');
229 |
230 | /**
231 | * Adds listeners in bulk using the manipulateListeners method.
232 | * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
233 | * You can also pass it a regular expression to add the array of listeners to all events that match it.
234 | * Yeah, this function does quite a bit. That's probably a bad thing.
235 | *
236 | * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
237 | * @param {Function[]} [listeners] An optional array of listener functions to add.
238 | * @return {Object} Current instance of EventEmitter for chaining.
239 | */
240 | proto.addListeners = function addListeners(evt, listeners) {
241 | // Pass through to manipulateListeners
242 | return this.manipulateListeners(false, evt, listeners);
243 | };
244 |
245 | /**
246 | * Removes listeners in bulk using the manipulateListeners method.
247 | * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
248 | * You can also pass it an event name and an array of listeners to be removed.
249 | * You can also pass it a regular expression to remove the listeners from all events that match it.
250 | *
251 | * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
252 | * @param {Function[]} [listeners] An optional array of listener functions to remove.
253 | * @return {Object} Current instance of EventEmitter for chaining.
254 | */
255 | proto.removeListeners = function removeListeners(evt, listeners) {
256 | // Pass through to manipulateListeners
257 | return this.manipulateListeners(true, evt, listeners);
258 | };
259 |
260 | /**
261 | * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
262 | * The first argument will determine if the listeners are removed (true) or added (false).
263 | * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
264 | * You can also pass it an event name and an array of listeners to be added/removed.
265 | * You can also pass it a regular expression to manipulate the listeners of all events that match it.
266 | *
267 | * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
268 | * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
269 | * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
270 | * @return {Object} Current instance of EventEmitter for chaining.
271 | */
272 | proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
273 | var i;
274 | var value;
275 | var single = remove ? this.removeListener : this.addListener;
276 | var multiple = remove ? this.removeListeners : this.addListeners;
277 |
278 | // If evt is an object then pass each of its properties to this method
279 | if (typeof evt === 'object' && !(evt instanceof RegExp)) {
280 | for (i in evt) {
281 | if (evt.hasOwnProperty(i) && (value = evt[i])) {
282 | // Pass the single listener straight through to the singular method
283 | if (typeof value === 'function') {
284 | single.call(this, i, value);
285 | }
286 | else {
287 | // Otherwise pass back to the multiple function
288 | multiple.call(this, i, value);
289 | }
290 | }
291 | }
292 | }
293 | else {
294 | // So evt must be a string
295 | // And listeners must be an array of listeners
296 | // Loop over it and pass each one to the multiple method
297 | i = listeners.length;
298 | while (i--) {
299 | single.call(this, evt, listeners[i]);
300 | }
301 | }
302 |
303 | return this;
304 | };
305 |
306 | /**
307 | * Removes all listeners from a specified event.
308 | * If you do not specify an event then all listeners will be removed.
309 | * That means every event will be emptied.
310 | * You can also pass a regex to remove all events that match it.
311 | *
312 | * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
313 | * @return {Object} Current instance of EventEmitter for chaining.
314 | */
315 | proto.removeEvent = function removeEvent(evt) {
316 | var type = typeof evt;
317 | var events = this._getEvents();
318 | var key;
319 |
320 | // Remove different things depending on the state of evt
321 | if (type === 'string') {
322 | // Remove all listeners for the specified event
323 | delete events[evt];
324 | }
325 | else if (evt instanceof RegExp) {
326 | // Remove all events matching the regex.
327 | for (key in events) {
328 | if (events.hasOwnProperty(key) && evt.test(key)) {
329 | delete events[key];
330 | }
331 | }
332 | }
333 | else {
334 | // Remove all listeners in all events
335 | delete this._events;
336 | }
337 |
338 | return this;
339 | };
340 |
341 | /**
342 | * Alias of removeEvent.
343 | *
344 | * Added to mirror the node API.
345 | */
346 | proto.removeAllListeners = alias('removeEvent');
347 |
348 | /**
349 | * Emits an event of your choice.
350 | * When emitted, every listener attached to that event will be executed.
351 | * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
352 | * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
353 | * So they will not arrive within the array on the other side, they will be separate.
354 | * You can also pass a regular expression to emit to all events that match it.
355 | *
356 | * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
357 | * @param {Array} [args] Optional array of arguments to be passed to each listener.
358 | * @return {Object} Current instance of EventEmitter for chaining.
359 | */
360 | proto.emitEvent = function emitEvent(evt, args) {
361 | var listeners = this.getListenersAsObject(evt);
362 | var listener;
363 | var i;
364 | var key;
365 | var response;
366 |
367 | for (key in listeners) {
368 | if (listeners.hasOwnProperty(key)) {
369 | i = listeners[key].length;
370 |
371 | while (i--) {
372 | // If the listener returns true then it shall be removed from the event
373 | // The function is executed either with a basic call or an apply if there is an args array
374 | listener = listeners[key][i];
375 |
376 | if (listener.once === true) {
377 | this.removeListener(evt, listener.listener);
378 | }
379 |
380 | response = listener.listener.apply(this, args || []);
381 |
382 | if (response === this._getOnceReturnValue()) {
383 | this.removeListener(evt, listener.listener);
384 | }
385 | }
386 | }
387 | }
388 |
389 | return this;
390 | };
391 |
392 | /**
393 | * Alias of emitEvent
394 | */
395 | proto.trigger = alias('emitEvent');
396 |
397 | /**
398 | * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
399 | * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
400 | *
401 | * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
402 | * @param {...*} Optional additional arguments to be passed to each listener.
403 | * @return {Object} Current instance of EventEmitter for chaining.
404 | */
405 | proto.emit = function emit(evt) {
406 | var args = Array.prototype.slice.call(arguments, 1);
407 | return this.emitEvent(evt, args);
408 | };
409 |
410 | /**
411 | * Sets the current value to check against when executing listeners. If a
412 | * listeners return value matches the one set here then it will be removed
413 | * after execution. This value defaults to true.
414 | *
415 | * @param {*} value The new value to check for when executing listeners.
416 | * @return {Object} Current instance of EventEmitter for chaining.
417 | */
418 | proto.setOnceReturnValue = function setOnceReturnValue(value) {
419 | this._onceReturnValue = value;
420 | return this;
421 | };
422 |
423 | /**
424 | * Fetches the current value to check against when executing listeners. If
425 | * the listeners return value matches this one then it should be removed
426 | * automatically. It will return true by default.
427 | *
428 | * @return {*|Boolean} The current value to check for or the default, true.
429 | * @api private
430 | */
431 | proto._getOnceReturnValue = function _getOnceReturnValue() {
432 | if (this.hasOwnProperty('_onceReturnValue')) {
433 | return this._onceReturnValue;
434 | }
435 | else {
436 | return true;
437 | }
438 | };
439 |
440 | /**
441 | * Fetches the events object and creates one if required.
442 | *
443 | * @return {Object} The events storage object.
444 | * @api private
445 | */
446 | proto._getEvents = function _getEvents() {
447 | return this._events || (this._events = {});
448 | };
449 |
450 | /**
451 | * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
452 | *
453 | * @return {Function} Non conflicting EventEmitter class.
454 | */
455 | EventEmitter.noConflict = function noConflict() {
456 | exports.EventEmitter = originalGlobalValue;
457 | return EventEmitter;
458 | };
459 |
460 | // Expose the class either via AMD, CommonJS or the global object
461 | if (typeof define === 'function' && define.amd) {
462 | define(function () {
463 | return EventEmitter;
464 | });
465 | }
466 | else if (typeof module === 'object' && module.exports){
467 | module.exports = EventEmitter;
468 | }
469 | else {
470 | exports.EventEmitter = EventEmitter;
471 | }
472 | }.call(this));
473 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/lib/fetch.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | if (self.fetch) {
5 | return
6 | }
7 |
8 | function normalizeName(name) {
9 | if (typeof name !== 'string') {
10 | name = name.toString();
11 | }
12 | if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
13 | throw new TypeError('Invalid character in header field name')
14 | }
15 | return name.toLowerCase()
16 | }
17 |
18 | function normalizeValue(value) {
19 | if (typeof value !== 'string') {
20 | value = value.toString();
21 | }
22 | return value
23 | }
24 |
25 | function Headers(headers) {
26 | this.map = {}
27 |
28 | if (headers instanceof Headers) {
29 | headers.forEach(function(value, name) {
30 | this.append(name, value)
31 | }, this)
32 |
33 | } else if (headers) {
34 | Object.getOwnPropertyNames(headers).forEach(function(name) {
35 | this.append(name, headers[name])
36 | }, this)
37 | }
38 | }
39 |
40 | Headers.prototype.append = function(name, value) {
41 | name = normalizeName(name)
42 | value = normalizeValue(value)
43 | var list = this.map[name]
44 | if (!list) {
45 | list = []
46 | this.map[name] = list
47 | }
48 | list.push(value)
49 | }
50 |
51 | Headers.prototype['delete'] = function(name) {
52 | delete this.map[normalizeName(name)]
53 | }
54 |
55 | Headers.prototype.get = function(name) {
56 | var values = this.map[normalizeName(name)]
57 | return values ? values[0] : null
58 | }
59 |
60 | Headers.prototype.getAll = function(name) {
61 | return this.map[normalizeName(name)] || []
62 | }
63 |
64 | Headers.prototype.has = function(name) {
65 | return this.map.hasOwnProperty(normalizeName(name))
66 | }
67 |
68 | Headers.prototype.set = function(name, value) {
69 | this.map[normalizeName(name)] = [normalizeValue(value)]
70 | }
71 |
72 | Headers.prototype.forEach = function(callback, thisArg) {
73 | Object.getOwnPropertyNames(this.map).forEach(function(name) {
74 | this.map[name].forEach(function(value) {
75 | callback.call(thisArg, value, name, this)
76 | }, this)
77 | }, this)
78 | }
79 |
80 | function consumed(body) {
81 | if (body.bodyUsed) {
82 | return Promise.reject(new TypeError('Already read'))
83 | }
84 | body.bodyUsed = true
85 | }
86 |
87 | function fileReaderReady(reader) {
88 | return new Promise(function(resolve, reject) {
89 | reader.onload = function() {
90 | resolve(reader.result)
91 | }
92 | reader.onerror = function() {
93 | reject(reader.error)
94 | }
95 | })
96 | }
97 |
98 | function readBlobAsArrayBuffer(blob) {
99 | var reader = new FileReader()
100 | reader.readAsArrayBuffer(blob)
101 | return fileReaderReady(reader)
102 | }
103 |
104 | function readBlobAsText(blob) {
105 | var reader = new FileReader()
106 | reader.readAsText(blob)
107 | return fileReaderReady(reader)
108 | }
109 |
110 | var support = {
111 | blob: 'FileReader' in self && 'Blob' in self && (function() {
112 | try {
113 | new Blob();
114 | return true
115 | } catch(e) {
116 | return false
117 | }
118 | })(),
119 | formData: 'FormData' in self
120 | }
121 |
122 | function Body() {
123 | this.bodyUsed = false
124 |
125 |
126 | this._initBody = function(body) {
127 | this._bodyInit = body
128 | if (typeof body === 'string') {
129 | this._bodyText = body
130 | } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
131 | this._bodyBlob = body
132 | } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
133 | this._bodyFormData = body
134 | } else if (!body) {
135 | this._bodyText = ''
136 | } else {
137 | throw new Error('unsupported BodyInit type')
138 | }
139 | }
140 |
141 | if (support.blob) {
142 | this.blob = function() {
143 | var rejected = consumed(this)
144 | if (rejected) {
145 | return rejected
146 | }
147 |
148 | if (this._bodyBlob) {
149 | return Promise.resolve(this._bodyBlob)
150 | } else if (this._bodyFormData) {
151 | throw new Error('could not read FormData body as blob')
152 | } else {
153 | return Promise.resolve(new Blob([this._bodyText]))
154 | }
155 | }
156 |
157 | this.arrayBuffer = function() {
158 | return this.blob().then(readBlobAsArrayBuffer)
159 | }
160 |
161 | this.text = function() {
162 | var rejected = consumed(this)
163 | if (rejected) {
164 | return rejected
165 | }
166 |
167 | if (this._bodyBlob) {
168 | return readBlobAsText(this._bodyBlob)
169 | } else if (this._bodyFormData) {
170 | throw new Error('could not read FormData body as text')
171 | } else {
172 | return Promise.resolve(this._bodyText)
173 | }
174 | }
175 | } else {
176 | this.text = function() {
177 | var rejected = consumed(this)
178 | return rejected ? rejected : Promise.resolve(this._bodyText)
179 | }
180 | }
181 |
182 | if (support.formData) {
183 | this.formData = function() {
184 | return this.text().then(decode)
185 | }
186 | }
187 |
188 | this.json = function() {
189 | return this.text().then(JSON.parse)
190 | }
191 |
192 | return this
193 | }
194 |
195 | // HTTP methods whose capitalization should be normalized
196 | var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
197 |
198 | function normalizeMethod(method) {
199 | var upcased = method.toUpperCase()
200 | return (methods.indexOf(upcased) > -1) ? upcased : method
201 | }
202 |
203 | function Request(url, options) {
204 | options = options || {}
205 | this.url = url
206 |
207 | this.credentials = options.credentials || 'omit'
208 | this.headers = new Headers(options.headers)
209 | this.method = normalizeMethod(options.method || 'GET')
210 | this.mode = options.mode || null
211 | this.referrer = null
212 |
213 | if ((this.method === 'GET' || this.method === 'HEAD') && options.body) {
214 | throw new TypeError('Body not allowed for GET or HEAD requests')
215 | }
216 | this._initBody(options.body)
217 | }
218 |
219 | function decode(body) {
220 | var form = new FormData()
221 | body.trim().split('&').forEach(function(bytes) {
222 | if (bytes) {
223 | var split = bytes.split('=')
224 | var name = split.shift().replace(/\+/g, ' ')
225 | var value = split.join('=').replace(/\+/g, ' ')
226 | form.append(decodeURIComponent(name), decodeURIComponent(value))
227 | }
228 | })
229 | return form
230 | }
231 |
232 | function headers(xhr) {
233 | var head = new Headers()
234 | var pairs = xhr.getAllResponseHeaders().trim().split('\n')
235 | pairs.forEach(function(header) {
236 | var split = header.trim().split(':')
237 | var key = split.shift().trim()
238 | var value = split.join(':').trim()
239 | head.append(key, value)
240 | })
241 | return head
242 | }
243 |
244 | Body.call(Request.prototype)
245 |
246 | function Response(bodyInit, options) {
247 | if (!options) {
248 | options = {}
249 | }
250 |
251 | this._initBody(bodyInit)
252 | this.type = 'default'
253 | this.url = null
254 | this.status = options.status
255 | this.ok = this.status >= 200 && this.status < 300
256 | this.statusText = options.statusText
257 | this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
258 | this.url = options.url || ''
259 | }
260 |
261 | Body.call(Response.prototype)
262 |
263 | self.Headers = Headers;
264 | self.Request = Request;
265 | self.Response = Response;
266 |
267 | self.fetch = function(input, init) {
268 | // TODO: Request constructor should accept input, init
269 | var request
270 | if (Request.prototype.isPrototypeOf(input) && !init) {
271 | request = input
272 | } else {
273 | request = new Request(input, init)
274 | }
275 |
276 | return new Promise(function(resolve, reject) {
277 | var xhr = new XMLHttpRequest()
278 |
279 | function responseURL() {
280 | if ('responseURL' in xhr) {
281 | return xhr.responseURL
282 | }
283 |
284 | // Avoid security warnings on getResponseHeader when not allowed by CORS
285 | if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
286 | return xhr.getResponseHeader('X-Request-URL')
287 | }
288 |
289 | return;
290 | }
291 |
292 | xhr.onload = function() {
293 | var status = (xhr.status === 1223) ? 204 : xhr.status
294 | if (status < 100 || status > 599) {
295 | reject(new TypeError('Network request failed'))
296 | return
297 | }
298 | var options = {
299 | status: status,
300 | statusText: xhr.statusText,
301 | headers: headers(xhr),
302 | url: responseURL()
303 | }
304 | var body = 'response' in xhr ? xhr.response : xhr.responseText;
305 | resolve(new Response(body, options))
306 | }
307 |
308 | xhr.onerror = function() {
309 | reject(new TypeError('Network request failed'))
310 | }
311 |
312 | xhr.open(request.method, request.url, true)
313 |
314 | if (request.credentials === 'include') {
315 | xhr.withCredentials = true
316 | }
317 |
318 | if ('responseType' in xhr && support.blob) {
319 | xhr.responseType = 'blob'
320 | }
321 |
322 | request.headers.forEach(function(value, name) {
323 | xhr.setRequestHeader(name, value)
324 | })
325 |
326 | xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
327 | })
328 | }
329 | self.fetch.polyfill = true
330 | })();
331 |
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/lib/flux.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Flux = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o} ids
163 | */
164 | Dispatcher.prototype.waitFor=function(ids) {
165 | invariant(
166 | this._isDispatching,
167 | 'Dispatcher.waitFor(...): Must be invoked while dispatching.'
168 | );
169 | for (var ii = 0; ii < ids.length; ii++) {
170 | var id = ids[ii];
171 | if (this._isPending[id]) {
172 | invariant(
173 | this._isHandled[id],
174 | 'Dispatcher.waitFor(...): Circular dependency detected while ' +
175 | 'waiting for `%s`.',
176 | id
177 | );
178 | continue;
179 | }
180 | invariant(
181 | this._callbacks[id],
182 | 'Dispatcher.waitFor(...): `%s` does not map to a registered callback.',
183 | id
184 | );
185 | this._invokeCallback(id);
186 | }
187 | };
188 |
189 | /**
190 | * Dispatches a payload to all registered callbacks.
191 | *
192 | * @param {object} payload
193 | */
194 | Dispatcher.prototype.dispatch=function(payload) {
195 | invariant(
196 | !this._isDispatching,
197 | 'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.'
198 | );
199 | this._startDispatching(payload);
200 | try {
201 | for (var id in this._callbacks) {
202 | if (this._isPending[id]) {
203 | continue;
204 | }
205 | this._invokeCallback(id);
206 | }
207 | } finally {
208 | this._stopDispatching();
209 | }
210 | };
211 |
212 | /**
213 | * Is this Dispatcher currently dispatching.
214 | *
215 | * @return {boolean}
216 | */
217 | Dispatcher.prototype.isDispatching=function() {
218 | return this._isDispatching;
219 | };
220 |
221 | /**
222 | * Call the callback stored with the given id. Also do some internal
223 | * bookkeeping.
224 | *
225 | * @param {string} id
226 | * @internal
227 | */
228 | Dispatcher.prototype._invokeCallback=function(id) {
229 | this._isPending[id] = true;
230 | this._callbacks[id](this._pendingPayload);
231 | this._isHandled[id] = true;
232 | };
233 |
234 | /**
235 | * Set up bookkeeping needed when dispatching.
236 | *
237 | * @param {object} payload
238 | * @internal
239 | */
240 | Dispatcher.prototype._startDispatching=function(payload) {
241 | for (var id in this._callbacks) {
242 | this._isPending[id] = false;
243 | this._isHandled[id] = false;
244 | }
245 | this._pendingPayload = payload;
246 | this._isDispatching = true;
247 | };
248 |
249 | /**
250 | * Clear bookkeeping used for dispatching.
251 | *
252 | * @internal
253 | */
254 | Dispatcher.prototype._stopDispatching=function() {
255 | this._pendingPayload = null;
256 | this._isDispatching = false;
257 | };
258 |
259 |
260 | module.exports = Dispatcher;
261 |
262 | },{"./invariant":3}],3:[function(require,module,exports){
263 | /**
264 | * Copyright (c) 2014-2015, Facebook, Inc.
265 | * All rights reserved.
266 | *
267 | * This source code is licensed under the BSD-style license found in the
268 | * LICENSE file in the root directory of this source tree. An additional grant
269 | * of patent rights can be found in the PATENTS file in the same directory.
270 | *
271 | * @providesModule invariant
272 | */
273 |
274 | "use strict";
275 |
276 | /**
277 | * Use invariant() to assert state which your program assumes to be true.
278 | *
279 | * Provide sprintf-style format (only %s is supported) and arguments
280 | * to provide information about what broke and what you were
281 | * expecting.
282 | *
283 | * The invariant message will be stripped in production, but the invariant
284 | * will remain to ensure logic does not differ in production.
285 | */
286 |
287 | var invariant = function(condition, format, a, b, c, d, e, f) {
288 | if (false) {
289 | if (format === undefined) {
290 | throw new Error('invariant requires an error message argument');
291 | }
292 | }
293 |
294 | if (!condition) {
295 | var error;
296 | if (format === undefined) {
297 | error = new Error(
298 | 'Minified exception occurred; use the non-minified dev environment ' +
299 | 'for the full error message and additional helpful warnings.'
300 | );
301 | } else {
302 | var args = [a, b, c, d, e, f];
303 | var argIndex = 0;
304 | error = new Error(
305 | 'Invariant Violation: ' +
306 | format.replace(/%s/g, function() { return args[argIndex++]; })
307 | );
308 | }
309 |
310 | error.framesToPop = 1; // we don't care about invariant's own frame
311 | throw error;
312 | }
313 | };
314 |
315 | module.exports = invariant;
316 |
317 | },{}]},{},[1])(1)
318 | });
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/lib/promise.js:
--------------------------------------------------------------------------------
1 | (function e(t, n, r) {
2 | function s(o, u) {
3 | if (!n[o]) {
4 | if (!t[o]) {
5 | var a = typeof require == "function" && require;
6 | if (!u && a) return a(o, !0);
7 | if (i) return i(o, !0);
8 | var f = new Error("Cannot find module '" + o + "'");
9 | throw f.code = "MODULE_NOT_FOUND", f;
10 | }
11 | var l = n[o] = {
12 | exports: {}
13 | };
14 | t[o][0].call(l.exports, function(e) {
15 | var n = t[o][1][e];
16 | return s(n ? n : e);
17 | }, l, l.exports, e, t, n, r);
18 | }
19 | return n[o].exports;
20 | }
21 | var i = typeof require == "function" && require;
22 | for (var o = 0; o < r.length; o++) s(r[o]);
23 | return s;
24 | })({
25 | 1: [ function(require, module, exports) {
26 | var process = module.exports = {};
27 | process.nextTick = function() {
28 | var canSetImmediate = typeof window !== "undefined" && window.setImmediate;
29 | var canPost = typeof window !== "undefined" && window.postMessage && window.addEventListener;
30 | if (canSetImmediate) {
31 | return function(f) {
32 | return window.setImmediate(f);
33 | };
34 | }
35 | if (canPost) {
36 | var queue = [];
37 | window.addEventListener("message", function(ev) {
38 | var source = ev.source;
39 | if ((source === window || source === null) && ev.data === "process-tick") {
40 | ev.stopPropagation();
41 | if (queue.length > 0) {
42 | var fn = queue.shift();
43 | fn();
44 | }
45 | }
46 | }, true);
47 | return function nextTick(fn) {
48 | queue.push(fn);
49 | window.postMessage("process-tick", "*");
50 | };
51 | }
52 | return function nextTick(fn) {
53 | setTimeout(fn, 0);
54 | };
55 | }();
56 | process.title = "browser";
57 | process.browser = true;
58 | process.env = {};
59 | process.argv = [];
60 | function noop() {}
61 | process.on = noop;
62 | process.addListener = noop;
63 | process.once = noop;
64 | process.off = noop;
65 | process.removeListener = noop;
66 | process.removeAllListeners = noop;
67 | process.emit = noop;
68 | process.binding = function(name) {
69 | throw new Error("process.binding is not supported");
70 | };
71 | process.cwd = function() {
72 | return "/";
73 | };
74 | process.chdir = function(dir) {
75 | throw new Error("process.chdir is not supported");
76 | };
77 | }, {} ],
78 | 2: [ function(require, module, exports) {
79 | "use strict";
80 | var asap = require("asap");
81 | module.exports = Promise;
82 | function Promise(fn) {
83 | if (typeof this !== "object") throw new TypeError("Promises must be constructed via new");
84 | if (typeof fn !== "function") throw new TypeError("not a function");
85 | var state = null;
86 | var value = null;
87 | var deferreds = [];
88 | var self = this;
89 | this.then = function(onFulfilled, onRejected) {
90 | return new self.constructor(function(resolve, reject) {
91 | handle(new Handler(onFulfilled, onRejected, resolve, reject));
92 | });
93 | };
94 | function handle(deferred) {
95 | if (state === null) {
96 | deferreds.push(deferred);
97 | return;
98 | }
99 | asap(function() {
100 | var cb = state ? deferred.onFulfilled : deferred.onRejected;
101 | if (cb === null) {
102 | (state ? deferred.resolve : deferred.reject)(value);
103 | return;
104 | }
105 | var ret;
106 | try {
107 | ret = cb(value);
108 | } catch (e) {
109 | deferred.reject(e);
110 | return;
111 | }
112 | deferred.resolve(ret);
113 | });
114 | }
115 | function resolve(newValue) {
116 | try {
117 | if (newValue === self) throw new TypeError("A promise cannot be resolved with itself.");
118 | if (newValue && (typeof newValue === "object" || typeof newValue === "function")) {
119 | var then = newValue.then;
120 | if (typeof then === "function") {
121 | doResolve(then.bind(newValue), resolve, reject);
122 | return;
123 | }
124 | }
125 | state = true;
126 | value = newValue;
127 | finale();
128 | } catch (e) {
129 | reject(e);
130 | }
131 | }
132 | function reject(newValue) {
133 | state = false;
134 | value = newValue;
135 | finale();
136 | }
137 | function finale() {
138 | for (var i = 0, len = deferreds.length; i < len; i++) handle(deferreds[i]);
139 | deferreds = null;
140 | }
141 | doResolve(fn, resolve, reject);
142 | }
143 | function Handler(onFulfilled, onRejected, resolve, reject) {
144 | this.onFulfilled = typeof onFulfilled === "function" ? onFulfilled : null;
145 | this.onRejected = typeof onRejected === "function" ? onRejected : null;
146 | this.resolve = resolve;
147 | this.reject = reject;
148 | }
149 | function doResolve(fn, onFulfilled, onRejected) {
150 | var done = false;
151 | try {
152 | fn(function(value) {
153 | if (done) return;
154 | done = true;
155 | onFulfilled(value);
156 | }, function(reason) {
157 | if (done) return;
158 | done = true;
159 | onRejected(reason);
160 | });
161 | } catch (ex) {
162 | if (done) return;
163 | done = true;
164 | onRejected(ex);
165 | }
166 | }
167 | }, {
168 | asap: 4
169 | } ],
170 | 3: [ function(require, module, exports) {
171 | "use strict";
172 | var Promise = require("./core.js");
173 | var asap = require("asap");
174 | module.exports = Promise;
175 | function ValuePromise(value) {
176 | this.then = function(onFulfilled) {
177 | if (typeof onFulfilled !== "function") return this;
178 | return new Promise(function(resolve, reject) {
179 | asap(function() {
180 | try {
181 | resolve(onFulfilled(value));
182 | } catch (ex) {
183 | reject(ex);
184 | }
185 | });
186 | });
187 | };
188 | }
189 | ValuePromise.prototype = Promise.prototype;
190 | var TRUE = new ValuePromise(true);
191 | var FALSE = new ValuePromise(false);
192 | var NULL = new ValuePromise(null);
193 | var UNDEFINED = new ValuePromise(undefined);
194 | var ZERO = new ValuePromise(0);
195 | var EMPTYSTRING = new ValuePromise("");
196 | Promise.resolve = function(value) {
197 | if (value instanceof Promise) return value;
198 | if (value === null) return NULL;
199 | if (value === undefined) return UNDEFINED;
200 | if (value === true) return TRUE;
201 | if (value === false) return FALSE;
202 | if (value === 0) return ZERO;
203 | if (value === "") return EMPTYSTRING;
204 | if (typeof value === "object" || typeof value === "function") {
205 | try {
206 | var then = value.then;
207 | if (typeof then === "function") {
208 | return new Promise(then.bind(value));
209 | }
210 | } catch (ex) {
211 | return new Promise(function(resolve, reject) {
212 | reject(ex);
213 | });
214 | }
215 | }
216 | return new ValuePromise(value);
217 | };
218 | Promise.all = function(arr) {
219 | var args = Array.prototype.slice.call(arr);
220 | return new Promise(function(resolve, reject) {
221 | if (args.length === 0) return resolve([]);
222 | var remaining = args.length;
223 | function res(i, val) {
224 | try {
225 | if (val && (typeof val === "object" || typeof val === "function")) {
226 | var then = val.then;
227 | if (typeof then === "function") {
228 | then.call(val, function(val) {
229 | res(i, val);
230 | }, reject);
231 | return;
232 | }
233 | }
234 | args[i] = val;
235 | if (--remaining === 0) {
236 | resolve(args);
237 | }
238 | } catch (ex) {
239 | reject(ex);
240 | }
241 | }
242 | for (var i = 0; i < args.length; i++) {
243 | res(i, args[i]);
244 | }
245 | });
246 | };
247 | Promise.reject = function(value) {
248 | return new Promise(function(resolve, reject) {
249 | reject(value);
250 | });
251 | };
252 | Promise.race = function(values) {
253 | return new Promise(function(resolve, reject) {
254 | values.forEach(function(value) {
255 | Promise.resolve(value).then(resolve, reject);
256 | });
257 | });
258 | };
259 | Promise.prototype["catch"] = function(onRejected) {
260 | return this.then(null, onRejected);
261 | };
262 | }, {
263 | "./core.js": 2,
264 | asap: 4
265 | } ],
266 | 4: [ function(require, module, exports) {
267 | (function(process) {
268 | var head = {
269 | task: void 0,
270 | next: null
271 | };
272 | var tail = head;
273 | var flushing = false;
274 | var requestFlush = void 0;
275 | var isNodeJS = false;
276 | function flush() {
277 | while (head.next) {
278 | head = head.next;
279 | var task = head.task;
280 | head.task = void 0;
281 | var domain = head.domain;
282 | if (domain) {
283 | head.domain = void 0;
284 | domain.enter();
285 | }
286 | try {
287 | task();
288 | } catch (e) {
289 | if (isNodeJS) {
290 | if (domain) {
291 | domain.exit();
292 | }
293 | setTimeout(flush, 0);
294 | if (domain) {
295 | domain.enter();
296 | }
297 | throw e;
298 | } else {
299 | setTimeout(function() {
300 | throw e;
301 | }, 0);
302 | }
303 | }
304 | if (domain) {
305 | domain.exit();
306 | }
307 | }
308 | flushing = false;
309 | }
310 | if (typeof process !== "undefined" && process.nextTick) {
311 | isNodeJS = true;
312 | requestFlush = function() {
313 | process.nextTick(flush);
314 | };
315 | } else if (typeof setImmediate === "function") {
316 | if (typeof window !== "undefined") {
317 | requestFlush = setImmediate.bind(window, flush);
318 | } else {
319 | requestFlush = function() {
320 | setImmediate(flush);
321 | };
322 | }
323 | } else if (typeof MessageChannel !== "undefined") {
324 | var channel = new MessageChannel();
325 | channel.port1.onmessage = flush;
326 | requestFlush = function() {
327 | channel.port2.postMessage(0);
328 | };
329 | } else {
330 | requestFlush = function() {
331 | setTimeout(flush, 0);
332 | };
333 | }
334 | function asap(task) {
335 | tail = tail.next = {
336 | task: task,
337 | domain: isNodeJS && process.domain,
338 | next: null
339 | };
340 | if (!flushing) {
341 | flushing = true;
342 | requestFlush();
343 | }
344 | }
345 | module.exports = asap;
346 | }).call(this, require("_process"));
347 | }, {
348 | _process: 1
349 | } ],
350 | 5: [ function(require, module, exports) {
351 | if (typeof Promise.prototype.done !== "function") {
352 | Promise.prototype.done = function(onFulfilled, onRejected) {
353 | var self = arguments.length ? this.then.apply(this, arguments) : this;
354 | self.then(null, function(err) {
355 | setTimeout(function() {
356 | throw err;
357 | }, 0);
358 | });
359 | };
360 | }
361 | }, {} ],
362 | 6: [ function(require, module, exports) {
363 | var asap = require("asap");
364 | if (typeof Promise === "undefined") {
365 | Promise = require("./lib/core.js");
366 | require("./lib/es6-extensions.js");
367 | }
368 | require("./polyfill-done.js");
369 | }, {
370 | "./lib/core.js": 2,
371 | "./lib/es6-extensions.js": 3,
372 | "./polyfill-done.js": 5,
373 | asap: 4
374 | } ]
375 | }, {}, [ 6 ]);
376 | //# sourceMappingURL=/polyfills/promise-6.1.0.js.map
--------------------------------------------------------------------------------
/flux-demo/flux-demo-static/src/js/store/flux-demo.js:
--------------------------------------------------------------------------------
1 | import dispatcher from '../dispatcher/dispatcher';
2 |
3 | const data = {
4 | introduction: {}
5 | };
6 |
7 | const createStore = (methods) => {
8 | let name;
9 |
10 | class Store extends EventEmitter {};
11 |
12 | for (name in methods) {
13 | Store.prototype[name] = methods[name];
14 | }
15 |
16 | return new Store();
17 | };
18 |
19 | const fluxDemoStore = createStore({
20 | getIntroduction (name) {
21 | return data.introduction[name];
22 | }
23 | });
24 |
25 | fluxDemoStore.dispatchToken = dispatcher.register((action) => {
26 | switch(action.type) {
27 | case 'FETCH_INTRODUCTION':
28 | // do something
29 | break;
30 |
31 | case 'FETCH_INTRODUCTION_SUCCESS':
32 | data.introduction[action.name] = action.response.data;
33 | fluxDemoStore.emit('change');
34 | break;
35 |
36 | case 'FETCH_INTRODUCTION_ERROR':
37 | // do something
38 | break;
39 | }
40 | });
41 |
42 | export default fluxDemoStore;
43 |
--------------------------------------------------------------------------------
/react-router-demo/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .DS_Store
3 | .orig
4 | .swp
5 | src/js/bundle.js
6 | .cache/
7 | npm-debug.log
8 |
--------------------------------------------------------------------------------
/react-router-demo/README.md:
--------------------------------------------------------------------------------
1 | # React Router Demo
2 |
3 | ### 启动项目
4 |
5 | 在项目根目录中先执行 `npm install` 安装依赖,依赖安装结束后执行 `npm start` 就启动了项目,浏览器中输入 `http://127.0.0.1:3002` 即可访问。
6 |
7 | 本 Demo 在 [从 React Router 谈谈路由的那些事](http://stylechen.com/react-router.html) 有详细的讲解。
--------------------------------------------------------------------------------
/react-router-demo/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var gutil = require('gulp-util');
3 | var babelify = require('babelify');
4 | var browserify = require('browserify');
5 | var watchify = require('watchify');
6 | var cacheify = require('cacheify');
7 | var levelup = require('levelup');
8 | var source = require('vinyl-source-stream');
9 | var less = require('gulp-less');
10 | var connect = require('gulp-connect');
11 | var LessPluginAutoPrefix = require('less-plugin-autoprefix');
12 | var autoprefix= new LessPluginAutoPrefix({ browsers: ['last 2 versions'] });
13 | var db = levelup('./.cache');
14 |
15 | var srcRoot = 'src';
16 | var jsSrcPath = './src/js/index.js';
17 | var jsDestPath = './src/js';
18 |
19 | var browserOpts = {
20 | entries: [jsSrcPath],
21 | debug: true,
22 | insertGlobals: true
23 | };
24 |
25 | gulp.task('connect', function () {
26 | connect.server({
27 | root: [srcRoot],
28 | port: 3002,
29 | livereload: true,
30 | fallback: 'src/index.html'
31 | });
32 | });
33 |
34 | gulp.task('watch-html', function () {
35 | gulp.watch(srcRoot + '/**/*.html', function () {
36 | return gulp.src(srcRoot + '/**/*.html')
37 | .pipe(connect.reload());
38 | });
39 | });
40 |
41 | var bundle = function () {
42 | return watcher.bundle()
43 | .on('error', function (err) {
44 | console.log(err.message);
45 | console.log(err.stack);
46 | })
47 | .pipe(source('bundle.js'))
48 | .pipe(gulp.dest(jsDestPath))
49 | .pipe(connect.reload());
50 | };
51 |
52 | var babelifyCache = cacheify(babelify.configure({
53 | presets: ["es2015", "react"]
54 | }), db);
55 |
56 | var bundler = browserify(browserOpts)
57 | .transform(babelifyCache);
58 |
59 | var watcher = watchify(bundler)
60 | .on('update', bundle)
61 | .on('log', gutil.log);
62 |
63 | gulp.task('watch-js', bundle);
64 | gulp.task('watch', ['watch-js', 'watch-html'])
65 | gulp.task('default', ['connect', 'watch']);
66 |
--------------------------------------------------------------------------------
/react-router-demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-router-demo",
3 | "version": "0.2.0",
4 | "description": "",
5 | "scripts": {
6 | "start": "gulp",
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "chenmnkken@gmail.com",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "babel-preset-es2015": "6.1.18",
13 | "babel-preset-react": "6.1.18",
14 | "babelify": "7.2.0",
15 | "browserify": "12.0.1",
16 | "cacheify": "0.4.1",
17 | "gulp": "3.9.0",
18 | "gulp-connect": "2.2.0",
19 | "gulp-less": "3.0.5",
20 | "gulp-util": "3.0.7",
21 | "less-plugin-autoprefix": "1.5.1",
22 | "leveldown": "1.4.2",
23 | "levelup": "1.3.0",
24 | "vinyl-source-stream": "1.1.0",
25 | "watchify": "3.6.1"
26 | },
27 | "dependencies": {
28 | "react": "0.14.5",
29 | "react-dom": "0.14.5",
30 | "react-router": "2.0.0-rc4"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/react-router-demo/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React Router Demo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/react-router-demo/src/js/component/about.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | class About extends React.Component {
4 | componentDidMount () {
5 | console.log('mount');
6 | }
7 |
8 | componentWillUnmount () {
9 | console.log('un mount');
10 | }
11 |
12 | render () {
13 | return (
14 | This is About page.
15 | );
16 | }
17 | };
18 |
19 | export default About;
20 |
--------------------------------------------------------------------------------
/react-router-demo/src/js/component/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | class App extends React.Component {
5 | render () {
6 | return (
7 |
8 |
React Router Demo
9 |
10 |
11 | by stylechen.com
12 |
13 |
14 | - Home
15 | - About
16 | - Concat
17 | - List 001
18 | - List 002
19 |
20 | {this.props.children}
21 |
22 | )
23 | }
24 | };
25 |
26 | export default App;
27 |
--------------------------------------------------------------------------------
/react-router-demo/src/js/component/concat.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Concat = () => {
4 | return (
5 | This is Concat page.
6 | );
7 | };
8 |
9 | export default Concat;
10 |
--------------------------------------------------------------------------------
/react-router-demo/src/js/component/list.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | class List extends React.Component {
4 | render () {
5 | return (
6 |
7 |
This is List page.
8 |
The list page id is
9 | {this.props.params.id}
10 |
11 |
12 | );
13 | }
14 | };
15 |
16 | export default List;
17 |
--------------------------------------------------------------------------------
/react-router-demo/src/js/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import App from './component/app';
5 | import About from './component/about';
6 | import Concat from './component/concat';
7 | import List from './component/list';
8 |
9 | import {Router, Route, browserHistory} from 'react-router';
10 |
11 | const router = (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | );
20 |
21 | ReactDOM.render(
22 | router,
23 | document.getElementById('root')
24 | );
25 |
--------------------------------------------------------------------------------