vue-cli使用指南


 

本文中使用的vue版本是 2.x
 

vue全家桶(技术栈)

  • vue-cli:脚手架,用于快速搭建vue项目
  • vue-router:路由,单页应用的核心插件
  • vuex:状态管理,可管理全局数据。小项目用vuex有点繁琐,建议大项目用vuex,小项目用bus总线
  • axios:对ajax的封装

 

使用vue-cli搭建Vue项目

1、准备工作。如果之前已安装,可以跳过这一步

  • 安装npm
  • 安装webpack、vue-cli
#最新稳定版
npm install webpack -g
npm install @vue/cli -g

 

2、使用vue-cli搭建vue项目

#初始化项目
vue create 项目名

#选择自定义,空格键选中、取消选中

#选择babel、router、vuex(根据需求)

#使用history模式的路由

#In dedicated config files,babel等配置写在单独的文件中

 

3、项目根目录下新建 vue.config.js ,写自定义的配置。示例

module.exports={
    configureWebpack:{
        devServer:{
            port:9000,  //使用的端口号,默认8080
            open:true,  //自动在浏览器中打开页面,默认false关闭
        }
    }
}

项目启动时会自动加载根目录下的vue.config.js,vue.config.js中配置项的写法可参考
https://cli.vuejs.org/zh/config/#vue-config-js

 

单页的编写

1、替tab栏图标 public/favicon.ico,根据需要修改public/index.html

2、在App.vue中写页面的公共部分

3、在views中写分页,Xxx.vue

4、要在多个分页中使用的部分,写成组件(Xxx.vue)放到components下,在分页中引用

5、静态资源放在assets目录下,在assets新建css、js、img文件夹来存放
 

Xxx.vue的基本骨架:<template>、<script>、<style>

<template>
  <div>
    <HelloWorld msg="hello"/>  <!-- 使用组件,父子组件之间可以通过属性传递数据 -->
  </div>
</template>


<script>
// 引入components下的组件(相当于声明组件),@是/src的别名
import HelloWorld from '@/components/HelloWorld.vue'

//不需要new Vue,然后在里面写data、methods,直接在export default中写即可
export default {
  name: 'Home',  //当前组件的名称
  components: {  //注册当前组件中要使用的其它组件
    HelloWorld  //有多个时逗号分隔
  },
  data(){
  },
  methods:{
  },
}
</script>


<!-- <style scoped> 如果加了scoped属性,则定义的样式只在当前.vue中有效 -->
<style>

</style>

vue代码提示常用插件:Vue 2 Snippets(推荐)、VueHelper
 

4、在router/index.js中配置路由(分页)

//导入首页
import Login from '../views/Login.vue'

//配置分页的路由
const routes = [
  {
    path: '/',   //配置首页
    name: 'Login',
    component: Login   //下面懒加载的组件都是写成字符串格式,首页是直接写的组件,所以开头用了import导入
  },
  {
    path: '/register',
    name: 'Register',
    component: () => import('../views/Register.vue')  //除了首页,分页都使用懒加载,防止加载首页时卡顿
  }
]

一个组件可以同时配置多个路由,即对应多个路径,copy后改下path即可,在组件中用 this.$route.path 可以获取当前使用的哪个 path 。

 

axios的使用

安装axios

npm install axios --save

 

在main.js中导入axios

import axios from 'axios'

// 挂载到Vue原型上,属性名常用$axios、$http
Vue.prototype.$http = axios

//axios配置
axios.defaults.baseURL = 'http://localhost:8080/msg-server'  //请求url公共前缀
axios.defaults.timeout = 10000   //超时时间 ms,默认0 不限制
//withCredentials = false   //发起跨域请求时是否发送cookie,默认false

 

说明

//如果前后端部署时使用相同的域名,比如使用的是模板引擎,可以使用 window.top.location.origin 直接获取当前js文件所在域名
axios.defaults.baseURL = window.top.location.origin + '/msg-server'

//以上是配置全局axios,也可以配置使用axios的某个实例
const axiosInstance = axios.create({
  baseURL: 'http://localhost:8080/msg-server',
  timeout: 10000
});
Vue.prototype.$http = axiosInstance

更多配置项可参考:https://github.com/axios/axios#request-config
 

axios使用示例

//get方式,请求参数放在config的params参数中,可以写成map形式,也可以直接 this.reqVo 之类传对象过去
//后端用基础类型直接接收,不用标注什么注解
this.$http.get("/task/send", {params: {username: 'chy', age: 20}})
//this.$http.get("/task/send", {params: this.reqVo})
    .then(resp => {
      console.log(resp.data);
    });
    .catch(err => {
      console.log(err);
    });


