一、利用vue-cli3快速搭建vue項目
Vue CLI 是一個基於 Vue.js 進行快速開發的完整系統。有三個組件:
CLI:@vue/cli
全局安裝的 npm 包,提供了終端里的vue命令(如:vue create 、vue serve 、vue ui 等命令)
CLI 服務:@vue/cli-service
是一個開發環境依賴。構建於 webpack 和 webpack-dev-server 之上(提供 如:serve
、build
和 inspect
命令)
CLI 插件:給Vue 項目提供可選功能的 npm 包 (如: Babel/TypeScript 轉譯、ESLint 集成、unit和 e2e測試 等)
1、全局安裝過舊版本的 vue-cli
(1.x 或 2.x)要先卸載它,否則跳過此步:
npm uninstall vue-cli -g
2、安裝vue-cli 3.0
Vue cli 3的包名稱由 vue-cli 改成了 @vue/cli
npm install @vue/cli -g
3. vue-cli搭建腳本文件
以搭建一個項目名稱為vue-test
的Vue前端項目為例:
vue create vue-test
默認設置(直接enter)非常適合快速創建一個新項目的原型,沒有帶任何輔助功能的 npm包
根據提示進行相應的配置(以手動配置為例)(按 “空格鍵”選擇/取消選擇,A鍵全選/取消全選):
3.1. 選擇Manually select features
3.2. 選擇項目需要的一些特性(此處我們選擇需要Babel編譯、使用Vue路由、Vue狀態管理器、CSS預處理器、代碼檢測和格式化、以及單元測試,暫時不考慮端到端測試(E2E Testing))
3.3.Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) y
3.4. 選擇CSS預處理器語言:
SCSS、LESS
3.5. 選擇ESLint的代碼規范,此處使用 Standard代碼規范 (大多數也選擇ESLint + Prettier)
3.6. 選擇何時進行代碼檢測,此處選擇在保存時進行檢測
3.7. 選擇單元測試解決方案,此處選擇 Jest
3.8. 選擇 Babel、PostCSS、ESLint等配置文件存放位置,此處選擇單獨保存在各自的配置文件中
3.9 Save preset as: // 將預設另存為
SaveVue3.0
// 是的話 項目命名假設為:SaveVue3.0
3.10. 配置完成后等待Vue-cli完成初始化
3.11. vue-cli初始化完成后,根據提示,進入到vue-test項目中,並啟動項目
cd vue-test
npm run serve
4. vue.config.js配置
4.1 vue.config.js介紹
vue.config.js是一個可選的配置文件,如果項目的(和package.json同級的)根目錄中存在這個文件,那么它會被@vue/cli自動加載。你也可以使用package.json中的vue字段,但是注意這種寫法需要你嚴格遵照JSON的格式來寫。
這個文件應該導出了一個包含了選項的對象
// vue.config.js module.exports = { // 選項... }
4.2. 配置代理
如果你的前端應用和后端 API 服務器沒有運行在同一個主機上,你需要在開發環境下將 API 請求代理到 API 服務器。這個問題可以通過 vue.config.js 中的 devServer.proxy 選項來配置
devServer
- Type: Object
所有webpack-dev-server
的選項都支持.注意:- 有些值像
host
、port
和https
可能會被命令行參數覆寫 - 有些像
publicPath
和historyApiFallback
不應該被修改,因為它們需要和開發服務器的baseUrl同步以保障正常工作
- 有些值像
devServer.proxy
- Type:
string | object
devServer.proxy
可以是一個指向開發環境API服務器的字符串:
module.exports = { devServer: { proxy: 'http://localhost:4000' } }
這會告訴開發服務器將任何未知請求 (沒有匹配到靜態文件的請求) 代理到http://localhost:4000
。
如果你想要更多的代理控制行為,也可以使用一個 path: options
成對的對象。完整的選項可以查閱 http-proxy-middleware 。
vue-cli2.0
創建的項目的代理配置方式是修改config/index.js
文件中的proxyTable:
vue-cli3.0
的代理配置,直接將proxyTable中配置copy到devServer.proxy中即可:
module.exports = { devServer: { proxy: { '/hrm/api': { //target: 'http://192.168.1.209:10751/', // Dev環境 // target: 'http://192.168.1.238:10751/', // Test環境 // target: 'http://192.168.1.215:10751/', // Rls環境 target: 'http://192.168.1.218:10751/', // 正式環境 changeOrigin: true, autoRewrite: true, cookieDomainRewrite: true, pathRewrite: { '^/hrm/api/': '/' } } } } }
4.3. 配置Webpack其他選項
調整webpack配置最簡單的方式就是在vue.config.js
中的configureWebpack
選項提供一個對象:
module.exports = { // 其他選項... configureWebpack: { plugins: [ new MyAwesomeWebpackPlugin() //...... ] } }
注意:
5. 升級已有項目到vue-cli 3.0版本
之前有考慮過通過將現有項目進行修改,安裝@vue/cli以及相關的包,發現行不通。其實,最簡單的方法,就是使用vue-cli 3.0,創建一個新的項目,然后將原有的項目的源碼拷到新的項目中即可
- 使用vue-cli創建新的項目
- 刪除新項目中
src
下的內容 - 將原有項目
src
中的源碼拷貝到新項目的src
中 - 將原有項目的
index.html
及favicon.ico
拷貝到新項目的public
中 - 將原有的*
static
文件夾也拷貝到新項目的public
中 - 修改package.json、.babelrc等文件,保持和原有項目一致即可
build之后靜態目錄存放位置區別:
vue-cli 2.0:存放在 dist/static下
vue-cli 3.0:存放於 dist/assets 下
使用vue-cli 2.x版本創建的項目,放在static下的文件,build之后,是會拷貝到dist\static項目下的,所以,也必須要將static文件夾移到新項目的public文件夾中; 會有放在static目錄的,大部分是一些用於下載的,或者是大的圖片、庫等不需要編譯的
2.0腳手架默認生成的靜態文件是放在dist/static下,3.0默認升成的靜態文件是放在 dist/assets下的,但是對於項目的升級來說,影響不大
如下圖,原有項目的static中的histudy
文件夾和wx.zip
文件,編譯后是會被拷貝到dist/static
下的
vue-cli 3.0創建的項目,放在public目錄的,編譯時才會被拷貝到dist目錄中,具體的配置方法,可以通過vue.config.js去配置,有興趣的可以去研究研究
如下圖:src中的**.vue等文件,編譯后生成的 img/css/js文件夾,都會被拷貝到dist/assets中,public中的文件/文件夾會被拷貝到dist目錄下。為了不修改原有項目的代碼,直接將原項目的static文件夾拷貝到新項目的public下即可。
6.babel.config.js:
babel.config.js
。和
.babelrc
或
package.json
中的
babel
字段不同,這個配置文件不會使用基於文件位置的方案,而是會一致地運用到項目根目錄以下的所有文件,包括
node_modules
內部的依賴。官方推薦在 Vue CLI 項目中始終使用
babel.config.js
取代其它格式。
7.拉取 2.x 模板 (舊版本):
Vue CLI 3 覆蓋了舊版本的vue
命令,如果需要使用舊版本的 vue init
功能,可以全局安裝一個橋接工具:
npm install -g @vue/cli-init //`vue init` 的運行效果將會跟 `vue-cli@2.x` 相同
vue init webpack my-project
8.在現有的項目中安裝插件(vue add 命令)
官方提示:vue add 的設計意圖是為了安裝和調用 Vue CLI 插件。這不意味着替換掉普通的 npm 包。對於這些普通的 npm 包,你仍然需要選用包管理器
vue add @vue/eslint //如果不帶 @vue 前綴,該命令會換作解析一個 unscoped 的包,你也可以基於一個指定的 scope 使用(eg:vue add @foo/bar)
二、vue引入Element
1.打開cmd,進入到當前剛創建的vue項目目錄
在當前目錄中運行:
npm i element-ui -S
順便安裝一下axios:
npm install axios -S
2.打開創建的項目文件夾
改變項目目錄中的main.js文件;
修改main.js文件:
import Vue from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); Vue.config.productionTip = false;
3.然后在.vue文件里就直接可以用了
例如:在src/components/Hello.vue做一下修改
<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>Essential Links</h2> <el-button>默認按鈕</el-button> <el-button type="primary">主要按鈕</el-button> <el-button type="text">文字按鈕</el-button> </div> </template> <script> export default { name: 'hello', data () { return { msg: 'Welcome to Your Vue.js App' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
運行:npm run serve
安裝使用成功!
三、axios
Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。
1、安裝
npm install axios -S
2.配置axios
在項目中新建api/index.js文件,用以配置axios
import axios from 'axios'; let http = axios.create({ baseURL: 'http://localhost:8080/', withCredentials: true, headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' }, transformRequest: [function (data) { let newData = ''; for (let k in data) { if (data.hasOwnProperty(k) === true) { newData += encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) + '&'; } } return newData; }] }); function apiAxios(method, url, params, response) { http({ method: method, url: url, data: method === 'POST' || method === 'PUT' ? params : null, params: method === 'GET' || method === 'DELETE' ? params : null, }).then(function (res) { response(res); }).catch(function (err) { response(err); }) } export default { get: function (url, params, response) { return apiAxios('GET', url, params, response) }, post: function (url, params, response) { return apiAxios('POST', url, params, response) }, put: function (url, params, response) { return apiAxios('PUT', url, params, response) }, delete: function (url, params, response) { return apiAxios('DELETE', url, params, response) } }
這里的配置了POST、GET、PUT、DELETE方法。並且自動將JSON格式數據轉為URL拼接的方式
同時配置了跨域,不需要的話將withCredentials設置為false即可
並且設置了默認頭部地址為:http://localhost:8080/,這樣調用的時候只需寫訪問方法即可.
注:PUT請求默認會發送兩次請求,第一次預檢請求不含參數,所以后端不能對PUT請求地址做參數限制
3.使用axios
首先在main.js文件:
import axios from "axios";
Vue.prototype.$axios = axios;
然后在需要的地方調用即可
this.$axios.post('user/login.do(地址)', { "參數名": "參數值" }, response => { if (response.status >= 200 && response.status < 300) { console.log(response.data);\\請求成功,response為成功信息參數 } else { console.log(response.message);\\請求失敗,response為失敗信息 } });
當然也可以不用封裝直接調用axios:
//get請求 axios.get('url地址').then( res => { console.log(res); },error =>{ console.log(error); }) //帶參數 axios.get('url地址',params:{參數}).then( res => { console.log(res); },error =>{ console.log(error); }) //post一樣 axios.post('url地址',{參數}).then( res => { console.log(res); },error =>{ console.log(error); })
不封裝,直接axios 發 post 請求,后端接收不到參數的解決方案 :
解決方案一:
【用 URLSearchParams 傳遞參數】
let param = new URLSearchParams() param.append('username', 'admin') param.append('pwd', 'admin') axios({ method: 'post', url: '/api/lockServer/search', data: param })
需要注意的是: URLSearchParams
不支持所有的瀏覽器,但是總體的支持情況還是 OK 的,所以優先推薦這種簡單直接的解決方案
解決方案二:
網上有很多方案說使用
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
或者
{headers:{'Content-Type':'application/x-www-form-urlencoded'}}
我試了一下,其實這樣還是不行的
【還需要額外的操作,(我們要將參數轉換為query參數)】
引入 qs ,這個庫是 axios 里面包含的,不需要再下載了。
import Qs from 'qs' let data = { "username": "admin", "pwd": "admin" } axios({ headers: { 'deviceCode': 'A95ZEF1-47B5-AC90BF3' }, method: 'post', url: '/api/lockServer/search', data: Qs.stringify(data) })
解決方案三:
既然 axios 源碼中有那么一段【很關鍵】的代碼,那么,我們也可以通過修改 transformRequest
來達到我們的目的。
在 axios 的請求配置項中,是有 transformRequest
的配置的:
import Qs from 'qs' axios({ url: '/api/lockServer/search', method: 'post', transformRequest: [function (data) { // 對 data 進行任意轉換處理 return Qs.stringify(data) }], headers: { 'deviceCode': 'A95ZEF1-47B5-AC90BF3' }, data: { username: 'admin', pwd: 'admin' } })
解決方案四:
axios.post('/api/lockServer/search',"userName='admin'&pwd='admin'");
四、vuex(狀態管理):
import Vue from 'vue'; import Vuex from 'vuex'; //引入 vuex import store from './store' //注冊store Vue.use(Vuex); //使用 vuex export default new Vuex.Store({ state: { // 初始化狀態 count: 0 }, mutations: { // 處理狀態 increment(state, payload) { state.count += payload.step || 1; } }, actions: { // 提交改變后的狀態 increment(context, param) { context.state.count += param.step; context.commit('increment', context.state.count)//提交改變后的state.count值 }, incrementStep({state, commit, rootState}) { if (rootState.count < 100) { store.dispatch('increment', {//調用increment()方法 step: 10 }) } } } })
使用時,eg:main.js:
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' //引入狀態管理 store Vue.config.productionTip = false new Vue({ router, store,//注冊store(這可以把 store 的實例注入所有的子組件) render: h => h(App) }).$mount('#app')
components/HelloWorld.vue:
<template> <div class="home"> <HelloWorld :msg="count"/> </div> </template> <script> import HelloWorld from '@/components/HelloWorld.vue' import {mapActions, mapState} from 'vuex' //注冊 action 和 state export default { name: 'home', computed: { //在這里映射 store.state.count,使用方法和 computed 里的其他屬性一樣 ...mapState([ 'count' ]), }, created() { this.incrementStep(); }, methods: { //在這里引入 action 里的方法,使用方法和 methods 里的其他方法一樣 ...mapActions([ 'incrementStep' ]), }, components: { HelloWorld } } </script>