Vue教程--使用官方脚手架构建实例(下篇)

本文基于工作项目开发,做的整理笔记
因工作需要,项目框架由最初的Java/jsp模式,逐渐转移成node/express模式。现在新项目又因为业务流程中的交互操作,会使页面dom根据数据data不断显示变化,便觉得此时是否是最佳实际,应该尝试一下vue框架。因为之前也偷偷的进行了一些vue框架的踩坑工作,已经填了一些坑或者有一些解决方案了,这也才敢用上。依然由后台Java提供API。本文就是做个笔记,说明如何使用Vue官方脚手架开始构建项目。

前提条件:
你已经听过、了解过Vue,至少一点点。

编码环境:
系统:OS X EI Capitan
版本:10.12.2

共2篇:
上篇:http://www.jianshu.com/p/ee2464501c65
下篇:http://www.jianshu.com/p/9baa03eb31fc(当前)

vue.jpg

目录
| - 0.传送门
| - 1.安装
| - 2.项目初始化
| - 3.项目构建
  | - Step1.阅读结构
  | - Step2. 阅读代码(泛读)
| - 4.项目实操
  | - Step1. 修改eslint配置
  | - Step2. 调整结构
  | - Step3. 添加登陆页面
  | - Step4. 模版嵌套
  | - (上下篇分割线)
  | - Step5. 引入mockjs独立开发
  | - Step6. 调用API接口
  | - Step7. 状态管理(store仓库)
  | - Step8. 抽离公共方法
  | - Step9. 剥离组件
  | - Finish. 生辰打包
| - 5.项目部署
  | - a)本地部署
  | - b)服务器部署
| - 6.结束

Step5. 引入mockjs独立开发

在前后端分离的开发中,为了不因为后端接口还没有弄好,前端开发处于Waiting状态,我们引入mock.js实现假数据接口,从而完成整个页面逻辑流程。

关于mock.js的知识,可以浏览官网http://mockjs.com/

我们这里准备拿登录接口的请求做实验。

先去./src/api文件夹下创建login.js文件,代码如下所示:

vue-demo
| -
| - src
  | - api
     | - login.js (新增)
  | -
| -

# ./src/api/login.js
import { fetch } from '@/utils/fetch';   //@表示的含义还记得是在webpack里定义的

export function loginByEmail(email, password) {
  const data = {
    email,
    password
  };
  return fetch({
    url: '/login/loginbyemail',
    method: 'post',
    params: data
  });
}

export function logout() {
  return fetch({
    url: '/login/logout',
    method: 'post'
  });
}

发现代码里引用了一个公共方法,暂时还没有这个文件和方法,我们这就去./src/utils文件夹下创建fetch.js文件,代码如下所示:

vue-demo
| -
| - src
  | -
  | - utils
     | - fetch.js (新增)
  | -
| -

import axios from 'axios';
import { Message } from 'element-ui';
import router from '../router';

export function fetch(options) {
  return new Promise((resolve, reject) => {
    const instance = axios.create({
      baseURL: process.env.BASE_API,   // 这里我们用了这样一个变量,根据环境选取开发接口还是生产接口
      timeout: 20000 // 超时
    });
    instance(options)
    .then(response => {
      const res = response.data;
      if (res.retCode !== "10000") {
        // console.log(options); // for debug
        // 40600:Token 过期了 50008:非法的token
        if (res.retCode === "40600" || res.retCode === "50008") {
          Message({
            message: res.msg,
            type: 'error',
            duration: 5 * 1000
          });
          router.push({ path: '/login' })
        } else {
          Message({
            message: res.msg,
            type: 'error',
            duration: 5 * 1000
          });
        }
        reject(res);
      } else {
        resolve(res);
      }
    })
    .catch(error => {
      Message({
        message: error,
        type: 'error',
        duration: 5 * 1000
      });
      // console.log(error); // for debug
      reject(error);
    });
  });
}

首先声明process.env.BASE_APIBASE_API变量在这里是用不到的,因为这里启用了mockjs,不会发生真实的请求,已经被拦截了。不过我们还是分别修改一下./config/dev.env.js./config/prod.env.js文件,为了真实的API接口调用时用到,如下所示:

# ./config/dev.env.js
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"http://52.80.14.58:8030/"' //公有IP,不用翻墙
})

