本文基于工作項目開發,做的整理筆記
因工作需要,項目框架由最初的Java/jsp模式,逐漸轉移成node/express模式。現在新項目又因為業務流程中的交互操作,會使頁面dom根據數據data不斷顯示變化,便覺得此時是否是最佳實際,應該嘗試一下vue框架。因為之前也偷偷的進行了一些vue框架的踩坑工作,已經填了一些坑或者有一些解決方案了,這也才敢用上。依然由后臺Java提供API。本文就是做個筆記,說明如何使用Vue官方腳手架開始構建項目。
前提條件:
你已經聽過、了解過Vue,至少一點點。
編碼環境:
系統:OS X EI Capitan
版本:10.12.2
共2篇:
上篇:http://www.lxweimin.com/p/ee2464501c65
下篇:http://www.lxweimin.com/p/9baa03eb31fc(當前)
目錄
| - 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_API
的BASE_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.js
和login.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
模塊,如下:
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”錯誤。
現在看一下這樣一個問題是如何產生的?
解答:經過研究測試,這一步需要服務器配置的。不知道是否還有其他解決方案。
如果打包部署出去,發現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.項目部署
由于最后我們打包生成并部署的實際上是一個靜態網站,那么我們就來看一下如何在本地部署訪問和如何在服務器上部署訪問。
a)本地部署
本地的話,就直接使用【MAMP】這個軟件吧,按步驟一步步安裝之后,運行起來基本就可以用了,不需要配置什么。
在“Hosts”那邊新增一個Server Name,右邊唯一注意的就是把Name resolution的via Xip.io(LAN only)勾選上,這樣你就看到下面輸入框有個訪問地址。在Document root選擇你指向的dist文件夾路徑(打包文生成的那個)。運行訪問就OK了。
(在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
- ...
大概就是這樣了,如果有什么不對的地方請評論指正,謝謝。
接下來,一方面是想知道如何優化架構,另一方面想去研究一下指令方式寫組件。哪位大神帶帶我!跟不上了,求你們別學了。
到這里,就先結束了。
學習是一條漫漫長路,每天不求一大步,進步一點點就是好的。