//post方式,第二个参数是data,即要传递的数据,可以写成map形式,也可以直接 this.reqVo 之类传对象过去
//后端需要使用实体类接收,并在参数前标注 @RequestBody
this.$http.post("/task/send", { username: "chy", age: 20 })  
//this.$http.post("/task/send", this.reqVo)  
  .then(resp => {
    console.log(resp.data);
  })
  .catch(error => {
    console.log(error);
  });

 

使用axios上传文件并携带其它参数

// 配置请求头,允许上传文件。默认的Content-Type是 'application/json'
let config = {headers:{'Content-Type':'multipart/form-data'}}

let param=new FormData();
//文件
param.append("file",this.uploadFile);
//要携带的其它参数
param.append("username",this.username);
//FormData不能直接添加一个数组,只能逐个添加数组中的元素,append(key,value),key相同时会把value放在一个数组中
this.friendList.forEach(ele => {
	param.append("friendList",ele);
});

// 向后端发起请求
this.$http
    .post("/task/add", param, config)  //参数、请求头配置
    .then(resp => {
        console.log(resp.data);
    })
    .catch(error => {
        console.log(error);
    });

参数是(url,param,config),url必需,param,config可选;后端接收参数时不必用 @RequestBody、@RequestParam 标注形参。

 

vuex的使用

vuex是一个状态仓库,用于存储、管理全局数据,常用于组件、页面之间的数据传递、共享

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {  //在state中写要存储的变量
    token:'',
    cart:[]
  },
  mutations: {  //在mutations中写操作变量(数据)的方法。state会自动传入
    setToken(state,token){  
      state.token=token
    }
  },
  actions: {
  },
  modules: {
  }
})

 
main.js中自动引入了vuex的store,可以在项目中直接用store

import store from './store'

 
使用示例

//存储到vuex中,第一个参数指定方法名,后续的参数指定实参
this.$store.commit('setToken',resp.data.token); 

//取值
this.$store.state.xxx

如果要清空vuex中的某个变量,可以this.$store.commit()传入空值,比如对象赋为空对象{ },数组赋为空数组[ ],也可以在store/index.js的mutations中写一个清空变量的方法,暴露给外部调用。

 

vuex中数据的保留时间

通过vue路由进行跳转时,vuex中的数据不会丢失,但刷新单页中的某个页面时 vuex中的数据会全部丢失,通常要把vuex中的数据保存在本地存储 localStorage 或 cookie 中。

userId、token、deviceId 之类体积小、服务端常用的数据,可以保存在cookie中 方便传给服务端;购物车的商品、搜索历史记录之类体积大、服务端不常用的数据,没必要保存在cookie中 每次都传给服务端,建议保存在 localStorage 中。

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

let store = new Vuex.Store({
  state: { 
    token:'',
    cart: JSON.parse(localStorage.getItem('cart')) || [], //先从本地存储中获取,如果没有才置为空数组
  },
  mutations: {
    setToken(state,token){  
      state.token=token
    }
  },
  actions: {
  },
  modules: {
  }
})

//监听mutations中的方法调用,每次调用mutations中的方法时,都会将指定数据更新、保存到本地存储中
store.subscribe((mutations,state)=>{
  //可以缺省window
  window.localStorage.setItem('cart',JSON.stringify(state.cart))
})

//将store模块暴露出去
export default store

 

axios的全局拦截

用axios请求数据时,往往需要拦截做一些额外处理,比如

  • 拦截请求,在请求头中添加 token
  • 拦截响应,如果响应码表示 token 已过期、不合法,则跳转到登录页;如果状态码表示服务端错误、超时,则提示xxx

src下新建 axios-interceptors.js

import axios from 'axios'
import store from './store'
import router from './router'

//设置axios拦截器
export default function setAxiosInterceptors(){
    //拦截请求,在请求头中添加 token
    axios.interceptors.request.use(
        config => {
            if(store.state.token){
            	//尽量用预定义的请求头字段Authorization,不要用自定义的字段 config.headers.token,否则控制台会有相关报错
            	//js对象用 config.headers.Authorization 或 config.headers['Authorization'] 访问都行
            	//前端传递 Authorization 时往往会拼接 Bearer 之类的前缀指定验证方式,服务端从Authorization获取token时需要先剔除对应的前缀
            	config.headers.Authorization = 'Bearer ' + store.state.token
            }
            return config
        }
    )
    
    //拦截响应
    axios.interceptors.response.use(
        response => {
            if(response.status === 200){
                const data = response.data
                //服务端返回的响应码表示token过期、不合法时
                if(data.code === '1001' || data.code === '1002'){
                    //清空vuex、localstorage保存的token
                    store.commit('settoken', '')
                    localStorage.removeItem('token')
                    //跳转到login页面。使用replace(),不插入到历史记录中
                    router.replace({path:'/login'})
                }
                return data
            }
            return response
        }
    )
}

