├── .babelrc
├── views
├── index.jade
├── error.jade
└── layout.jade
├── app
├── images
│ ├── footer_cart.png
│ ├── footer_class.png
│ ├── footer_shop.png
│ ├── footer_cart_on.png
│ ├── footer_class_on.png
│ ├── footer_service.png
│ ├── footer_shop_on.png
│ └── footer_service_on.png
├── main.js
├── components
│ ├── App.js
│ ├── Index.jsx
│ ├── footer.sass
│ ├── HeadSwiper.jsx
│ ├── css.sass
│ ├── Sections.jsx
│ └── footer.js
├── sass
│ └── base.sass
├── index.html
└── test.js
├── .gitignore
├── routes
├── index.js
└── users.js
├── README.md
├── server.js
├── app.js
├── package.json
├── bin
└── www
├── index.html
├── webpack.config.js
└── webpack.config.prod.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-0", "react"]
3 | }
--------------------------------------------------------------------------------
/views/index.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | h1= title
5 | p Welcome to #{title}
6 |
--------------------------------------------------------------------------------
/app/images/footer_cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_cart.png
--------------------------------------------------------------------------------
/app/images/footer_class.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_class.png
--------------------------------------------------------------------------------
/app/images/footer_shop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_shop.png
--------------------------------------------------------------------------------
/app/images/footer_cart_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_cart_on.png
--------------------------------------------------------------------------------
/app/images/footer_class_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_class_on.png
--------------------------------------------------------------------------------
/app/images/footer_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_service.png
--------------------------------------------------------------------------------
/app/images/footer_shop_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_shop_on.png
--------------------------------------------------------------------------------
/app/images/footer_service_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kunkun12/react-mishop/HEAD/app/images/footer_service_on.png
--------------------------------------------------------------------------------
/views/error.jade:
--------------------------------------------------------------------------------
1 | extends layout
2 |
3 | block content
4 | h1= message
5 | h2= error.status
6 | pre #{error.stack}
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .sass-cache
3 | node_modules/
4 | *.swp
5 | *.swo
6 | *.swn
7 | .idea
8 | scripts/*
9 | .sass-cache
10 | npm-debug.log
11 | ftp/*
12 |
--------------------------------------------------------------------------------
/views/layout.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | title= title
5 | link(rel='stylesheet', href='/stylesheets/style.css')
6 | body
7 | block content
8 |
--------------------------------------------------------------------------------
/app/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './components/App'
4 | setTimeout(function(){
5 | ReactDOM.render(,document.getElementById('app'));
6 | },300);
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 |
4 | /* GET home page. */
5 | router.get('/', function(req, res, next) {
6 | res.render('index', { title: 'Express' });
7 | });
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/routes/users.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 |
4 | /* GET users listing. */
5 | router.get('/', function(req, res, next) {
6 | res.send('respond with a resource');
7 | });
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 技术栈: `Webpack`+`React`+`Sass`
4 |
5 | * 运行 `npm install` 安装依赖
6 | * 开发环境运行 `npm start` 访问
7 | * 生产环境 `npm run bulld` 生成的生产环境代码在build目录下
8 | * 开发环境支持热更新
9 | * ES6
10 | * 多屏适配 rem解决方案
11 | * Sass、postcss
12 | * 里面中用到的相关数据均为模拟测试数据。
13 | * [在线预览](http://kunkun12.com/react-mishop/)
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/components/App.js:
--------------------------------------------------------------------------------
1 | import {} from '../sass/base.sass';
2 | import React from 'react';
3 | import Index from './Index'
4 | import Data from '../test.js'
5 | class App extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | this.state=Data;
9 | }
10 | render() {
11 | return (
12 |
13 |
14 |
15 | );
16 | }
17 | }
18 |
19 |
20 | export default App;
--------------------------------------------------------------------------------
/app/components/Index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import HeadSwiper from './HeadSwiper'
3 | import Sections from './Sections'
4 | import Footer from './Footer'
5 | class Index extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | this.state=this.props;
9 | }
10 | render() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 | }
20 |
21 | export default Index;
22 |
--------------------------------------------------------------------------------
/app/sass/base.sass:
--------------------------------------------------------------------------------
1 | body,h1,h2,h3,p,dl,dd,ol,ul,th,td,form,fieldset,input,button,textarea
2 | margin: 0
3 | padding: 0
4 | html
5 | -webkit-text-size-adjust: none
6 | word-wrap: break-word
7 | h1,h2,h3
8 | font-size: 100%
9 | ol,ul
10 | list-style: none
11 | table
12 | border-collapse: collapse
13 | border-spacing: 0
14 | empty-cells: show
15 | font-size: inherit
16 | fieldset,img
17 | border: 0
18 | cite,em,s,i,b
19 | font-style: normal
20 | input,button,textarea,select
21 | font-size: 100%
22 | body,input,button,textarea,select,option
23 | font-size: normal
24 | a,input,textarea
25 | text-decoration: none
26 | outline: 0
27 | -webkit-tap-highlight-color: rgba(0,0,0,0)
28 | li,img,label,input
29 | vertical-align: middle
30 | var
31 | font-style: normal
32 | ins
33 | text-decoration: none
34 |
35 | html,body
36 | height: 100%
37 | font-size: (20rem/100)
38 | font-family: Arial, Verdana, Sans-serif
39 | .viewport
40 | width: 100%
41 | max-width: (720rem/100)
42 | margin: 0 auto
43 |
--------------------------------------------------------------------------------
/app/components/footer.sass:
--------------------------------------------------------------------------------
1 | @import "compass/utilities"
2 | @import "compass/css3"
3 |
4 |
5 | .footer
6 | position: fixed
7 | bottom: 0
8 | left: 0
9 | right: 0
10 | background: #FFF
11 | z-index: 99
12 | border-top: 1px solid #e0e0e0
13 | ul
14 | display: flex
15 | justify-content:center
16 | .nav
17 | .ispr
18 | width: (40rem/100)
19 | height: (40rem/100)
20 | +background-size((40rem/100) (40rem/100))
21 | overflow: hidden
22 | margin: 0 auto (8rem/100)
23 | &.ih
24 | background-image: url("../images/footer_shop.png")
25 | &.ic
26 | background-image: url("../images/footer_class.png")
27 | &.is
28 | background-image: url("../images/footer_cart.png")
29 | &.if
30 | background-image: url("../images/footer_service.png")
31 | p
32 | font-size: (22rem/100)
33 | line-height: 0.8
34 | color: #999999
35 | li
36 | flex: 1
37 | width: 100%
38 | text-align: center
39 | &>a
40 | display: block
41 | padding: (12rem/100) 0
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const express = require('express');
3 | const webpack = require('webpack');
4 | const webpackMiddleware = require('webpack-dev-middleware');
5 | const webpackHotMiddleware = require('webpack-hot-middleware');
6 | const config = require('./webpack.config.js');
7 |
8 | const isDeveloping = process.env.NODE_ENV !== 'production';
9 | const port = isDeveloping ? 4000 : process.env.port;
10 | const app = express();
11 |
12 | if (isDeveloping) {
13 | const compiler = webpack(config);
14 | const middleware = webpackMiddleware(compiler, {
15 | publicPath: config.output.publicPath,
16 | contentBase: 'build',
17 | stats: {
18 | colors: true,
19 | hash: false,
20 | timings: true,
21 | chunks: false,
22 | chunkModules: false,
23 | modules: false
24 | }
25 | });
26 |
27 | app.use(middleware);
28 | app.use(webpackHotMiddleware(compiler));
29 | // app.get('*', function response(req, res) {
30 | // res.write(middleware.fileSystem.readFileSync(path.join(__dirname, 'build/index.html')));
31 | // res.end();
32 | // });
33 | } else {
34 | app.use(express.static(__dirname + '/build'));
35 | app.get('*', function response(req, res) {
36 | res.sendFile(path.join(__dirname, 'build/index.html'));
37 | });
38 | }
39 | app.listen(port, '0.0.0.0', function onStart(err) {
40 | if (err) {
41 | console.log(err);
42 | }
43 | console.info('==> 🌎 Listening on port %s. Open up http://0.0.0.0:%s/ in your browser.', port, port);
44 | });
--------------------------------------------------------------------------------
/app/components/HeadSwiper.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactSwipe from 'react-swipe'
3 | import css from "./css.sass"
4 | class HeadSwiper extends React.Component {
5 |
6 | constructor(props) {
7 | super(props);
8 | this.state={
9 | selectindex:0,
10 | swipecount:this.props.swipedata.length
11 | }
12 | }
13 | swipechanges(e){
14 | var index=e%this.state.swipecount;
15 | this.setState({
16 | selectindex:index
17 | })
18 |
19 | }
20 | render() {
21 | var swipes=[];
22 | var swipestyle={
23 | height:"3.6rem",
24 | width:"7.2rem"
25 | },
26 | swipeimg={
27 | width: "100%"
28 | };
29 | var navs=[];
30 | this.props.swipedata.forEach((i,b)=>{
31 | swipes.push()
32 | navs.push();
33 | });
34 | return (
35 |
36 |
37 | {swipes}
38 |
39 |
42 |
43 |
44 | );
45 | }
46 | }
47 |
48 |
49 | export default HeadSwiper;
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var path = require('path');
3 | var favicon = require('serve-favicon');
4 | var logger = require('morgan');
5 | var cookieParser = require('cookie-parser');
6 | var bodyParser = require('body-parser');
7 |
8 | var routes = require('./routes/index');
9 | var users = require('./routes/users');
10 |
11 | var app = express();
12 |
13 | // view engine setup
14 | app.set('views', path.join(__dirname, 'views'));
15 | app.set('view engine', 'jade');
16 |
17 | // uncomment after placing your favicon in /public
18 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
19 | app.use(logger('dev'));
20 | app.use(bodyParser.json());
21 | app.use(bodyParser.urlencoded({ extended: false }));
22 | app.use(cookieParser());
23 | app.use(express.static(path.join(__dirname, 'public')));
24 |
25 | app.use('/', routes);
26 | app.use('/users', users);
27 |
28 | // catch 404 and forward to error handler
29 | app.use(function(req, res, next) {
30 | var err = new Error('Not Found');
31 | err.status = 404;
32 | next(err);
33 | });
34 |
35 | // error handlers
36 |
37 | // development error handler
38 | // will print stacktrace
39 | if (app.get('env') === 'development') {
40 | app.use(function(err, req, res, next) {
41 | res.status(err.status || 500);
42 | res.render('error', {
43 | message: err.message,
44 | error: err
45 | });
46 | });
47 | }
48 |
49 | // production error handler
50 | // no stacktraces leaked to user
51 | app.use(function(err, req, res, next) {
52 | res.status(err.status || 500);
53 | res.render('error', {
54 | message: err.message,
55 | error: {}
56 | });
57 | });
58 |
59 |
60 | module.exports = app;
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-tool",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "clean": "rimraf dist",
7 | "build:webpack": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js",
8 | "build": "npm run clean && npm run build:webpack&&NODE_ENV=production port=3000 node server.js",
9 | "start": "node server.js",
10 | "lint": "eslint src"
11 | },
12 | "dependencies": {
13 | "gulp": "^3.9.1",
14 | "gulp-util": "^3.0.7",
15 | "react": "^0.14.7",
16 | "react-dom": "^0.14.7",
17 | "react-lazy-load": "^3.0.5",
18 | "react-swipe": "4.0.1"
19 | },
20 | "devDependencies": {
21 | "autoprefixer": "^6.3.6",
22 | "babel-core": "^6.5.2",
23 | "babel-loader": "^6.2.3",
24 | "babel-preset-es2015": "^6.5.0",
25 | "babel-preset-react": "^6.5.0",
26 | "babel-preset-react-hmre": "^1.1.0",
27 | "babel-preset-stage-0": "^6.5.0",
28 | "body-parser": "~1.13.2",
29 | "compass-mixins": "^0.12.7",
30 | "cookie-parser": "~1.3.5",
31 | "cross-env": "^1.0.7",
32 | "css-loader": "^0.23.1",
33 | "debug": "~2.2.0",
34 | "express": "~4.13.1",
35 | "file-loader": "^0.8.5",
36 | "gulp-clean": "^0.3.2",
37 | "html-loader": "^0.4.3",
38 | "html-webpack-plugin": "^2.9.0",
39 | "jade": "^1.11.0",
40 | "jade-html-loader": "0.0.3",
41 | "morgan": "~1.6.1",
42 | "node-sass": "^3.4.2",
43 | "postcss-loader": "^0.8.2",
44 | "precss": "^1.4.0",
45 | "rimraf": "^2.5.2",
46 | "sass-loader": "^3.1.2",
47 | "serve-favicon": "~2.3.0",
48 | "style-loader": "^0.13.0",
49 | "url-loader": "^0.5.7",
50 | "webpack": "^1.12.2",
51 | "webpack-dev-middleware": "^1.2.0",
52 | "webpack-hot-middleware": "^2.2.0"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React-Mi-Shop
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
33 |
34 |
35 |
38 |
39 |
--------------------------------------------------------------------------------
/bin/www:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * Module dependencies.
5 | */
6 |
7 | var app = require('../app');
8 | var debug = require('debug')('css-tool:server');
9 | var http = require('http');
10 |
11 | /**
12 | * Get port from environment and store in Express.
13 | */
14 |
15 | var port = normalizePort(process.env.PORT || '3000');
16 | app.set('port', port);
17 |
18 | /**
19 | * Create HTTP server.
20 | */
21 |
22 | var server = http.createServer(app);
23 |
24 | /**
25 | * Listen on provided port, on all network interfaces.
26 | */
27 |
28 | server.listen(port);
29 | server.on('error', onError);
30 | server.on('listening', onListening);
31 |
32 | /**
33 | * Normalize a port into a number, string, or false.
34 | */
35 |
36 | function normalizePort(val) {
37 | var port = parseInt(val, 10);
38 |
39 | if (isNaN(port)) {
40 | // named pipe
41 | return val;
42 | }
43 |
44 | if (port >= 0) {
45 | // port number
46 | return port;
47 | }
48 |
49 | return false;
50 | }
51 |
52 | /**
53 | * Event listener for HTTP server "error" event.
54 | */
55 |
56 | function onError(error) {
57 | if (error.syscall !== 'listen') {
58 | throw error;
59 | }
60 |
61 | var bind = typeof port === 'string'
62 | ? 'Pipe ' + port
63 | : 'Port ' + port;
64 |
65 | // handle specific listen errors with friendly messages
66 | switch (error.code) {
67 | case 'EACCES':
68 | console.error(bind + ' requires elevated privileges');
69 | process.exit(1);
70 | break;
71 | case 'EADDRINUSE':
72 | console.error(bind + ' is already in use');
73 | process.exit(1);
74 | break;
75 | default:
76 | throw error;
77 | }
78 | }
79 |
80 | /**
81 | * Event listener for HTTP server "listening" event.
82 | */
83 |
84 | function onListening() {
85 | var addr = server.address();
86 | var bind = typeof addr === 'string'
87 | ? 'pipe ' + addr
88 | : 'port ' + addr.port;
89 | debug('Listening on ' + bind);
90 | }
91 |
--------------------------------------------------------------------------------
/app/components/css.sass:
--------------------------------------------------------------------------------
1 | @import "compass/utilities"
2 | @import "compass/css3"
3 | .indexpage
4 | padding-bottom: 0.8rem
5 | .swapwrap
6 | position: relative;
7 | .swipe-nav
8 | position: absolute
9 | bottom: 0.1rem
10 | left: 0
11 | right: 0
12 | display: flex
13 | justify-content: center
14 | li
15 | width: .8em
16 | height: .8em
17 | margin: 0 (8em/20)
18 | +border-radius((20em/20))
19 | background: #e5e5e5
20 | opacity: .8
21 | &.on
22 | background: #ccc
23 | .HeadSwiper
24 | position: relative
25 |
26 | .list
27 | transform: translate3d(0,0,0)
28 | background: #FFF
29 | .item
30 | display: flex
31 | align-items: center
32 | padding: (30rem/100) 0
33 | border-bottom: 1px solid #F2F2F2
34 | .section
35 | &:last-child
36 | .item
37 | border: none
38 | .info
39 | flex: 1
40 | margin-right: (20rem/100)
41 | .img
42 | width: (254rem/100)
43 | height: (145rem/100)
44 | position: relative
45 | .ico
46 | width: 100%
47 | .tag
48 | position: absolute
49 | width: (120rem/100)
50 | height: (120rem/100)
51 | bottom: 0
52 | left: (10rem/100)
53 | opacity: .9 !important
54 | z-index: 2
55 | .name
56 | font-size: (30rem/100)
57 | color: #000
58 | margin-bottom: (10rem/100)
59 | .brief
60 | font-size: (26rem/100)
61 | line-height: (34rem/100)
62 | color: #969696
63 | margin-bottom: (12rem/100)
64 | .price
65 | font-size: (28rem/100)
66 | color: #FE4900
67 |
--------------------------------------------------------------------------------
/app/components/Sections.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactSwipe from 'react-swipe'
3 | import LazyLoad from 'react-lazy-load';
4 | import css from "./css.sass"
5 |
6 | export default class Sections extends React.Component {
7 | constructor(props) {
8 | super(props);
9 | }
10 | render() {
11 | var items=this.props.Sections.map((item,i)=>{
12 | var items=item.body.items;
13 | return items.map(function(a,b){
14 | return(
15 |
16 |
17 |
18 |
19 |
![]()
20 | {
21 | a.product_tag?

:""
22 | }
23 |
24 |
25 |
26 |
{a.product_name}
27 |
28 |
29 |
{a.product_brief}
30 |
31 |
32 |
{a.product_price}
33 |
34 |
35 |
)
36 | })
37 | });
38 | return (
39 |
40 |
41 | {items}
42 |
43 |
44 | );
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-mishop
6 |
7 |
8 |
34 |
35 |
36 |
37 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
61 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/components/footer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactSwipe from 'react-swipe'
3 | import css from "./footer.sass"
4 |
5 | export default class Footer extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 | render() {
10 | return ( < div className = 'footer' >
11 |
57 | < /div >
58 | );
59 | }
60 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require("webpack");
2 | var path = require('path');
3 | var gutil = require("gulp-util");
4 | var node_modules = path.resolve(__dirname, 'node_modules');
5 | var HtmlWebpackPlugin = require('html-webpack-plugin');
6 | var precss = require('precss');
7 | var autoprefixer = require('autoprefixer');
8 | var myConfig = {
9 | debug: true,
10 | devtool: 'source-map',
11 | entry: ['webpack-hot-middleware/client?reload=true',path.resolve(__dirname, 'app/main.js')],
12 | context: path.resolve(process.cwd(), 'app'),
13 | output: {
14 | path: path.resolve(__dirname, 'build'),
15 | filename: 'main.js',
16 | publicPath: ""
17 | },
18 | module: {
19 | loaders: [{
20 | test: /\.jsx?$/,
21 | exclude: /node_modules/,
22 | loader: 'babel',
23 | query: {
24 | "presets": ["react", "es2015", "stage-0", "react-hmre"]
25 | }
26 | }, {
27 | test: /\.jade$/,
28 | loader: 'html!jade-html'
29 | }, {
30 | test: /\.css$/,
31 | loader: 'style!css'
32 | }, {
33 | test: /\.sass$/,
34 | loader: "style!css!postcss-loader!sass?indentedSyntax&includePaths[]=" + path.resolve(__dirname, "./node_modules/compass-mixins/lib") + "&includePaths[]=" + path.resolve(__dirname, "./mixins/app_mixins")
35 | }, {
36 | test: /\.(png|jpg)$/,
37 | loader: 'url-loader?limit=10000&name=[path][name]-[hash:8].[ext]'
38 | }]
39 | },
40 | postcss: function () {
41 | return [precss, autoprefixer];
42 | },
43 | resolve: {
44 | root: [path.resolve(process.cwd(), 'app'), path.resolve(__dirname, 'node_modules')], //设置搜索目录
45 | alias: {
46 | images: './images'
47 | },
48 | extensions: ['', '.js', '.jade', '.jsx']
49 | },
50 | plugins: [
51 | new HtmlWebpackPlugin({ // Also generate a test.html
52 | filename: 'index.html',
53 | template: 'index.html',
54 | }),
55 | new webpack.NoErrorsPlugin(),
56 | new webpack.optimize.OccurenceOrderPlugin(),
57 | new webpack.HotModuleReplacementPlugin(),
58 | new webpack.DefinePlugin({
59 | 'process.env.NODE_ENV': JSON.stringify('development')
60 | }),
61 | new webpack.ProgressPlugin(function handler(percentage, msg) {
62 | gutil.log(msg)
63 | })
64 | ]
65 | };
66 |
67 |
68 | module.exports = myConfig;
--------------------------------------------------------------------------------
/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | var webpack = require("webpack");
2 | var path = require('path');
3 | var gutil = require("gulp-util");
4 | var node_modules = path.resolve(__dirname, 'node_modules');
5 | var HtmlWebpackPlugin = require('html-webpack-plugin');
6 | var precss = require('precss');
7 | var autoprefixer = require('autoprefixer');
8 | var myConfig = {
9 | debug: true,
10 | devtool: 'source-map',
11 | entry: [path.resolve(__dirname, 'app/main.js')],
12 | context: path.resolve(process.cwd(), 'app'),
13 | output: {
14 | path: path.resolve(__dirname, 'build'),
15 | filename: '[name][hash].js',
16 | publicPath: ""
17 | },
18 | module: {
19 | loaders: [{
20 | test: /\.jsx?$/,
21 | exclude: /node_modules/,
22 | loader: 'babel',
23 | query: {
24 | "presets": ["react", "es2015", "stage-0"]
25 | },
26 | include: path.join(__dirname, 'app')
27 | }, {
28 | test: /\.jade$/,
29 | loader: 'html!jade-html'
30 | }, {
31 | test: /\.css$/,
32 | loader: 'style!css!postcss-loader'
33 | }, {
34 | test: /\.sass$/,
35 | loader: "style!css!postcss-loader!sass?indentedSyntax&includePaths[]=" + path.resolve(__dirname, "./node_modules/compass-mixins/lib") + "&includePaths[]=" + path.resolve(__dirname, "./mixins/app_mixins")
36 | }, {
37 | test: /\.(png|jpg)$/,
38 | loader: 'url-loader?limit=10000&name=[path][name]-[hash:8].[ext]'
39 | }]
40 | },
41 | postcss: function() {
42 | return [precss, autoprefixer];
43 | },
44 | resolve: {
45 | root: [path.resolve(process.cwd(), 'app'), path.resolve(__dirname, 'node_modules')], //设置搜索目录
46 | alias: {
47 | images: './images'
48 | },
49 | extensions: ['', '.js', '.jade', '.jsx']
50 | },
51 | plugins: [
52 | new HtmlWebpackPlugin({ // Also generate a test.html
53 | filename: 'index.html',
54 | template: 'index.html',
55 | }),
56 | new webpack.NoErrorsPlugin(),
57 | new webpack.optimize.OccurenceOrderPlugin(),
58 | new webpack.optimize.UglifyJsPlugin({
59 | compressor: {
60 | warnings: false
61 | }
62 | }),
63 | new webpack.DefinePlugin({
64 | 'process.env.NODE_ENV': JSON.stringify('production')
65 | }),
66 | new webpack.ProgressPlugin(function handler(percentage, msg) {
67 | gutil.log(msg)
68 | })
69 | ]
70 | };
71 |
72 |
73 | module.exports = myConfig;
--------------------------------------------------------------------------------
/app/test.js:
--------------------------------------------------------------------------------
1 | var data={
2 | "swipedata": [
3 | {
4 | "img": "http://i8.mifile.cn/v1/a1/T1_jKgBbdT1RXrhCrK.jpg"
5 | },
6 | {
7 | "img": "http://i8.mifile.cn/v1/a1/T1B4_jBsYT1RXrhCrK.jpg"
8 | },
9 | {
10 | "img": "http://i8.mifile.cn/v1/a1/T1tXKgBgbv1RXrhCrK.jpg"
11 | },
12 | {
13 | "img": "http://i8.mifile.cn/v1/a1/T1tXKgBgbv1RXrhCrK.jpg"
14 | }
15 | ],
16 | "Sections": [
17 | {
18 | "body": {
19 | "items": [
20 | {
21 | "img_url": "http://i8.mifile.cn/v1/a1/T14xJTByZ_1RXrhCrK.jpg",
22 | "product_brief": "骁龙820处理器 / 4GB 内存 / 128GB 闪存 / 4轴防抖相机 / 3D陶瓷机身 / 3月1日早10点首轮开售",
23 | "product_name": "小米手机5",
24 | "product_price": "1999元 起",
25 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/xp.png",
26 | "view_type": ""
27 | }
28 | ]
29 | },
30 | "phone_type": "0",
31 | "view_type": "fast_recommend"
32 | },
33 | {
34 | "body": {
35 | "items": [
36 | {
37 | "img_url": "http://i8.mifile.cn/v1/a1/T1Z5bgBCYv1RXrhCrK.jpg",
38 | "product_brief": "骁龙808处理器 / 64GB大容量 / 指纹识别 / 全网通双卡双待 / 5英寸屏非凡手感 / 13MP相位对焦相机",
39 | "product_name": "小米手机4S",
40 | "product_price": "1699元",
41 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/xp.png",
42 | "view_type": ""
43 | }
44 | ]
45 | },
46 | "phone_type": "0",
47 | "view_type": "fast_recommend"
48 | },
49 | {
50 | "body": {
51 | "items": [
52 | {
53 | "img_url": "http://i1.mifile.cn/v1/a1/T1RWWgBghT1RXrhCrK.jpg",
54 | "product_brief": "独立 HiFi 音乐系统 / 5.7英寸全高清屏幕 / 骁龙801四核处理器",
55 | "product_name": "小米Note",
56 | "product_price": "1499元 起",
57 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/d300.png",
58 | "view_type": ""
59 | }
60 | ]
61 | },
62 | "phone_type": "0",
63 | "view_type": "fast_recommend"
64 | },
65 | {
66 | "body": {
67 | "items": [
68 | {
69 | "img_url": "http://i1.mifile.cn/v1/a1/T1TrdjBKLT1RXrhCrK.jpg",
70 | "product_brief": "Type-C 双面充电接口 / 红外遥控 / 5英寸全高清阳光屏 / 骁龙808六核处理器",
71 | "product_name": "小米手机4c",
72 | "product_price": "1299元",
73 | "product_tag": "",
74 | "view_type": ""
75 | }
76 | ]
77 | },
78 | "phone_type": "0",
79 | "view_type": "fast_recommend"
80 | },
81 | {
82 | "body": {
83 | "items": [
84 | {
85 | "img_url": "http://i1.mifile.cn/v1/a1/T1WdJjBmdT1RXrhCrK.jpg",
86 | "product_brief": "4.7英寸视网膜屏 / 骁龙410四核处理器 / 800万像素相机 / 2GB内存+16GB容量 / 最高支持32GB扩展",
87 | "product_name": "红米2A高配双卡版",
88 | "product_price": "499元",
89 | "product_tag": "",
90 | "view_type": ""
91 | }
92 | ]
93 | },
94 | "phone_type": "0",
95 | "view_type": "fast_recommend"
96 | },
97 | {
98 | "body": {
99 | "items": [
100 | {
101 | "img_url": "http://i1.mifile.cn/v1/a1/T1VNJjBsdT1RXrhCrK.jpg",
102 | "product_brief": "金属机身 / 指纹识别 / 4050mAh大电池 / 5.5英寸全高清屏",
103 | "product_name": "红米Note 3",
104 | "product_price": "899元 起",
105 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/xp.png",
106 | "view_type": ""
107 | }
108 | ]
109 | },
110 | "phone_type": "0",
111 | "view_type": "fast_recommend"
112 | },
113 | {
114 | "body": {
115 | "items": [
116 | {
117 | "img_url": "http://i1.mifile.cn/v1/a1/T1LuWgBjhT1RXrhCrK.jpg",
118 | "product_brief": "金属机身 / 4100mAh大电池 / 5英寸阳光屏 / 骁龙616八核处理器 / 2GB内存+16GB容量",
119 | "product_name": "红米手机3",
120 | "product_price": "699元",
121 | "product_tag": "",
122 | "view_type": ""
123 | }
124 | ]
125 | },
126 | "phone_type": "0",
127 | "view_type": "fast_recommend"
128 | },
129 | {
130 | "body": {
131 | "items": [
132 | {
133 | "img_url": "http://i1.mifile.cn/v1/a1/T1jFWjBjJT1RXrhCrK.jpg",
134 | "product_brief": "不锈钢边框 / 5英寸屏超窄边 / 骁龙801四核处理器 / MIUI、Win10 双系统",
135 | "product_name": "小米手机4",
136 | "product_price": "1299元 起",
137 | "product_tag": "",
138 | "view_type": ""
139 | }
140 | ]
141 | },
142 | "phone_type": "0",
143 | "view_type": "fast_recommend"
144 | },
145 | {
146 | "body": {
147 | "items": [
148 | {
149 | "img_url": "http://i8.mifile.cn/v1/a1/T1GaJgB7hv1RXrhCrK.jpg",
150 | "product_brief": "5.5英寸全贴合大屏 / 骁龙410四核处理器 / 1300万像素相机 / 2GB内存+16GB容量 / 3200mAh大电池",
151 | "product_name": "红米Note 电信4G双卡增强版",
152 | "product_price": "799元",
153 | "product_tag": "",
154 | "view_type": ""
155 | }
156 | ]
157 | },
158 | "phone_type": "0",
159 | "view_type": "fast_recommend"
160 | },
161 | {
162 | "body": {
163 | "items": [
164 | {
165 | "img_url": "http://i1.mifile.cn/v1/a1/T1lBYjBKdT1RXrhCrK.jpg",
166 | "product_brief": "4.7英寸舒适手感 / 高通64位处理器",
167 | "product_name": "红米手机2",
168 | "product_price": "599元 起",
169 | "product_tag": "",
170 | "view_type": ""
171 | }
172 | ]
173 | },
174 | "phone_type": "0",
175 | "view_type": "fast_recommend"
176 | },
177 | {
178 | "body": {
179 | "items": [
180 | {
181 | "img_url": "http://i1.mifile.cn/v1/a1/T1RXWgBsCT1RXrhCrK.jpg",
182 | "product_brief": "全金属机身 / 7.9英寸视网膜屏幕 / 800万像素相机 / 6190mAh大电池 / 支持5V/2A快充",
183 | "product_name": "小米平板2",
184 | "product_price": "999元 起",
185 | "product_tag": "",
186 | "view_type": ""
187 | }
188 | ]
189 | },
190 | "phone_type": "0",
191 | "view_type": "fast_recommend"
192 | },
193 | {
194 | "body": {
195 | "items": [
196 | {
197 | "img_url": "http://i1.mifile.cn/v1/a1/T1H0K_ByKv1RXrhCrK.jpg",
198 | "product_brief": "全金属轻薄机身 / 次世代分体电视",
199 | "product_name": "小米电视3",
200 | "product_price": "3999元起",
201 | "product_tag": "",
202 | "view_type": ""
203 | }
204 | ]
205 | },
206 | "phone_type": "0",
207 | "view_type": "fast_recommend"
208 | },
209 | {
210 | "body": {
211 | "items": [
212 | {
213 | "img_url": "http://i1.mifile.cn/v1/a1/T1YKC_BC_v1RXrhCrK.jpg",
214 | "product_brief": "全新升级64位 4K网络机顶盒 / 标配小米蓝牙语音体感遥控器",
215 | "product_name": "小米盒子3",
216 | "product_price": "299元",
217 | "product_tag": "",
218 | "view_type": ""
219 | }
220 | ]
221 | },
222 | "phone_type": "0",
223 | "view_type": "fast_recommend"
224 | },
225 | {
226 | "body": {
227 | "items": [
228 | {
229 | "img_url": "http://i1.mifile.cn/v1/a1/T14mdjBKxT1RXrhCrK.jpg",
230 | "product_brief": "高品质电芯 / 铝合金金属外壳",
231 | "product_name": "小米移动电源",
232 | "product_price": "49元 起",
233 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/hot.png",
234 | "view_type": ""
235 | }
236 | ]
237 | },
238 | "phone_type": "0",
239 | "view_type": "fast_recommend"
240 | },
241 | {
242 | "body": {
243 | "items": [
244 | {
245 | "img_url": "http://i1.mifile.cn/v1/a1/T1aFDjB_ZT1RXrhCrK.jpg",
246 | "product_brief": "美国ADI传感器 / 30天超长续航",
247 | "product_name": "小米手环",
248 | "product_price": "69元 起",
249 | "product_tag": "",
250 | "view_type": ""
251 | }
252 | ]
253 | },
254 | "phone_type": "0",
255 | "view_type": "fast_recommend"
256 | },
257 | {
258 | "body": {
259 | "items": [
260 | {
261 | "img_url": "http://i1.mifile.cn/v1/a1/T1R.xjBT_T1RXrhCrK.jpg",
262 | "product_brief": "22公里超长续航 / 轻、小、便携 / 重心驱动 / 15重安全保障",
263 | "product_name": "九号平衡车",
264 | "product_price": "1999元",
265 | "product_tag": "",
266 | "view_type": ""
267 | }
268 | ]
269 | },
270 | "phone_type": "0",
271 | "view_type": "fast_recommend"
272 | },
273 | {
274 | "body": {
275 | "items": [
276 | {
277 | "img_url": "http://i8.mifile.cn/v1/a1/T1ktDgBgEv1RXrhCrK.jpg",
278 | "product_brief": "全新空气增压系统,净化能力高达310m³/h / 高效360°桶形净化滤芯 / 低分贝,低功耗 / 手机智能控制,一目了然",
279 | "product_name": "小米空气净化器2",
280 | "product_price": "699元",
281 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/by.png",
282 | "view_type": ""
283 | }
284 | ]
285 | },
286 | "phone_type": "0",
287 | "view_type": "fast_recommend"
288 | },
289 | {
290 | "body": {
291 | "items": [
292 | {
293 | "img_url": "http://s1.mi.com/m/images/20151028/water.jpg",
294 | "product_brief": "400加仑大流量 / RO反渗透直出纯净水",
295 | "product_name": "小米净水器",
296 | "product_price": "1299元",
297 | "product_tag": "",
298 | "view_type": ""
299 | }
300 | ]
301 | },
302 | "phone_type": "0",
303 | "view_type": "fast_recommend"
304 | },
305 | {
306 | "body": {
307 | "items": [
308 | {
309 | "img_url": "http://i1.mifile.cn/v1/a1/T12xLgBjZT1RXrhCrK.jpg",
310 | "product_brief": "3个USB充电口 / 支持2A快充 / 3重安全保护 / 隐藏式提示灯 / 超薄小插头 / 迷你设计,仅1个铅笔盒大小",
311 | "product_name": "小米插线板",
312 | "product_price": "49元",
313 | "product_tag": "",
314 | "view_type": ""
315 | }
316 | ]
317 | },
318 | "phone_type": "0",
319 | "view_type": "fast_recommend"
320 | },
321 | {
322 | "body": {
323 | "items": [
324 | {
325 | "img_url": "http://i1.mifile.cn/v1/a1/T19IWjBvKT1RXrhCrK.jpg",
326 | "product_brief": "MFI认证产品 / 镀金C48端子头,镀锡工艺铜线 / 支持5V/2.4A电量输出",
327 | "product_name": "苹果Lightning to USB数据线",
328 | "product_price": "39元",
329 | "product_tag": "",
330 | "view_type": ""
331 | }
332 | ]
333 | },
334 | "phone_type": "0",
335 | "view_type": "fast_recommend"
336 | },
337 | {
338 | "body": {
339 | "items": [
340 | {
341 | "img_url": "http://i1.mifile.cn/v1/a1/T1tTA_BsCT1RXrhCrK.jpg",
342 | "product_brief": "全金属外观 / 双USB智能输出 / 支持快充",
343 | "product_name": "小米车载充电器",
344 | "product_price": "49元",
345 | "product_tag": "",
346 | "view_type": ""
347 | }
348 | ]
349 | },
350 | "phone_type": "0",
351 | "view_type": "fast_recommend"
352 | },
353 | {
354 | "body": {
355 | "items": [
356 | {
357 | "img_url": "http://i1.mifile.cn/v1/a1/T1mwV_Bydv1RXrhCrK.jpg",
358 | "product_brief": "表面蜂窝形设计,防刮花 / 高弹性静音轮胎 / 内饰采用亲肤纺织布料,环保安全",
359 | "product_name": "90分旅行箱 24寸",
360 | "product_price": "349元",
361 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/by.png",
362 | "view_type": ""
363 | }
364 | ]
365 | },
366 | "phone_type": "0",
367 | "view_type": "fast_recommend"
368 | },
369 | {
370 | "body": {
371 | "items": [
372 | {
373 | "img_url": "http://i1.mifile.cn/v1/a1/T1Eyb_BXEv1RXrhCrK.jpg",
374 | "product_brief": "4重存储空间,可携带14寸电脑 / 填充EPE珍珠棉,减少双肩背部压力",
375 | "product_name": "小米极简都市双肩包",
376 | "product_price": "149元",
377 | "product_tag": "",
378 | "view_type": ""
379 | }
380 | ]
381 | },
382 | "phone_type": "0",
383 | "view_type": "fast_recommend"
384 | },
385 | {
386 | "body": {
387 | "items": [
388 | {
389 | "img_url": "http://i8.mifile.cn/v1/a1/T1WbL_B5Vv1RXrhCrK.jpg",
390 | "product_brief": "播放音乐、车载充电二合一 / 蓝牙配对,一键连接 / 双口充电,8重电路保护",
391 | "product_name": "车载蓝牙播放器",
392 | "product_price": "69元",
393 | "product_tag": "",
394 | "view_type": ""
395 | }
396 | ]
397 | },
398 | "phone_type": "0",
399 | "view_type": "fast_recommend"
400 | },
401 | {
402 | "body": {
403 | "items": [
404 | {
405 | "img_url": "http://i1.mifile.cn/v1/a1/T1alVjBQCT1RXrhCrK.jpg",
406 | "product_brief": "动圈+动铁 双发声单元 / 金属音腔 / 线控麦克风,清晰的通话质量",
407 | "product_name": "小米圈铁耳机",
408 | "product_price": "99元",
409 | "product_tag": "",
410 | "view_type": ""
411 | }
412 | ]
413 | },
414 | "phone_type": "0",
415 | "view_type": "fast_recommend"
416 | },
417 | {
418 | "body": {
419 | "items": [
420 | {
421 | "img_url": "http://i1.mifile.cn/v1/a1/T1HTh_Bs_T1RXrhCrK.jpg",
422 | "product_brief": "进口高密度电芯 / 双USB输出 / 支持快速自充 / 便携轻便,仅338克",
423 | "product_name": "小米移动电源20000mAh",
424 | "product_price": "149元",
425 | "product_tag": "",
426 | "view_type": ""
427 | }
428 | ]
429 | },
430 | "phone_type": "0",
431 | "view_type": "fast_recommend"
432 | },
433 | {
434 | "body": {
435 | "items": [
436 | {
437 | "img_url": "http://i1.mifile.cn/v1/a1/T1PLJgB_dT1RXrhCrK.jpg",
438 | "product_brief": "碱性10粒装5号环保电池,无汞无镉 / 防泄漏技术,双重安全保障 / 十种绚丽色彩,送收纳盒",
439 | "product_name": "彩虹5号电池",
440 | "product_price": "9.9元",
441 | "product_tag": "",
442 | "view_type": ""
443 | }
444 | ]
445 | },
446 | "phone_type": "0",
447 | "view_type": "fast_recommend"
448 | },
449 | {
450 | "body": {
451 | "items": [
452 | {
453 | "img_url": "http://i1.mifile.cn/v1/a1/T16RE_BQxv1RXrhCrK.jpg",
454 | "product_brief": "12小时超长播放 / 金属机身外壳 / 轻巧便携 / 支持免提通话",
455 | "product_name": "小钢炮蓝牙音箱",
456 | "product_price": "99元",
457 | "product_tag": "",
458 | "view_type": ""
459 | }
460 | ]
461 | },
462 | "phone_type": "0",
463 | "view_type": "fast_recommend"
464 | },
465 | {
466 | "body": {
467 | "items": [
468 | {
469 | "img_url": "http://i1.mifile.cn/v1/a1/T1mvb_ByAv1RXrhCrK.jpg",
470 | "product_brief": "仅270克,方便携带 / 完全充电,可持续使用8小时 / 支持Micro SD卡 / 支持免提通话",
471 | "product_name": "小米蓝牙音箱",
472 | "product_price": "199元",
473 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/by.png",
474 | "view_type": ""
475 | }
476 | ]
477 | },
478 | "phone_type": "0",
479 | "view_type": "fast_recommend"
480 | },
481 | {
482 | "body": {
483 | "items": [
484 | {
485 | "img_url": "http://i1.mifile.cn/v1/a1/T1K3A_BsAT1RXrhCrK.jpg",
486 | "product_brief": "掌心大小 / PCB天线覆盖大,抗干扰 / 一键穿墙技术,自动提升信号强度",
487 | "product_name": "小米路由器青春版",
488 | "product_price": "79元",
489 | "product_tag": "",
490 | "view_type": ""
491 | }
492 | ]
493 | },
494 | "phone_type": "0",
495 | "view_type": "fast_recommend"
496 | },
497 | {
498 | "body": {
499 | "items": [
500 | {
501 | "img_url": "http://i1.mifile.cn/v1/a1/T1RlE_BvDT1RXrhCrK.jpg",
502 | "product_brief": "小巧轻便 / 一步配对免安装 / 不用切换热点,自动选择最优信号 / 180°旋转的USB插口",
503 | "product_name": "小米Wifi放大器",
504 | "product_price": "39元",
505 | "product_tag": "http://c1.mifile.cn/f/i/f/mishop/iic/hot.png",
506 | "view_type": ""
507 | }
508 | ]
509 | },
510 | "phone_type": "0",
511 | "view_type": "fast_recommend"
512 | },
513 | {
514 | "body": {
515 | "items": [
516 | {
517 | "img_url": "http://i1.mifile.cn/v1/a1/T13EL_B5hv1RXrhCrK.jpg",
518 | "product_brief": "100克,喝杯水都可感知的精准 / 高精度压力传感器 / 手机管理全家健康",
519 | "product_name": "小米体重秤",
520 | "product_price": "99元",
521 | "product_tag": "",
522 | "view_type": ""
523 | }
524 | ]
525 | },
526 | "phone_type": "0",
527 | "view_type": "fast_recommend"
528 | },
529 | {
530 | "body": {
531 | "items": [
532 | {
533 | "img_url": "http://i1.mifile.cn/v1/a1/T17rh_BsVT1RXrhCrK.jpg",
534 | "product_brief": "原装三星真4K屏 / 四核1.4GHz CPU / 9.9mm全金属纤薄机身",
535 | "product_name": "小米电视2S 48英寸",
536 | "product_price": "2799元",
537 | "product_tag": "",
538 | "view_type": ""
539 | }
540 | ]
541 | },
542 | "phone_type": "0",
543 | "view_type": "fast_recommend"
544 | },
545 | {
546 | "body": {
547 | "items": [
548 | {
549 | "img_url": "http://i1.mifile.cn/v1/a1/T17CxjBvET1RXrhCrK.jpg",
550 | "product_brief": "720P高清分辨率 / 111°广角 / 双向语音通话 / 4倍变焦,看到画面的每一个细节",
551 | "product_name": "小蚁智能摄像机",
552 | "product_price": "149元",
553 | "product_tag": "",
554 | "view_type": ""
555 | }
556 | ]
557 | },
558 | "phone_type": "0",
559 | "view_type": "fast_recommend"
560 | },
561 | {
562 | "body": {
563 | "items": [
564 | {
565 | "img_url": "http://i1.mifile.cn/v1/a1/T1vrh_BsCT1RXrhCrK.jpg",
566 | "product_brief": "6.5克轻巧 / 蓝牙4.1高清通话音质 / 荣获德国IF设计大奖 / 低噪音硅麦,语音更清晰",
567 | "product_name": "小米蓝牙耳机",
568 | "product_price": "79元",
569 | "product_tag": "",
570 | "view_type": ""
571 | }
572 | ]
573 | },
574 | "phone_type": "0",
575 | "view_type": "fast_recommend"
576 | }
577 | ]
578 | };
579 |
580 |
581 | export default data;
--------------------------------------------------------------------------------