一、利用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>