# ./config/prod.env.js
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')

module.exports = {
  NODE_ENV: '"production"',
  BASE_API: '"http://52.80.14.58:8030/"', //公有IP,不用翻墙
}

然后去./src/mock文件夹下创建index.jslogin.js文件,代码分别如下所示:

vue-demo
| -
| - src
  | -
  | - mock
     | - index.js (新增)
     | - login.js (新增)
  | -
| -

# ./src/mock/index.js
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import loginAPI from './login';

const mock = new MockAdapter(axios);

// 邮箱登录接口
mock.onPost('/login/loginbyemail').reply(loginAPI.loginByEmail);
// 登出接口
mock.onPost('/login/logout').reply(loginAPI.logout);

export default mock;
# ./src/mock/login.js
const userMap = {
  admin: {
    retCode: "10000",
    msg: "成功",
    time: "2017-06-27 15:05:06",
    data: {
      adminInfo: {
        adminId: "xxxxxxxxxxxxxx",
        email: "admin@fusio.com.cn",
        password2: "123456",
        adminType: 99,
        nickname: "XXXX",
        realName: "XXXX",
        mobile: "xxxxxxxxxxx",
        createTime: "2017-06-27 14:29:51",
        isValid: 0,
        lastModTime: "2017-06-27 14:29:22",
        password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        salt: "xxxxxx",
        comment: "xxxx"
      },
      tokenModel: {
        adminId: "xxxxxxxxxxxxxx",
        token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

export default {
  loginByEmail: config => {
    const { email } = config.params;
    return new Promise((resolve, reject) => {
      if (userMap[email.split('@')[0]]) {
        setTimeout(() => {
          resolve([200, 
            userMap[email.split('@')[0]]
          ]);
        }, 500);
      } else {
        reject('账号不正确')
      }
    })
  },
  logout: () => new Promise(resolve => {
    setTimeout(() => {
      resolve([200, {"retCode":"10000","msg":"成功","time":"2017-06-27 15:19:03","data":null}]);
    }, 100);
  })
};

先去安装一下mock模块,如下:

Yuxinde-MacBook-Pro:vue-demo yuxin$ npm install mockjs --save
npm WARN skippingAction Module is inside a symlinked module: not running update node-pre-gyp@0.6.36 node_modules/fsevents/node_modules/node-pre-gyp
npm WARN skippingAction Module is inside a symlinked module: not running move co@4.6.0 node_modules/ajv-keywords/node_modules/ajv/node_modules/co
npm WARN skippingAction Module is inside a symlinked module: not running move json-stable-stringify@1.0.1 node_modules/ajv-keywords/node_modules/ajv/node_modules/json-stable-stringify
npm WARN skippingAction Module is inside a symlinked module: not running add ajv@4.11.8 node_modules/ajv-keywords/node_modules/ajv
vue-demo@1.0.0 /Users/yuxin/Documents/Season/Project/Vue/vue-demo
└── mockjs@1.0.1-beta3 

我们在./src/main.js中把mock模块引入,代码如下:

# ./src/main.js
...
import './styles/index.scss';
import './mock/index.js';   //新增
...

现在,我们执行npm run dev命令,看一下是否有错误。果然提示我们漏安装一些模块,这些模块在真实的API也可能需要用到,了解请谷歌。

Yuxinde-MacBook-Pro:vue-demo yuxin$ npm run dev

> vue-demo@1.0.0 dev /Users/yuxin/Documents/Season/Project/Vue/vue-demo
> node build/dev-server.js

> Starting dev server...


 ERROR  Failed to compile with 2 errors                                                                                                           17:31:46

These dependencies were not found:

* axios in ./src/mock/index.js
* axios-mock-adapter in ./src/mock/index.js

To install them, you can run: npm install --save axios axios-mock-adapter
> Listening at http://localhost:8080

^C
# 停止运行
# 去安装缺失模块
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm install --save axios axios-mock-adapter
npm WARN skippingAction Module is inside a symlinked module: not running update node-pre-gyp@0.6.36 node_modules/fsevents/node_modules/node-pre-gyp
npm WARN skippingAction Module is inside a symlinked module: not running move co@4.6.0 node_modules/ajv-keywords/node_modules/ajv/node_modules/co
npm WARN skippingAction Module is inside a symlinked module: not running move json-stable-stringify@1.0.1 node_modules/ajv-keywords/node_modules/ajv/node_modules/json-stable-stringify
npm WARN skippingAction Module is inside a symlinked module: not running add ajv@4.11.8 node_modules/ajv-keywords/node_modules/ajv
vue-demo@1.0.0 /Users/yuxin/Documents/Season/Project/Vue/vue-demo
├─┬ axios@0.16.2 
│ └── follow-redirects@1.2.4 
└─┬ axios-mock-adapter@1.9.0 
  └── deep-equal@1.0.1 

# 重新运行
Yuxinde-MacBook-Pro:vue-demo yuxin$ npm run dev

现在没有出现错误,那我们就去修改一下./src/views/login/login.vue文件,我们将重写handleLogin方法,如下:

#./src/views/login/login.vue
      ...
      handleLogin() {
    // 验证表单
        this.$refs.loginForm.validate(valid => {
          if (valid) {
        // 验证通过
            this.loading = true;
            loginByEmail(this.loginForm.email, this.loginForm.password).then(response => {
              console.log(response);  // 这里输出一下,看看是不是我们mock定义的返回
              this.loading = false;
              this.$router.push({ path: '/' });
            }).catch(err => {
              this.loading = false;
              console.error(err);
            });

            //  if(this.loginForm.email == 'admin@fusio.com.cn' && this.loginForm.password == '123456') {
            //  // 注意这里有2种方法
            //  // 注意下不同写法时this的指向问题,用=>可以保持this的固定指向

            //  // 方法1
            //  // let that = this;
            //  // setTimeout(function(){
            //  //  that.loading = false;
            //  //  that.$router.push({ path: '/' });
            //  // }, 1000);

            //  // 方法2
            //  setTimeout(() => {
            //      this.loading = false;
            //      this.$router.push({ path: '/' });
            //  }, 1000);
            // }
          } else {
        // 验证失败
            console.error('error submit!!');
            return false;
          }
        });
      }

现在访问一下http://localhost:8080/login验证是否能够登录成功,验证可行。

同样的,我们去添加一下登出点击后的请求和处理,修改./src/views/layout/Navbar.vue文件,如下:

# ./src/views/layout/Navbar.vue
...
<script>
  import { logout } from '@/api/login';
  export default {
    methods: {
      logout() {
        logout().then(response => {
          console.log(response);  // 这里输出一下,看看是不是我们mock定义的返回
          this.$router.push({ path: '/login' });
        }).catch(err => {
          console.error(err);
        });
      }
    }
  }
</script>
...

那么,“如何使用````mockjs```进行接口假数据返回”到这里就结束啦。

Step6. 调用API接口

因为前面我们已经用mockjs实现了接口请求,只是返回了假数据。那用真实的接口,只是需要暂停使用mockjs,并将api指向真实的接口进行调用。

暂停mockjs的使用,修改./src/main.js文件,如下:

# ./src/main.js
...
// 注释掉这句
// import './mock/index.js';
...

此时你再去访问http://localhost:8080/login网站,点击登录的话,就报错了。

去修改./src/api/login.js文件,把假接口指向真实接口,如下:

# ./src/api/login.js
import { fetch } from '@/utils/fetch';

export function loginByEmail(email, password) {
  const data = {
    email,
    password
  };
  return fetch({
    // url: '/login/loginbyemail',
    url: '/loginController/login',
    method: 'post',
    params: data
  });
}

export function logout() {
  return fetch({
    // url: '/login/logout',
    url: '/loginController/logout',
    method: 'post'
  });
}

此时你再去访问http://localhost:8080/login网站,点击登录进行验证,成功。再去验证一下登出,成功。

注意:有时候你先使用mockjs用假数据接口完成开发,然后再与后台对接真实接口,这里多数时参数、字段都不一样,所以要注意修改。

这时,我们发现一个问题“应该如何记住登录状态”。这样就能实现进入登陆页时自动跳转,没登录或登录过期时需要跳入登录页重新登录。下面就来看“状态管理”这个问题。

Step7. 状态管理(store仓库)

状态管理,我们就要用到vuex,详见http://vuex.vuejs.org/zh-cn/intro.html

文档里告诉我们,状态自管理应用包含以下几个部分:

  • state,驱动应用的数据源;
  • view,以声明方式将state映射到视图;
  • actions,响应在view上的用户输入导致的状态变化。

我们在什么情况下应该考虑用到状态管理:

  • 多个视图依赖于同一状态。
  • 来自不同视图的行为需要变更同一状态。
vuex.jpg

我们先安装vuex模块,如下:

Yuxinde-MacBook-Pro:vue-demo yuxin$ npm install vuex --save
npm WARN skippingAction Module is inside a symlinked module: not running update node-pre-gyp@0.6.36 node_modules/fsevents/node_modules/node-pre-gyp
npm WARN skippingAction Module is inside a symlinked module: not running move co@4.6.0 node_modules/ajv-keywords/node_modules/ajv/node_modules/co
npm WARN skippingAction Module is inside a symlinked module: not running move json-stable-stringify@1.0.1 node_modules/ajv-keywords/node_modules/ajv/node_modules/json-stable-stringify
npm WARN skippingAction Module is inside a symlinked module: not running add ajv@4.11.8 node_modules/ajv-keywords/node_modules/ajv
vue-demo@1.0.0 /Users/yuxin/Documents/Season/Project/Vue/vue-demo
└── vuex@2.3.1 

去store下面创建一系列文件,代码分别如下:

vue-demo
| -
| - src
  | -
  | - store
     | - modules
        | - user.js (新增,state管理)
     | - getters.js (新增,用于返回页面使用数据)
     | - index.js (新增,引用)
  | -
| -

# ./src/store/modules/user.js
import { loginByEmail, logout } from 'api/login';
// 用了storage,就停止了cookie方式
// import Cookies from 'js-cookie';

const user = {
  state: {
    email: '',  // 用户的登录邮箱
    uid: localStorage.getItem('uid'),   // 用户的唯一ID
    auth_type: '',  // 用户的类型
    status: '',  // 用户的状态
    token: localStorage.getItem('token'),    // 用户登录后的token值,其他接口调用要携带,以便检查登录是否有效
    // token: Cookies.get('X-Ivanka-Token'),
    roles: []   // 用户角色
  },

  mutations: {
    SET_EMAIL: (state, email) => {
      state.email = email;
    },
    SET_UID: (state, uid) => {
      state.uid = uid;
    },
    SET_AUTH_TYPE: (state, type) => {
      state.auth_type = type;
    },
    SET_STATUS: (state, status) => {
      state.status = status;
    },
    SET_TOKEN: (state, token) => {
      state.token = token;
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles;
    }
  },

  actions: {
    // 邮箱登录
    LoginByEmail({ commit }, userInfo) {
      const email = userInfo.email.trim();
      return new Promise((resolve, reject) => {
        loginByEmail(email, userInfo.password).then(response => {
          if(response.retCode==="10000") {
            const data = response.data;
            localStorage.token = data.tokenModel.adminId+'_'+data.tokenModel.token;
            localStorage.uid = data.adminInfo.adminId;
            // Cookies.set('X-Ivanka-Token', data.tokenModel.adminId+'_'+data.tokenModel.token);
            commit('SET_TOKEN', data.tokenModel.adminId+'_'+data.tokenModel.token);
            commit('SET_EMAIL', data.adminInfo.email);
            commit('SET_ROLES', ['admin']);
            commit('SET_UID', data.adminInfo.adminId);
            resolve();
          } else {
            reject('账号或密码不正确');
          }
        }).catch(error => {
          reject(error);
        });
      });
    },

    // 登出
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout().then(response => {
          if(response.retCode==="10000") {
            commit('SET_TOKEN', '');
            commit('SET_ROLES', []);
            localStorage.removeItem("token");
            localStorage.removeItem("uid");
            // Cookies.remove('X-Ivanka-Token');
            resolve();
          } else {
            reject('登出失败');
          }
        }).catch(error => {
          reject(error);
        });
      });
    }

  }
};

export default user;

# ./src/store/getters.js
const getters = {
  token: state => state.user.token,
  uid: state => state.user.uid,
  email: state => state.user.email,
  auth_type: state => state.user.auth_type,
  status: state => state.user.status,
  roles: state => state.user.roles
  
};
export default getters

# ./src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
import getters from './getters';

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    user
  },
  getters
});

export default store

接着我们去修改./src/view/login/login.vue文件,代码如下:

# ./src/view/login/login.vue
...
<script>
  // import { loginByEmail } from '@/api/login';    // 注释掉
  ...
     // 重写方法
     handleLogin() {
        // 验证表单
        this.$refs.loginForm.validate(valid => {
          if (valid) {
        // 验证通过
            this.loading = true;

            // 使用状态管理
            this.$store.dispatch('LoginByEmail', this.loginForm).then(() => {
              this.loading = false;
              this.$router.push({ path: '/' });
            }).catch(err => {
              this.loading = false;
              this.$message.error(err);
            });

            // 使用mockjs或真实接口
            ...
...
</script>

接着我们去修改./src/main.js文件,把store引入进来,代码如下:

# ./src/main.js
...
// import './mock/index.js';
import store from './store';    // 新增
...
new Vue({
  el: '#app',
  router,
  store,   // 新增
  template: '<App/>',
  components: { App }
})

此时你再去访问http://localhost:8080/login网站,点击登录进行验证,成功。 调用的时候,去查看Local Storage留意一下。

同样的,我们去改一下登出,修改./src/views/layout/Navbar.vue,然后测试一下。

# ./src/views/layout/Navbar.vue
...
<script>
  // import { logout } from '@/api/login';
  ...
    logout() {
        // 使用状态管理
        this.$store.dispatch('LogOut').then(() => {
          this.$router.push({ path: '/login' });
        }).catch(err => {
          this.$message.error(err);
        });

        // 使用mockjs或真实接口
        ...
...

测试之后,发现登出也可以了。但是我们发现一个问题,现在如果我们直接访问页面http://localhost:8080/dashboard,我们也可以进入,这是不对的,现在我们来看一下这个问题。

修改./src/main.js文件,代码如下:

# ./src/main.js
...
// 新增
const whiteList = ['/login'];// 不重定向白名单、登录、重置密码等等
router.beforeEach((to, from, next) => {
  document.title = (to.name || '') + '- vue demo'   // 设置页面的title
  if (store.getters.token) {   // 根据有没有token去判断是否登录
    if (to.path === '/login') {
      next({ path: '/' });
    } else {
      next();
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next('/login')
    }
  }
});
...

再访问页面http://localhost:8080/dashboard进行测试检查,发现已经可以了。

Step8. 抽离公共方法

由于篇幅有限、时间有限,这里能够给出的demo还是过于简单,并没有什么页面,也没有重复使用的方法。但是这里就提一下吧,多次调用的该抽离的就抽离出去以便可维护,相似的方法集中一个文件也是减少维护成本。

编程思想,我觉得还是很重要的,不单单只是实现页面、实现功能,如何最好的实现,哪种方式、思路更好,这都是慢慢修炼的,哈哈。

Step9. 剥离组件

这个demo也是没有给出复杂页面,实际项目中某些页面是可以有几个功能模块组成的,在这里都没有体现。组件思想在vue算是核心,所以写完一个页面后,就可以开始研究页面的组件化。

我是比较不建议,一个复杂页面上来就开始先做拆分,除非思路很清晰、也没有难点。不过最安全、快捷的方法是先写出来,这样理解已经更透彻,然后才去拆分,我觉得这样是最快的。

(看其他demo吧,或者自己重构一下项目,我可以开放项目接口出来)

Finish. 生成打包

在打包的时候,同事注意到这样一个问题。当我们的命令附带NODE_ENV=production的时候,是不一样的:

# Mac写法
"build:prod": "NODE_ENV=production node build/build.js",
# Windows写法
"build:prod": "set NODE_ENV=production && node build/build.js",

我在做打包部署的时候,遇到这样一个问题。比如我在本地跑起来一个服务,它的域名先使用自定义的,如vue.demo.192.168.4.24.xip.io,网站地址为http://vue.demo.192.168.4.24.xip.io/dashboard。当我刷新页面的时候,就会报“Not Found”错误。

现在看一下这样一个问题是如何产生的?
解答:经过研究测试,这一步需要服务器配置的。不知道是否还有其他解决方案。

如果打包部署出去,发现jscss找不到的问题,一定是config那里不太对,修改配置文件./connfig/index.js

# ./connfig/index.js
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
  build: {
    env: require('./prod.env'),
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: '',
    assetsPublicPath: '/',
    staticPath:'/',
    productionSourceMap: true,
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  },
  dev: {
    env: require('./dev.env'),
    port: 8080,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    staticPath:'/static/',
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }
}

5.项目部署

由于最后我们打包生成并部署的实际上是一个静态网站,那么我们就来看一下如何在本地部署访问和如何在服务器上部署访问。

a)本地部署

本地的话,就直接使用【MAMP】这个软件吧,按步骤一步步安装之后,运行起来基本就可以用了,不需要配置什么。
在“Hosts”那边新增一个Server Name,右边唯一注意的就是把Name resolution的via Xip.io(LAN only)勾选上,这样你就看到下面输入框有个访问地址。在Document root选择你指向的dist文件夹路径(打包文生成的那个)。运行访问就OK了。

MAMP本地运行.png

(在Mac,可以直接利用apache搭建一个的服务器,只要在Users/yourname/Sites这个目录下的静态网站,都可以直接访问,具体搭建可以查询类似“在Mac上搭建本地Apache服务器”)

b)服务器部署

另外一种方式,就是找一个服务器进行部署了,比如亚马逊云、阿里云、腾讯云等。我只是玩过ubuntu和centOS,它们在安装nginx后的路径、配置文件的路径有些不一样,只要找对了位置进行配置就好了。

先把部署文件夹dist丢上服务器,之后再配置nginx的时候指向这个路径就行了。可以通过专门建一个放dist部署文件夹的git项目,这样方便部署更新。

先看下centOS服务器的:

# centOS上面的安装配置大概就这几行
# 遇到权限问题切换admin安装,也可以谷歌查询解决方案

1、安装nodeJS
curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
yum -y install nodejs

2、安装nginx
sudo yum install epel-release
sudo yum install nginx
vi /etc/nginx/nginx.conf  //编辑配置文件
sudo /etc/init.d/nginx start  //启动
sudo /etc/init.d/nginx restart  //重启
sudo /etc/init.d/nginx stop  //停止

3、配置文件内容
# 修改server那一块就好了
server {
    listen 80;
    server_name www.ma.h.fusio.net.cn;
    index index.html;
    root /data/web/apps/ma_front_dev/my-vue-demo-dist/dist;     // 这一行可以测试下不写
    location / {
       root /data/web/apps/ma_front_dev/my-vue-demo-dist/dist;
       try_files $uri $uri/ /index.html =404;
  }
}

下面则是ubuntu服务器的:

# ubuntu上面的安装配置大概就这几行
# 应该比centOS遇到的问题少一点

1、安装nodeJS
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt-get install -y build-essential

2、安装nginx
sudo apt-get update
sudo apt-get install nginx
sudo vi /etc/nginx/sites-available/default   //编辑配置文件
sudo /etc/init.d/nginx start  //启动
sudo /etc/init.d/nginx restart  //重启
sudo /etc/init.d/nginx stop  //停止

3、配置文件内容
(同上)

6.结束

整篇文章的代码放在github上,可以下载。
代码地址为:https://github.com/YuxinChou/vue-demo-source
Demo地址为:https://yuxinchou.github.io/login

题外话:
我学习vue主要是通过几个demo去开始的,都是从github上找,对比、最后选择满足最满足自己需求的去研究,并去优化调整结构、代码。

你们如果是从看这篇文档开始学习的话,那之后就要去github上找找其他demo,来不断优化这一个框架结构,并去完善内部的各种功能,比如图表、导出等。这里的demo还是太简单了。

我学习时参考了这个项目:
代码地址:https://github.com/PanJiaChen/vue-element-admin
我最近看到它的代码还在更新,赞。

我们现在的demo很多功能都没有,一般项目还需要哪些功能,可以之后去研究一下:

  • 侧边栏菜单的展开收缩
  • 增删改查
  • 图表
  • 权限控制
  • 404、500
  • ...

大概就是这样了,如果有什么不对的地方请评论指正,谢谢。
接下来,一方面是想知道如何优化架构,另一方面想去研究一下指令方式写组件。哪位大神带带我!跟不上了,求你们别学了。

到这里,就先结束了。


学习是一条漫漫长路,每天不求一大步,进步一点点就是好的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容