上面直接配置的 import axios from 'axios'导入的axios,是全局配置axios拦截器,也可以把axios换成某个axios实例 axiosInstance,针对axios某个实例进行配置。

更多配置可参考:https://github.com/axios/axios#interceptors
 

在main.js中设置axios的拦截

import setAxiosInterceptors from './axios-interceptors'

setAxiosInterceptors()

 

axios的跨域问题

参考:https://blog.csdn.net/chy_18883701161/article/details/108325424

 

全局常量

//在 main.js 中挂载到Vue原型上
Vue.prototype.XXX='xxx';


//在 .vue 文件的js脚本中可通过 Vue.prototype 来引用
let xxx = Vue.prototype.XXX;

//如果是在Vue实例中,或者可解析的html元素中,可直接通过 this 引用
let xxx = this.XXX;
<el-upload :action="this.XXX">{{this.XXX}}</el-upload>

 

使用Mock模拟后端接口返回数据

mock常用于前后端分离的项目,后端还没写好暴露给前端的接口时,前端可以用mock模拟后台接口返回数据进行调试,使前端可以独立开发,不必停下开发进度等后端。

 

嵌套路由

嵌套路由用于在一个页面中再嵌套页面

eg. /phone/apple,/phone/huawei,/phone/xiaomi

<!-- 在一级路由中给二级路由预留位置 -->
<router-view />
{  //一级路由
    path: '/phone',
    name: 'Phone',
    component: Phone,
    children:[  //二级路由(嵌套路由),path开头不加/
		{
		    path: 'apple',
		    name: 'Apple',
		    component: () => import('../views/Apple.vue')
		 },
		 {
		    path: 'huawei',
		    name: 'Huawei',
		    component: () => import('../views/Huawei.vue')
		 }
	]
  },

 

路由守卫

路由守卫可以在单页的路由跳转(包括刷新当前页面)时做一些前处理。

eg. 跳转到某些页面时,先校验用户是否已登录、是否有指定权限,满足条件才跳转

router.js

{  //一级路由
    path: '/msg',
    name: 'Index',
    component: Index,
    meta:{
    	requireAuth: true,  //自定义的标志,为true时需要登录才能访问该页面
	}
}

 
main.js

//路由守卫,beforeEach()是路由前置钩子函数。next指定要执行的方法
router.beforeEach((to,from,next)=>{
	//刷新页面时vuex的数据会丢失,需要重新设置
  store.commit('settoken',localStorage.getItem('token'))
  
  if(to.meta.requireAuth){
    if(store.state.token){
      next()  //跳转到目标页面,()中可以传递参数
    }else{
      next({  //跳转到登录页面
        path:'/login',
        query:{redirect:to.fullPath} 
      })
    }
  }else{
    next()
  }
})

执行的都是next(),不设置参数的next()默认是跳转到目标页面;设置了参数的可以跳转到指定页面

 

引入jq(不推荐)

vue本来就可以视图-内存数据双向绑定,修改内存数据时自动同步更新视图,没有必要再用 jq 更新视图,vue也提供了异步请求,使用vue的同时引入jq有点鸡肋,了解即可。

1、安装jq的依赖

npm install jquery --save

 

2、在vue.config.js中添加配置
在这里插入图片描述

const webpack = require('webpack')

module.exports = {
    configureWebpack:{
        devServer:{
            port:9000,
            open:true,
        }
    },
    //声明jq的$、jQuery
    chainWebpack: config => {
        config.plugin('provide').use(webpack.ProvidePlugin, [{
            $: 'jquery',
            jQuery: 'jquery'
        }])
    },
    
}

 

3、在main.js中引入jq

import $ from 'jquery'

 

4、使用示例

<script>
$(function () {

	//jq代码
    $('#btn').click(function () {
        alert('ok');
    });

});

export default {

};
</script>

