Vue教程--使用官方腳手架構(gòu)建實例(下篇)

本文基于工作項目開發(fā)郁副,做的整理筆記
因工作需要,項目框架由最初的Java/jsp模式晚缩,逐漸轉(zhuǎn)移成node/express模式×牛現(xiàn)在新項目又因為業(yè)務流程中的交互操作漱受,會使頁面dom根據(jù)數(shù)據(jù)data不斷顯示變化,便覺得此時是否是最佳實際,應該嘗試一下vue框架昂羡。因為之前也偷偷的進行了一些vue框架的踩坑工作絮记,已經(jīng)填了一些坑或者有一些解決方案了,這也才敢用上虐先。依然由后臺Java提供API怨愤。本文就是做個筆記,說明如何使用Vue官方腳手架開始構(gòu)建項目蛹批。

前提條件:
你已經(jīng)聽過撰洗、了解過Vue,至少一點點腐芍。

編碼環(huán)境:
系統(tǒng):OS X EI Capitan
版本:10.12.2

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

vue.jpg

目錄
| - 0.傳送門
| - 1.安裝
| - 2.項目初始化
| - 3.項目構(gòu)建
??| - Step1.閱讀結(jié)構(gòu)
??| - Step2. 閱讀代碼(泛讀)
| - 4.項目實操
??| - Step1. 修改eslint配置
??| - Step2. 調(diào)整結(jié)構(gòu)
??| - Step3. 添加登陸頁面
??| - Step4. 模版嵌套
??| - (上下篇分割線)
??| - Step5. 引入mockjs獨立開發(fā)
??| - Step6. 調(diào)用API接口
??| - Step7. 狀態(tài)管理(store倉庫)
??| - Step8. 抽離公共方法
??| - Step9. 剝離組件
??| - Finish. 生辰打包
| - 5.項目部署
??| - a)本地部署
??| - b)服務器部署
| - 6.結(jié)束

Step5. 引入mockjs獨立開發(fā)

在前后端分離的開發(fā)中差导,為了不因為后端接口還沒有弄好,前端開發(fā)處于Waiting狀態(tài)猪勇,我們引入mock.js實現(xiàn)假數(shù)據(jù)接口设褐,從而完成整個頁面邏輯流程。

關于mock.js的知識泣刹,可以瀏覽官網(wǎng)http://mockjs.com/助析。

我們這里準備拿登錄接口的請求做實驗。

先去./src/api文件夾下創(chuàng)建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'
  });
}

發(fā)現(xiàn)代碼里引用了一個公共方法貌笨,暫時還沒有這個文件和方法弱判,我們這就去./src/utils文件夾下創(chuàng)建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,   // 這里我們用了這樣一個變量,根據(jù)環(huán)境選取開發(fā)接口還是生產(chǎn)接口
      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开伏,不會發(fā)生真實的請求,已經(jīng)被攔截了遭商。不過我們還是分別修改一下./config/dev.env.js./config/prod.env.js文件固灵,為了真實的API接口調(diào)用時用到,如下所示:

# ./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文件夾下創(chuàng)建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';   //新增
...

現(xiàn)在,我們執(zhí)行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

現(xiàn)在沒有出現(xiàn)錯誤袜茧,那我們就去修改一下./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;
          }
        });
      }

現(xiàn)在訪問一下http://localhost:8080/login驗證是否能夠登錄成功康栈,驗證可行递递。

