├── src ├── less │ └── common.less ├── components │ ├── index.js │ └── header.vue ├── pages │ ├── index │ │ ├── logo.png │ │ └── index.vue │ ├── home │ │ └── index.vue │ ├── signout │ │ └── index.vue │ └── login │ │ └── index.vue ├── css │ └── common.css ├── app.vue ├── store │ ├── index.js │ └── user.js ├── template │ └── index.html ├── main.js └── config │ └── routes.js ├── .babelrc ├── config └── index.js ├── server.js ├── docs ├── 2.md └── 1.md ├── gulpfile.js ├── package.json ├── webpack.config.js └── README.md /src/less/common.less: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import header from './header' 2 | export default { header } -------------------------------------------------------------------------------- /src/pages/index/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sijinglei/vue2-demo/master/src/pages/index/logo.png -------------------------------------------------------------------------------- /src/css/common.css: -------------------------------------------------------------------------------- 1 | input::-webkit-outer-spin-button, 2 | input::-webkit-inner-spin-button{ 3 | -webkit-appearance: none !important; 4 | margin: 0; 5 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "stage-0" 5 | ], 6 | "plugins": [ 7 | "transform-object-assign", 8 | "transform-vue-jsx" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/app.vue: -------------------------------------------------------------------------------- 1 | 4 | 7 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import user from './user' 4 | 5 | Vue.use(Vuex) 6 | 7 | export default new Vuex.Store({ 8 | strict: process.env.NODE_ENV !== 'production', //在非生产环境下,使用严格模式 9 | modules: { 10 | user 11 | } 12 | }) -------------------------------------------------------------------------------- /src/template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | vue2-demo 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /src/pages/home/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 13 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devTest: { //部署到测试服务器上 3 | remotePath: '/app/', //部署到服务器的路径 4 | host: '111.11.111.111', //ip地址 5 | user: 'root', //帐号 6 | pass: '88888888', //密码 7 | port: 22 //端口 8 | }, 9 | devDist: { //部署正式服务器上 10 | remotePath: '/app/', //部署到服务器的路径 11 | host: '111.11.111.111', //ip地址 12 | user: 'root', //帐号 13 | pass: '88888888', //密码 14 | port: 22 //端口 15 | }, 16 | publicPath: '/app/', //程序在网站根路径地址 17 | target: 'https://cnodejs.org/' //连接的服务器地址 18 | } 19 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const Webpack = require("webpack") 2 | const WebpackDevServer = require('webpack-dev-server') 3 | const webpackConfig = require("./webpack.config") 4 | const config = require('./config/') 5 | 6 | var compiler = Webpack(webpackConfig) 7 | var server = new WebpackDevServer(compiler, { 8 | publicPath: config.publicPath, 9 | stats: { 10 | colors: true //显示不同的颜色区分打包的文件 11 | }, 12 | proxy: { //代理服务器 13 | '*': { 14 | target: config.target, 15 | changeOrigin: true 16 | } 17 | } 18 | }) 19 | 20 | server.listen(3000, (err) => { 21 | if (err) { 22 | console.log(err) 23 | return 24 | } 25 | console.log('http://localhost:3000' + config.publicPath) 26 | }) -------------------------------------------------------------------------------- /src/pages/signout/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 20 | -------------------------------------------------------------------------------- /src/store/user.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export const USER_SIGNIN = 'USER_SIGNIN' //登录成功 4 | export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登录 5 | 6 | export default { 7 | state: JSON.parse(sessionStorage.getItem('user')) || {}, 8 | mutations: { 9 | [USER_SIGNIN](state, user) { 10 | sessionStorage.setItem('user', JSON.stringify(user)) 11 | Object.assign(state, user) 12 | }, 13 | [USER_SIGNOUT](state) { 14 | sessionStorage.removeItem('user') 15 | Object.keys(state).forEach(k => Vue.delete(state, k)) 16 | } 17 | }, 18 | actions: { 19 | [USER_SIGNIN]({commit}, user) { 20 | commit(USER_SIGNIN, user) 21 | }, 22 | [USER_SIGNOUT]({commit}) { 23 | commit(USER_SIGNOUT) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | import routes from './config/routes' 5 | import store from './store/' 6 | import components from './components/' //加载公共组件 7 | 8 | import './css/common.css' 9 | import './less/common.less' 10 | 11 | Object.keys(components).forEach((key) => { 12 | var name = key.replace(/(\w)/, (v) => v.toUpperCase()) //首字母大写 13 | Vue.component(`v${name}`, components[key]) 14 | }) 15 | 16 | Vue.use(VueRouter) 17 | 18 | const router = new VueRouter({ 19 | routes 20 | }) 21 | router.beforeEach(({meta, path}, from, next) => { 22 | var { auth = true } = meta 23 | var isLogin = Boolean(store.state.user.id) //true用户已登录, false用户未登录 24 | 25 | if (auth && !isLogin && path !== '/login') { 26 | return next({ path: '/login' }) 27 | } 28 | next() 29 | }) 30 | 31 | new Vue({ store, router }).$mount('#app') -------------------------------------------------------------------------------- /src/components/header.vue: -------------------------------------------------------------------------------- 1 | 25 | 36 | -------------------------------------------------------------------------------- /src/pages/index/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 27 | -------------------------------------------------------------------------------- /src/config/routes.js: -------------------------------------------------------------------------------- 1 | import App from '../app' 2 | /** 3 | * auth true登录才能访问,false不需要登录,默认true 4 | */ 5 | export default [ 6 | { 7 | path: '/', 8 | component: App, 9 | children: [ 10 | { 11 | path: '/login', //登录 12 | meta: { auth: false }, 13 | component: resolve => require(['../pages/login/'], resolve) 14 | }, 15 | { 16 | path: '/signout', //退出 17 | component: resolve => require(['../pages/signout/'], resolve) 18 | }, 19 | { 20 | path: '/home', //个人主页 21 | component: resolve => require(['../pages/home/'], resolve) 22 | }, 23 | { 24 | path: '/', //首页 25 | meta: { auth: false }, 26 | component: resolve => require(['../pages/index/'], resolve) 27 | }, 28 | { 29 | path: '*', //其他页面,强制跳转到登录页面 30 | redirect: '/login' 31 | } 32 | ] 33 | } 34 | ] -------------------------------------------------------------------------------- /docs/2.md: -------------------------------------------------------------------------------- 1 | ## 2.实现登录退出 2 | 3 | ### 1.页面访问入口html 4 | [src/template/index.html](../src/template/index.html) 5 | 6 | ### 2.程序入口文件 7 | [src/main.js](../src/main.js) 加载各种公共的css,less,字体图标,组件,权限验证,等 8 | 9 | ### 3.vuex 10 | [src/store/index.js](../src/store/index.js) 加载各种模块,实例化 11 | [src/store/user.js](../src/store/user.js) 创建用户状态模块 12 | 13 | ### 4.配置路由 14 | [src/config/routes.js](../src/config/routes.js) 按需加载模块 15 | [src/app.vue](../src/app.vue) 可以放置一些公共头部或底部 16 | 17 | ### 5.登录页面 18 | [src/pages/login/index.vue](../src/pages/login/index.vue) 将用户的数据存储在vuex中 19 | [src/component/index.js](../src/component/index.js) 加载各种公共组件 20 | [src/component/header.vue](../src/component/header.vue) 公共头部组件 21 | 22 | ### 6.个人中心 23 | [src/pages/home/index.vue](../src/pages/home/index.vue) 从vuex中读取用户的数据 24 | 25 | ### 7.退出登录 26 | [src/pages/signout/index.vue](../src/pages/signout/index.vue) 删除vuex中的用户数据 27 | 28 | ### 8.首页 29 | [src/pages/index/index.vue](../src/pages/index/index.vue) 根据用户登录,显示对应的内容 -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const path = require('path') 3 | const config = require('./config/') 4 | const isEnv = process.env.NODE_ENV == 'production' 5 | 6 | /** 7 | * 清除生产目录文件 8 | */ 9 | const del = require('del') 10 | gulp.task('clean', ['upload'], function (callback) { 11 | console.log('## 已经成功部署到服务器上') 12 | console.log('## 清除原来编译的代码') 13 | del(['.' + config.publicPath], callback) 14 | }) 15 | 16 | /** 17 | * 编译代码 18 | */ 19 | const webpack = require('webpack') 20 | const webpackConfig = require('./webpack.config') 21 | gulp.task('build', function (callback) { 22 | console.log('## 代码编译开始') 23 | webpack(webpackConfig, function (err, state) { 24 | console.log('## 代码编译完成') 25 | callback(err) 26 | }) 27 | }) 28 | 29 | /** 30 | * 编译代码,自动部署到服务器 31 | */ 32 | const ftp = require('gulp-sftp') 33 | gulp.task('upload', ['build'], function (callback) { 34 | console.log('## 正在部署到服务器上') 35 | var dev = isEnv ? config.devDist : config.devTest 36 | gulp.src('.' + config.publicPath + '**') 37 | .pipe(ftp(Object.assign(dev, {callback}))) 38 | }) 39 | 40 | /** 41 | * 上传到测试服务器上 42 | */ 43 | gulp.task('devTest', ['build', 'upload', 'clean']) 44 | 45 | /** 46 | * 上传到生产服务器上 47 | */ 48 | gulp.task('devDist', ['build', 'upload', 'clean']) 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "node server", 8 | "dev:dist": "cross-env NODE_ENV=production gulp devDist", 9 | "dev:test": "gulp devTest" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "autoprefixer-loader": "^3.2.0", 15 | "babel-core": "^6.18.0", 16 | "babel-helper-vue-jsx-merge-props": "^2.0.1", 17 | "babel-loader": "^6.2.7", 18 | "babel-plugin-syntax-jsx": "^6.18.0", 19 | "babel-plugin-transform-object-assign": "^6.8.0", 20 | "babel-plugin-transform-vue-jsx": "^3.1.1", 21 | "babel-preset-es2015": "^6.18.0", 22 | "babel-preset-stage-0": "^6.16.0", 23 | "cross-env": "^3.1.3", 24 | "css-loader": "^0.25.0", 25 | "del": "^2.2.2", 26 | "file-loader": "^0.9.0", 27 | "gulp": "^3.9.1", 28 | "gulp-sftp": "^0.1.5", 29 | "html-webpack-plugin": "^2.24.0", 30 | "less": "^2.7.1", 31 | "less-loader": "^2.2.3", 32 | "style-loader": "^0.13.1", 33 | "url-loader": "^0.5.7", 34 | "vue-loader": "^9.7.0", 35 | "webpack": "^1.13.3", 36 | "webpack-dev-server": "^1.16.2" 37 | }, 38 | "dependencies": { 39 | "vue": "^2.1.4", 40 | "vue-router": "^2.1.1", 41 | "vuex": "^2.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/pages/login/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 37 | -------------------------------------------------------------------------------- /docs/1.md: -------------------------------------------------------------------------------- 1 | ## 1.安装开发环境 2 | #### vs code https://code.visualstudio.com 3 | ``` 4 | 开发时所用的编辑器,内置了终端,开发时使它执行命令运行程序 5 | ``` 6 | #### Node.js https://nodejs.org 7 | ``` 8 | JS服务器端的运行环境,内置npm包管理器,管理项目依赖的各种模块,编译代码,自动部署到服务器就全靠他了 9 | ``` 10 | 11 | ### 2.安装全局模块 12 | #### webpack 13 | ``` 14 | npm install -g webpack 15 | ``` 16 | webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理 17 | 18 | 19 | #### gulp 20 | ``` 21 | npm install -g gulp 22 | ``` 23 | gulp是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务 24 | 25 | ### 3.创建项目 26 | ``` 27 | 创建项目目录,并且在项目目录下执行命令,初始化package.json文件 28 | npm init 29 | ``` 30 | 31 | ### 4.安装开发环境依赖模块 npm install --save-dev 模块名 32 | ``` 33 | npm install --save-dev webpack webpack-dev-server html-webpack-plugin url-loader file-loader css-loader less less-loader style-loader autoprefixer-loader babel-core babel-loader babel-plugin-transform-object-assign babel-preset-es2015 babel-preset-stage-0 vue-loader babel-helper-vue-jsx-merge-props babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx gulp gulp-sftp del cross-env 34 | ``` 35 | ### 5.安装生产环境依赖模块 npm install --save 模块名 36 | ``` 37 | npm install --save vue vue-router vuex 38 | ``` 39 | 40 | ### 5.搭建开发环境 41 | + [config/index.js](../config/index.js) 配置项目开发时的信息 42 | + [webpack.config.js](../webpack.config.js) webpack打包配置 43 | + [.babelrc](../.babelrc) ES6编译配置 44 | + [server.js](../server.js) 设置代理服务器 45 | + [gulpfile.js](../gulpfile.js) 自动化打包,编译,压缩,部署服务器 46 | + [package.json](../package.json) 执行npm init 初始化项目,自定义命令,启动程序,自动部署 47 | 48 | ### 6.测试编译 49 | #### src/template/index.html 50 | ```html 51 | 52 | 53 | 54 | 55 | 56 | vue2-demo 57 | 58 | 59 | 60 | 61 | 62 | 63 | ``` 64 | #### src/main.js 65 | ```javascript 66 | alert('test') 67 | ``` 68 | ``` 69 | 1.运行程序执行命令:npm run dev 70 | 2.然后打开网址:http://localhost:3000/app/ 71 | 3.如果浏览器弹出test,说明我们的开发环境已经搭建通过。 72 | ``` 73 | #### package.json自定义命令说明 74 | ``` 75 | npm run dev 开发环境 76 | npm run dev:test 将代码打包到测试服务器 77 | npm run dev:dist 将代码打包到正式服务器 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | const config = require('./config/') 5 | const IS_ENV = process.env.NODE_ENV == 'production' 6 | 7 | 8 | var plugins = [] 9 | if (IS_ENV) { //生产环境 10 | plugins.push(new webpack.DefinePlugin({ 11 | 'process.env': { //设置成生产环境 12 | NODE_ENV: '"production"' 13 | } 14 | })) 15 | plugins.push(new webpack.optimize.UglifyJsPlugin({ //压缩代码 16 | compress: { 17 | warnings: false 18 | } 19 | })) 20 | } 21 | 22 | plugins.push( 23 | new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML 24 | filename: './index.html', //生成的html存放路径,相对于 path 25 | template: './src/template/index.html', //html模板路径 26 | }) 27 | ) 28 | 29 | 30 | module.exports = { 31 | entry: ['./src/main.js'], //编译入口文件 32 | output: { 33 | publicPath: config.publicPath, //服务器的路径 34 | path: path.resolve(__dirname + config.publicPath), //编译到app目录 35 | filename: '[name].js?[hash]' //编译后的文件名 36 | }, 37 | module: { 38 | loaders: [ 39 | { 40 | test: /\.js(x)*$/, 41 | exclude: /^node_modules$/, 42 | loader: 'babel' 43 | }, 44 | { 45 | test: /\.vue$/, 46 | loader: 'vue' 47 | }, 48 | { 49 | test: /\.css/, 50 | exclude: /^node_modules$/, 51 | loader: `style-loader!css-loader!autoprefixer-loader?{ browsers: ['last 100 versions'] }!` 52 | }, 53 | { 54 | test: /\.less/, 55 | exclude: /^node_modules$/, 56 | loader: `style-loader!css-loader!autoprefixer-loader?{ browsers: ['last 100 versions'] }!less-loader` 57 | }, 58 | { 59 | test: /\.(png|jpg)$/, 60 | exclude: /^node_modules$/, 61 | loader: 'url?limit=2000&name=[name].[ext]' //注意后面那个limit的参数,当你图片大小小于这个限制的时候,会自动启用base64编码图片 62 | }, 63 | { 64 | test: /\.(eot|woff|svg|ttf|woff2|gif|appcache)(\?|$)/, 65 | exclude: /^node_modules$/, 66 | loader: 'file-loader?name=[name].[ext]' 67 | } 68 | ] 69 | }, 70 | plugins, 71 | resolve: { 72 | extensions: ['', '.js', '.vue', '.jsx'], //后缀名自动补全 73 | alias: { 74 | vue: 'vue/dist/vue.js', //webpack打包时,需要设置别名 75 | store: path.resolve('src/store/'), //常用工具方法 76 | } 77 | }, 78 | vue: { 79 | postcss: [ 80 | require('autoprefixer')({ 81 | browsers: ['last 100 versions'] 82 | }) 83 | ] 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 前言 2 | ``` 3 | 国庆在回家的路上,得知了vue2发布了正式版, 4 | 国庆回来后,在公司内两个项目便直接应用上了vue2, 5 | 一个是PC端的商户后台,一个是微信端商城, 6 | 都是基于Vue2、vue-router、vuex ...... 7 | 在开发的过程中,遇到了一系列的问题, 8 | 比如页面后退数据还原,滚动条还原, 9 | 登录超时,获取列表数据,表单提交, 10 | 多台服务器自动化部署,最终后一个个解决了, 11 | 能够平稳的从react切换到vue2开发,vue的文档功不可没。 12 | ``` 13 | github:[https://github.com/lzxb/vue2-demo](https://github.com/lzxb/vue2-demo) 14 | 15 | ## 源码说明 16 | ### 项目目录说明 17 | ``` 18 | . 19 | |-- config // 项目开发环境配置 20 | | |-- index.js // 项目打包部署配置 21 | |-- src // 源码目录 22 | | |-- components // 公共组件 23 | | |-- header.vue // 页面头部公共组件 24 | | |-- index.js // 加载各种公共组件 25 | | |-- config // 路由配置和程序的基本信息配置 26 | | |-- routes.js // 配置页面路由 27 | | |-- css // 各种css文件 28 | | |-- common.css // 全局通用css文件 29 | | |-- iconfont // 各种字体图标 30 | | |-- images // 公共图片 31 | | |-- less // 各种less文件 32 | | |-- common.less // 全局通用less文件 33 | | |-- pages // 页面组件 34 | | |-- home // 个人中心 35 | | |-- index // 网站首页 36 | | |-- login // 登录 37 | | |-- signout // 退出 38 | | |-- store // vuex的状态管理 39 | | |-- index.js // 加载各种store模块 40 | | |-- user.js // 用户store 41 | | |-- template // 各种html文件 42 | | |-- index.html // 程序入口html文件 43 | | |-- util // 公共的js方法,vue的mixin混合 44 | | |-- app.vue // 页面入口文件 45 | | |-- main.js // 程序入口文件,加载各种公共组件 46 | |-- .babelrc // ES6语法编译配置 47 | |-- gulpfile.js // 启动,打包,部署,自动化构建 48 | |-- webpack.config.js // 程序打包配置 49 | |-- server.js // 代理服务器配置 50 | |-- README.md // 项目说明 51 | |-- package.json // 配置项目相关信息,通过执行 npm init 命令创建 52 | . 53 | ``` 54 | 55 | ### 开发环境依赖模块说明 56 | #### webpack相关模块 57 | ``` 58 | webpack // 用来构建打包程序 59 | webpack-dev-server // 开发环境下,设置代理服务器 60 | html-webpack-plugin // html 文件编译 61 | url-loader // 图片 转化成base64格式 62 | file-loader // 字体 将字体文件打包 63 | css-loader // css 生成 64 | less // css 预处理器less 65 | less-loader // css 预处理器less的webpack插件 66 | style-loader // css 插入到style标签 67 | autoprefixer-loader // css 浏览器兼容性问题处理 68 | babel-core // ES6 代码转换器 69 | babel-loader // ES6 代码转换器,webpack插件 70 | babel-plugin-transform-object-assign // ES6 Object.assign方法做兼容处理 71 | babel-preset-es2015 // ES6 代码编译成现在浏览器支持的ES5 72 | babel-preset-stage-0 // ES6 ES7要使用的语法阶段 73 | vue-loader // vue 组件编译 74 | babel-helper-vue-jsx-merge-props // vue jsx语法编译 75 | babel-plugin-syntax-jsx // vue jsx语法编译 76 | babel-plugin-transform-vue-jsx // vue jsx语法编译 77 | ``` 78 | 79 | #### gulp相关模块 80 | ``` 81 | gulp // 用来构建自动化工作流 82 | gulp-sftp // 将代码自动部署到服务器上 83 | del // 代码部署成功后,删除本地编译的代码 84 | ``` 85 | #### 其他模块 86 | ``` 87 | cross-env // 解决跨平台设置NODE_ENV的问题 88 | ``` 89 | ### 生产模块依赖说明 90 | #### vue全家桶 91 | ``` 92 | vue // 构建用户界面的 93 | vue-router // 路由 94 | vuex // 组件状态管理 95 | ``` 96 | 97 | ### 页面说明 98 | ``` 99 | /login // 登录,不需要登录可以访问 100 | /signout // 退出登录,需要登录后才可以访问 101 | /home // 个人中心,需要登录后才可以访问 102 | / // 首页,不需要登录可以访问 103 | * // 强制跳转到登录页面 104 | ``` 105 | 106 | ### 运行程序 107 | ``` 108 | npm install 109 | npm run dev 110 | http://localhost:3000/app/ 111 | ``` 112 | 113 | ## 开发教程 114 | [1.开发环境搭建](https://github.com/lzxb/vue2-demo/blob/master/docs/1.md) 115 | [2.实现登录退出](https://github.com/lzxb/vue2-demo/blob/master/docs/2.md) 116 | --------------------------------------------------------------------------------