注意:需要把jq代码放在$(function () { }中才有效,因为vue使用的是虚拟dom,jq代码要在dom加载完成后才能执行

 

运行、调试

cd到项目根目录下

#如果是刚从 svn|git 拉取的项目,先安装所需依赖
#npm install

#运行
npm run serve

chrome安装插件 Vue.js devtools用于调试vue-cli项目,此插件只能调试vue-cli项目,如果只是在模板引擎之类的页面中使用Vue,则无法使用此插件进行调试。

 

打包

在vue.config.js中配置publicPath、assetsDir

const webpack = require("webpack");

module.exports = {
    publicPath: "/mall-admin/",   //部署到哪个应用中,即项目url的根目录
    assetsDir: "static",  //静态资源打包到哪个目录下
    configureWebpack: {
        devServer: {
            port: 9000,
            open: true,
        },
    },
    chainWebpack: (config) => {
        config.plugin("provide").use(webpack.ProvidePlugin, [
            {
                $: "jquery",
                jQuery: "jquery",
            },
        ]);
    },
};
  • publicPath:要部署到域名下的哪个目录(应用)中,默认/ 直接部署到域名下。
  • outputDir:输出目录,默认dist
  • assetsDir:静态资源的打包输出目录,输出到outputDir的哪个目录下,默认’’ 直接输出到outputDir下

配置参考:https://cli.vuejs.org/config
 

#构建生产版,会输出到dist文件夹
npm run build

 

部署

参考:https://cli.vuejs.org/zh/guide/deployment.html

 

常见问题

堆栈溢出

Uncaught RangeError: Maximum call stack size exceeded

常见原因:UI框架的标签和我们自定义的vue组件重名了,修改我们自定义的组件名称即可

 

路由重复

history路由模式,顾名思义,会记录请求url历史,如果请求的url就是上次路由的url,则不会再次发起请求,除非目标 url 改变或传递给目标 url 的参数发生改变。

使用history路由模式时,重复点击路由到同一页面,虽然页面显示正常,但控制台会报错

vue-router.esm.js?8c4f:2062 Uncaught (in promise) Error: Avoided redundant navigation to current location: “/xxx”.

解决方式:在router/index.js中添加

// 解决history模式,路由重复的问题
const originalPush = VueRouter.prototype.push

VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

可以加在router/index.js中,也可以加在其它文件中,只要该文件导入了VueRouter即可

import VueRouter from 'vue-router'

 

路由传参,参数不刷新

这是组件复用时经常发生的问题,在组件创建后从后端加载数据,后续再次使用这个组件,只要参数不变就不会重新创建,显示的还是之前的数据。
 

常见的解决方案有2个

  • 使用动态url,比如拼接一个时间戳
  • 把组件初始化时加载数据的代码抽出来,作为方法放到 methods 中,监听 $route 对象中某个特征属性的变化,常见的比如path,发生变化时调用加载数据的方法重新加载数据。即原先的初始化操作不放在created()之类的方法中,改为放在数据监听中。

详细信息可参考:https://blog.csdn.net/chy_18883701161/article/details/106723292

 

手动调用methods中的方法时,提示方法未定义

需要通过this来调用methods中的方法

mounted() {
   // 加this
   this.getTaskList();
},
methods: {
   getTaskList() {
      
   },
   toAdd() {
       // 加this
   	   this.getTaskList();
   },
}

 

报错 1 error, 13 warnings…fixable with the --fix option 确定代码本身没有问题

✖ 14 problems (1 error, 13 warnings)
0 errors and 13 warnings potentially fixable with the --fix option.

 
解决方案:package.json

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    #原来是 vue-cli-service lint,把lint换为 eslint --fix --ext .js,.vue src
    "lint": "vue-cli-service eslint --fix --ext .js,.vue src"
  },

 

配置生效问题

修改src/main.js、vue.config.js后,需要重启项目才会生效

 

vue-cli 3.x及之后的项目中没有webpack的配置文件

从vue-cli 3.x开始,用vue.config.js代替了webpack的配置文件,可以把webpack的配置写在vue.config.js中。

配置写法参考:https://cli.vuejs.org/zh/guide/webpack.html

 

axios传到后端的参数都是null、或无法传递数组

参考:https://blog.csdn.net/chy_18883701161/article/details/106732406

 

版本控制与依赖

一般不把 node_modules 上传到svn或者git仓库中,拉取项目后需要先安装项目依赖

#安装项目依赖
npm install

 

过渡(滑动)效果

页面切换时,一般不直接切换,写一个过渡效果(滑动),使用户体验更好

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值