同樣的,我們?nèi)ヌ砑右幌碌浅鳇c擊后的請求和處理啥么,修改./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```進行接口假數(shù)據(jù)返回”到這里就結(jié)束啦菠秒。

Step6. 調(diào)用API接口

因為前面我們已經(jīng)用mockjs實現(xiàn)了接口請求,只是返回了假數(shù)據(jù)氯迂。那用真實的接口践叠,只是需要暫停使用mockjs,并將api指向真實的接口進行調(diào)用嚼蚀。

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

# ./src/main.js
...
// 注釋掉這句
// import './mock/index.js';
...

此時你再去訪問http://localhost:8080/login網(wǎng)站轿曙,點擊登錄的話弄捕,就報錯了。

去修改./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網(wǎng)站,點擊登錄進行驗證您单,成功斋荞。再去驗證一下登出,成功虐秦。

注意:有時候你先使用mockjs用假數(shù)據(jù)接口完成開發(fā)平酿,然后再與后臺對接真實接口,這里多數(shù)時參數(shù)悦陋、字段都不一樣蜈彼,所以要注意修改。

這時叨恨,我們發(fā)現(xiàn)一個問題“應該如何記住登錄狀態(tài)”柳刮。這樣就能實現(xiàn)進入登陸頁時自動跳轉(zhuǎn),沒登錄或登錄過期時需要跳入登錄頁重新登錄。下面就來看“狀態(tài)管理”這個問題秉颗。

Step7. 狀態(tài)管理(store倉庫)

狀態(tài)管理痢毒,我們就要用到vuex,詳見http://vuex.vuejs.org/zh-cn/intro.html蚕甥。

文檔里告訴我們哪替,狀態(tài)自管理應用包含以下幾個部分:

  • state,驅(qū)動應用的數(shù)據(jù)源菇怀;
  • view凭舶,以聲明方式將state映射到視圖;
  • actions爱沟,響應在view上的用戶輸入導致的狀態(tài)變化帅霜。

我們在什么情況下應該考慮用到狀態(tài)管理:

  • 多個視圖依賴于同一狀態(tài)。
  • 來自不同視圖的行為需要變更同一狀態(tài)呼伸。
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下面創(chuàng)建一系列文件,代碼分別如下:

vue-demo
| -
| - src
??| -
??| - store
?? ??| - modules
?? ?? ??| - user.js (新增括享,state管理)
?? ??| - getters.js (新增搂根,用于返回頁面使用數(shù)據(jù))
?? ??| - 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: '',  // 用戶的狀態(tài)
    token: localStorage.getItem('token'),    // 用戶登錄后的token值剩愧,其他接口調(diào)用要攜帶,以便檢查登錄是否有效
    // 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

接著我們?nèi)バ薷?code>./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;

            // 使用狀態(tài)管理
            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>

接著我們?nèi)バ薷?code>./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網(wǎng)站成洗,點擊登錄進行驗證五督,成功藏否。 調(diào)用的時候瓶殃,去查看Local Storage留意一下。

同樣的副签,我們?nèi)ジ囊幌碌浅鲆4唬薷?code>./src/views/layout/Navbar.vue,然后測試一下淆储。

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

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

測試之后冠场,發(fā)現(xiàn)登出也可以了。但是我們發(fā)現(xiàn)一個問題本砰,現(xiàn)在如果我們直接訪問頁面http://localhost:8080/dashboard碴裙,我們也可以進入,這是不對的,現(xiàn)在我們來看一下這個問題舔株。

修改./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) {   // 根據(jù)有沒有token去判斷是否登錄
    if (to.path === '/login') {
      next({ path: '/' });
    } else {
      next();
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next('/login')
    }
  }
});
...

再訪問頁面http://localhost:8080/dashboard進行測試檢查惭等,發(fā)現(xiàn)已經(jīng)可以了。

Step8. 抽離公共方法

由于篇幅有限办铡、時間有限辞做,這里能夠給出的demo還是過于簡單,并沒有什么頁面寡具,也沒有重復使用的方法秤茅。但是這里就提一下吧,多次調(diào)用的該抽離的就抽離出去以便可維護童叠,相似的方法集中一個文件也是減少維護成本嫂伞。

編程思想,我覺得還是很重要的拯钻,不單單只是實現(xiàn)頁面帖努、實現(xiàn)功能,如何最好的實現(xiàn)粪般,哪種方式拼余、思路更好,這都是慢慢修煉的亩歹,哈哈匙监。

Step9. 剝離組件

這個demo也是沒有給出復雜頁面,實際項目中某些頁面是可以有幾個功能模塊組成的小作,在這里都沒有體現(xiàn)亭姥。組件思想在vue算是核心,所以寫完一個頁面后顾稀,就可以開始研究頁面的組件化达罗。

我是比較不建議,一個復雜頁面上來就開始先做拆分静秆,除非思路很清晰粮揉、也沒有難點。不過最安全抚笔、快捷的方法是先寫出來扶认,這樣理解已經(jīng)更透徹,然后才去拆分殊橙,我覺得這樣是最快的辐宾。

(看其他demo吧狱从,或者自己重構(gòu)一下項目,我可以開放項目接口出來)

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递沪,網(wǎng)站地址為http://vue.demo.192.168.4.24.xip.io/dashboard。當我刷新頁面的時候综液,就會報“Not Found”錯誤款慨。

現(xiàn)在看一下這樣一個問題是如何產(chǎn)生的?
解答:經(jīng)過研究測試谬莹,這一步需要服務器配置的檩奠。不知道是否還有其他解決方案。

如果打包部署出去附帽,發(fā)現(xiàn)js埠戳,css找不到的問題,一定是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.項目部署

由于最后我們打包生成并部署的實際上是一個靜態(tài)網(wǎng)站,那么我們就來看一下如何在本地部署訪問和如何在服務器上部署訪問喳钟。

a)本地部署

本地的話屁使,就直接使用【MAMP】這個軟件吧,按步驟一步步安裝之后奔则,運行起來基本就可以用了蛮寂,不需要配置什么。
在“Hosts”那邊新增一個Server Name易茬,右邊唯一注意的就是把Name resolution的via Xip.io(LAN only)勾選上酬蹋,這樣你就看到下面輸入框有個訪問地址。在Document root選擇你指向的dist文件夾路徑(打包文生成的那個)疾呻。運行訪問就OK了除嘹。

MAMP本地運行.png

(在Mac写半,可以直接利用apache搭建一個的服務器岸蜗,只要在Users/yourname/Sites這個目錄下的靜態(tài)網(wǎng)站,都可以直接訪問叠蝇,具體搭建可以查詢類似“在Mac上搭建本地Apache服務器”)

b)服務器部署

另外一種方式璃岳,就是找一個服務器進行部署了年缎,比如亞馬遜云、阿里云铃慷、騰訊云等单芜。我只是玩過ubuntu和centOS,它們在安裝nginx后的路徑犁柜、配置文件的路徑有些不一樣洲鸠,只要找對了位置進行配置就好了。

先把部署文件夾dist丟上服務器馋缅,之后再配置nginx的時候指向這個路徑就行了扒腕。可以通過專門建一個放dist部署文件夾的git項目萤悴,這樣方便部署更新瘾腰。

先看下centOS服務器的:

# centOS上面的安裝配置大概就這幾行
# 遇到權(quán)限問題切換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、配置文件內(nèi)容
# 修改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、配置文件內(nèi)容
(同上)

6.結(jié)束

整篇文章的代碼放在github上伟众,可以下載岩灭。
代碼地址為:https://github.com/YuxinChou/vue-demo-source
Demo地址為:https://yuxinchou.github.io/login

題外話:
我學習vue主要是通過幾個demo去開始的,都是從github上找赂鲤,對比噪径、最后選擇滿足最滿足自己需求的去研究,并去優(yōu)化調(diào)整結(jié)構(gòu)数初、代碼找爱。

你們?nèi)绻菑目催@篇文檔開始學習的話,那之后就要去github上找找其他demo泡孩,來不斷優(yōu)化這一個框架結(jié)構(gòu)车摄,并去完善內(nèi)部的各種功能,比如圖表仑鸥、導出等吮播。這里的demo還是太簡單了。

我學習時參考了這個項目:
代碼地址:https://github.com/PanJiaChen/vue-element-admin
我最近看到它的代碼還在更新眼俊,贊意狠。

我們現(xiàn)在的demo很多功能都沒有,一般項目還需要哪些功能疮胖,可以之后去研究一下:

  • 側(cè)邊欄菜單的展開收縮
  • 增刪改查
  • 圖表
  • 權(quán)限控制
  • 404环戈、500
  • ...

大概就是這樣了闷板,如果有什么不對的地方請評論指正,謝謝院塞。
接下來遮晚,一方面是想知道如何優(yōu)化架構(gòu),另一方面想去研究一下指令方式寫組件拦止。哪位大神帶帶我县遣!跟不上了,求你們別學了汹族。

到這里艺玲,就先結(jié)束了。


學習是一條漫漫長路鞠抑,每天不求一大步饭聚,進步一點點就是好的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末搁拙,一起剝皮案震驚了整個濱河市秒梳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箕速,老刑警劉巖酪碘,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盐茎,居然都是意外死亡兴垦,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門字柠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來探越,“玉大人,你說我怎么就攤上這事窑业∏蔗#” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵常柄,是天一觀的道長鲤氢。 經(jīng)常有香客問我,道長西潘,這世上最難降的妖魔是什么卷玉? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮喷市,結(jié)果婚禮上相种,老公的妹妹穿的比我還像新娘。我一直安慰自己东抹,他們只是感情好蚂子,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布沃测。 她就那樣靜靜地躺著缭黔,像睡著了一般食茎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馏谨,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天别渔,我揣著相機與錄音,去河邊找鬼惧互。 笑死哎媚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的喊儡。 我是一名探鬼主播拨与,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼艾猜!你這毒婦竟也來了买喧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤匆赃,失蹤者是張志新(化名)和其女友劉穎淤毛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算柳,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡低淡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞬项。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔗蹋。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖囱淋,靈堂內(nèi)的尸體忽然破棺而出纸颜,到底是詐尸還是另有隱情,我是刑警寧澤绎橘,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布胁孙,位于F島的核電站,受9級特大地震影響称鳞,放射性物質(zhì)發(fā)生泄漏涮较。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一冈止、第九天 我趴在偏房一處隱蔽的房頂上張望狂票。 院中可真熱鬧,春花似錦熙暴、人聲如沸闺属。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掂器。三九已至亚皂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間国瓮,已是汗流浹背灭必。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乃摹,地道東北人禁漓。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像孵睬,于是被迫代替她去往敵國和親播歼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容