不知道怎么回事线上地址的图片全部消失了,但是我发现稀土掘金的似乎都还在,完整版移步稀土掘金:https://juejin.cn/post/7218392277919334456
克隆一份新的vue-admin-template模板项目
# 新建hmhr文件夹
新建hmhr文件夹
# 克隆一份新的项目模板 (后面空格.代表克隆到路径所在文件夹下)
git clone https://gitee.com/panjiachen/vue-admin-template.git .
# 安装所有依赖
npm install
# 启动开发调试模式 查看package.json文件的scripts可知晓启动命令
npm run dev
克隆时, 为何后面有时候要加个点
答案把它的项目里代码都删除掉, 留下一个框
从上到下, 挨个文件过筛子
自带的作者的.git文件夹删除掉, 一会儿我们自己初始化一个自己的使用(删除)
mock - 文件夹删除 (用于模拟数据, 无后台接口使用)
配套 - vue.config.js - 对应使用的代码, 删除
// before: require('./mock/mock-server.js')
main.js -> 清除mock.js相关代码
import Vue from 'vue'
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/en' // lang i18n
import '@/styles/index.scss' // global css
import App from './App'
import store from './store'
import router from './router'
import '@/icons' // icon
import '@/permission' // permission control
// if (process.env.NODE_ENV === 'production') {
// const { mockXHR } = require('../mock')
// mockXHR()
// }
Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
api文件夹
删除table.js, 留下user.js, 但是清空user.js里一切
router/index.js - 路由修改
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import Layout from '@/layout'
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: 'Dashboard', icon: 'dashboard' }
}]
},
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () => new Router({
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
export default router
views/删除不需要的页面, 只需要保存路由需要的页面即可
utils/request.js中, 肃清模板
import axios from 'axios'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
service.interceptors.request.use(
config => {
return config
},
error => {
return Promise.reject(error)
}
)
service.interceptors.response.use(
response => {
return response
},
error => {
return Promise.reject(error)
}
)
export default service
permission.js -> 路由权限管理, 肃清留框
import router from './router'
// const whiteList = ['/login'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
next()
})
router.afterEach(() => {
})
为何要肃清模板?
答案以后进公司, 公司写完的项目, 我能肃清吗?
答案本地初始化git环境
码云建立远程仓库, 推送上去
注意
: 之前的项目是直接从 vue-admin-template **克隆
**而来
里面有原来的提交记录,为了避免冲突, 先将原来的**.git
**文件夹删除掉,自己初始化个空的自己的
# 初始化项目
git init
# 将修改添加到暂存
git add .
# 将暂存提到本地仓库
git commit -m '人资项目初始化_肃清模板后'
远程仓库建立只需要在网站上直接操作即可
创建项目完成后, 找到git仓库地址.git结尾的
推送到远程仓库一般先将**远程仓库地址
**用本地仓库别名代替
# 添加远程仓库地址
git remote add origin 远程仓库地址
当我们不清楚自己的仓库对应的origin地址时, 我们可以通过命令查看当前的远程仓库地址
# 查看本地仓库的远程仓库地址映射
git remote -v
推送master分支到远程仓库
如果想推送其他分支, 本地先确保有, 然后把master换成对应分支名
# 将master分支推送到origin所代表的远程仓库地址
git push -u origin master
-u作用是建立一条通道, 以后直接git push即可(但是要在master分支下)
本地准备git仓库(得到.git文件夹), .git文件夹作用是什么?
答案为什么要把git记录提交到远程服务器上?
答案第一次从git仓库拿到代码, 命令是什么?
答案git clone可以拉取所有分支吗?
答案git pull的作用? 代码在哪里合并的?
答案如何查看git提交记录
答案修改登录页面静态布局。参考图:
项目中已经有了login.vue文件了,有现成的结构和样式。
在原来的基础上进行修改, 找标签列名覆盖样式
课程资料的素材/common
中,要将**common
**文件夹拷到 **assets
**目录里
课程资料的素材/styles
中,2个scss文件, 复制到 **styles
**目录里
variables.scss
**common.scss
**在**index.scss
**中引入该样式
// 引入common.scss样式表 (公共样式)
@import './common.scss';
main.js已经默认引入了index.scss入口文件带着所有样式变量
views\login\index.vue
注意1: 是在el-form内
views\login\index.vue
注意: 在样式表使用@时, 要在前面加~告诉webpack从根路径识别而不是相对路径
.login-container {
background-image: url('~@/assets/common/login.jpg'); // 设置背景图片
background-position: center; // 将图片位置设置为充满整个屏幕
}
views\login\index.vue
修改样式变量的值在style标签内
$light_gray: #68b0fe; // 将输入框颜色改成蓝色
$cursor: #68b0fe; // 将输入框光标改成蓝色
/* reset element-ui css */
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
// background: rgba(0, 0, 0, 0.1);
+ background: rgba(255, 255, 255, 0.7);
border-radius: 5px;
color: #454545;
}
views\login\index.vue
在el-button 上补充一个 login_btn的class,并设置样式如下
.login_btn{
background: #407ffe;
height: 64px;
line-height: 32px;
font-size: 24px;
}
手机号: 13800000002
密码: 123456
当表单元素的输入验证错误时,它会在相应的表单元素下边出现一个文字说明。
/* reset element-ui css */
.el-form-item__error {
font-size: 14px
}
其他的.scss文件引入到index.scss, 为何这样干?
答案如何在现有项目, 修改样式?
答案路径中的@代表的是什么?
答案在样式中使用@, 前面加~, webpack才会识别绝对地址
虽然样式好了, 但是标签内容和文字内容, 不太符合需求
从头过一遍, 明确需求目标, 然后进行文字和变量的替换
src/views/login/index.vue
登录
手机号: 13800000002
密码: 123456
在utils/validate.js中
/**
* 验证手机号
* @param {string} str 账号-手机号
* @returns {Boolean} 通过校验为true, 否则为false
*/
export function validMobile(str) {
return /^1[3-9]\d{9}$/.test(str)
}
做需求, 和改页面, 4步套路是?
答案基础模板已有校验代码,我们来修正和完善
el-form表单校验标签结构和属性配置
注意: 规则对象key名字(rules属性)一定要和model表单对象的key同名
上一步, 已经把对应的key都对应好了, 规则对象和表单对象绑定的属性已经一致
密码验证不需要自定义校验过程, 可以直接用内置min和max
长度在6-16位
password: [
{ required: true, trigger: 'blur', min: 6, max: 16, message: '密码长度在6-16位' }
]
删除validatePassword方法即可
最终落地代码
import { validMobile } from '@/utils/validate'
export default {
name: 'Login',
data() {
const validateMobile = (rule, value, callback) => {
if (!validMobile(value)) {
callback(new Error('请输入正确的手机号'))
} else {
callback()
}
}
return {
loginForm: {
mobile: '13800000002',
password: '123456'
},
loginRules: {
mobile: [
{ required: true, trigger: 'blur', validator: validateMobile }
],
password: [
{ required: true, trigger: 'blur', min: 6, max: 16, message: '密码长度在6-16位' }
]
},
loading: false,
passwordType: 'password',
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true
this.loading = false
} else {
return false
}
})
}
}
}
完整的表单校验需要三个组件完成配合 分别是
答案简单的校验和复杂的校验分别使用什么方式?
答案校验的触发方式, 有哪2种?
答案请求线上接口,实现登录
在utils/request.js中发现使用的是.env.development
的环境变量
VUE_APP_BASE_API = 'http://ihrm.itheima.net/api'
baseURL基地址就会提取上面地址使用
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 设置axios请求的基础的基础地址
timeout: 20000 // 定义20秒超时
})
src/api/user.js 中修改原来方法
import request from '@/utils/request'
/**
* 用户 - 登录
* @param {*} param0
* @returns
*/
export function loginAPI(data) {
return request({
url: '/sys/login',
method: 'post',
data
})
}
src/api/新建index.js
export * from './user' // 从user.js按需导入所有, 然后按需导出所有
在views/login/index.vue中, 引入login接口, 进行调用
import { loginAPI } from '@/api'
export default {
methods: {
// 登录
handleLogin() {
this.$refs.loginForm.validate(async(valid) => { // 登录校验
if (valid) {
this.loading = true
const res = await loginAPI(this.loginForm)
console.log(res)
this.loading = false
} else {
return false // 未通过
}
})
}
}
}
我的天啊, 但是发现, 跨域了, 因为后台没有开启cors
.env配置文件有何作用?
答案我们这次基地址如何配置?
答案网络请求方法, 如何封装?
答案接口调用的完整逻辑和文件划分?
答案掌握跨域的原因;
复习常用的解决方案;
在A地址(发起请求的页面地址)向B地址(要请求的目标页面地址)发起请求时,
如果A地址和B地址在: 协议 、域名、 端口 不全相同,则说明请求是跨域的
请求是跨域的,并不一定会报错。普通的图片请求,css文件请求是不会报错的
跨域请求出现错误的条件: 浏览器同源策略 && 请求是ajax类型
浏览器同源策略,同源策略是一个重要的安全策略,它能帮助阻隔恶意文档,减少可能被攻击的媒介。
跨域是谁对谁做出的限制?
答案什么是跨域?
答案这个项目哪个地址和哪个地址, 跨域访问了?
答案解决跨域有几种方法?
答案如何做代理转发
vue脚手架项目内置了代理转发功能
在vue.config.js
配置文件中,有一项是devServer,它就是我们下边要操作的主角。
注意1: 一定要把.env.development里设置为/api, 让它触发webpack开发服务器作为的代理服务器使用
# 开发环境的基础地址
VUE_APP_BASE_API = '/api'
注意2: 一定要把mock服务注释掉, 用线上地址
在vue.config.js中
module.exports = {
devServer: {// 里面新增
// before: require('./mock/mock-server.js'), // 注释线上地址
// 代理配置
proxy: {
// 这里的 api 表示如果我们的请求地址以 /api 开头的时候,就出触发代理机制
'/api': {
target: 'http://ihrm.itheima.net', // 需要代理的地址
changeOrigin: true // 是否跨域,需要设置此值为 true 才可以让本地服务代理我们发出请求
}
// 这里没有pathRewrite, 因为后端接口就是ihrm.itheima.net/api这种格式,所以不需要重写
}
}
}
修改webpack入口以外的代码, 需要重新启动webpack服务器生效
登录这个原网站查看员工: http://ihrm.itheima.net/hrsaas/login, 密码默认都是123456
后端开启cors原理?
答案如果后端不开启, 我们如何才能跨域访问?
答案如果以后打包上线了, 我们代理转发还有用吗?
答案以前用try+catch捕获错误, 我们试试
handleLogin() { // 登录
this.$refs.loginForm.validate(async(valid) => { // 登录校验
if (valid) {
this.loading = true
try {
const res = await loginAPI(this.loginForm)
console.log(res)
} catch (err) {
console.error(err)
}
this.loading = false
} else {
return false // 未通过
}
// 知识点1:
// this.loginForm是上面定义和v-model绑定的对象以及对象key属性
// 这里直接把相同的参数名对象直接发给后台 (建议: 前端定义变量可以直接跟接口文档要求的参数名一致)
// 知识点2: await只能拿到成功的结果, 如果Promise对象内用reject()返回, 这里就中断不往下执行
// 知识点3: 当Promise对象这里, 没有自己捕获到错误(try+catch, 或者.catch())然后处理的话, 浏览器就会把"抛出的这个错误"打印到控制台里, "终止代码继续往下"
// 知识点4: 捕获Promise的错误 try+catch
// 知识点5: 打印相关
// 小点: .log(普通打印) .error(红色打印) .dir(打印对象详细信息-可以展开看里面key+value)
})
}
发现, 还是不进catch里, 原因是, 我们密码错误, http请求过程是ok的, 返回状态为200, 但是axios内部判定http状态码为4xx, 5xx才会抛出错误, 让catch捕获
分析原因:
首先 axios 内部的报错机制:
但当用户用户名和密码输入错误时,本次请求的状态码是正常的(虽然 success 字段是false),也没有网络错误,所以axios并不会报错。如下图示:
解决思路:
在响应拦截器中,根据本次请求返回的数据中的 success 字段值,来决定是否主动抛出错误。
落地代码
service.interceptors.response.use(
response => {
const { success, message } = response.data
if (success) {
return response
} else {
return Promise.reject(new Error(message)) // 返回Promise错误的对象, 等同reject() -> 自己根据success字段判断逻辑错误(账号密码错误)
}
},
error => {
return Promise.reject(error)
}
)
再次查看try+catch能否进入
观察api的返回结果,我们发现axios在处理接口返回值时,默认会自动给包裹一个data字段,这导致我们每次在业务模块获取数据都需要写res.data.data.xxxx
,这样太麻烦了。
落地代码
在src/utils/request.js
中,补充请求拦截器如下:
service.interceptors.response.use(
response => {
const { success, message } = response.data
if (success) {
+ return response.data
} else {
return Promise.reject(new Error(message)) // 返回Promise错误的对象, 等同reject() -> 自己根据success字段判断逻辑错误(账号密码错误)
}
},
error => {
return Promise.reject(error)
}
)
向外返回后台返回的数据
handleLogin() { // 登录
this.$refs.loginForm.validate(async(valid) => { // 登录校验
if (valid) {
this.loading = true
try {
const res = await loginAPI(this.loginForm)
console.log(res)
} catch (err) {
console.error(err)
}
this.loading = false
} else {
return false // 未通过
}
})
}
}
查询element-ui文档, 找到了message消息提示
handleLogin() {
this.$refs.loginForm.validate(async(valid) => { // 登录校验
if (valid) {
this.loading = true
try {
const res = await loginAPI(this.loginForm)
this.$message.success(res.message)
console.log(res)
} catch (err) {
this.$message.error(err.message)
console.error(err)
}
this.loading = false
} else {
return false // 未通过
}
})
}
如果每次发起请求后,都进行错误处理,会让代码也非常冗余
我们既然在响应拦截器中进行获取到了错误的状态码,这时候就可以进行错误的统一处理
import { Message } from 'element-ui'
service.interceptors.response.use(
response => {
const { success, message } = response.data
if (success) {
return response.data
} else {
+ Message.error(message) // http状态码2xx, 但是逻辑错误
return Promise.reject(new Error(message)) // 返回Promise错误的对象, 等同reject() -> 自己根据success字段判断逻辑错误(账号密码错误)
}
},
error => {
+ Message.error(error.response.data.message) // http状态码4xx
return Promise.reject(error)
}
)
handleLogin() { // 登录
this.$refs.loginForm.validate(async(valid) => {
// 登录校验
if (valid) {
this.loading = true
try {
const res = await loginAPI(this.loginForm)
this.$message.success(res.message)
console.log(res)
} catch (err) {
- this.$message.error(err.message)
console.error(err)
}
this.loading = false
} else {
return false // 未通过
}
})
}
整个接口调用的流程是什么?
答案后台返回错误状态有哪2种方式?
答案弹窗的机制是如何设置的?
答案await只能获取Promise内成功结果, 想要捕获失败怎么办?
答案本项目中,后端接口中只有登录接口是不需要 token 的,其他接口都需要 token 才能访问。
登陆功能之后,从后端获取到了 token 值,在接下来的其他请求中,接口服务器都会去检查 token 值,这里我们提前把它保存到统一管理公共状态的 vuex 中
使用vuex的基本逻辑:数据放在state中,要修改数据则调用mutations
整体思路如下
由于项目中,已经用了modules,直接在store/modules/user.js
中定义token
把别的变量都删除掉
// 共享的数据
const state = () => ({
token: '' // 用户 Token,默认为 ''
})
在store/modules/user.js
中
// 操作数据的方法
const mutations = {
// ...其他
// 设置token
SET_TOKEN(state, newToken) {
state.token = newToken
},
// 删除token
REMOVE_TOKEN(state) {
state.token = ''
}
}
在 views/login/index.vue
中
直接使用$store.commit方式, 注意vuex是分模块方式
handleLogin() {
this.$refs.loginForm.validate(async(valid) => {
// 登录校验
if (valid) {
this.loading = true
try {
const res = await loginAPI(this.loginForm)
this.$message.success(res.message)
+ this.$store.commit('user/SET_TOKEN', res.data)
console.log(res)
} catch (err) {
this.$message.error(err.message)
console.error(err)
}
this.loading = false
} else {
return false // 未通过
}
})
}
在vue调试工具中核实效果
注意: 需要点击登录后, 在点击左侧第二行mutations才能看到token值存入
使用vuex的基本流程?
答案除了登录接口无需携带token, 因为这个是后台数据管理系统, 必须登录才能看到其他接口数据
在axios请求拦截器统一携带token
在文件**src/utils/request.js
**中:
引入 store
先在store/getters.js, 为token变量设置getters
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token, // 返回用户token
avatar: state => state.user.avatar,
name: state => state.user.name
}
export default getters
原来代码里有, 在它的基础上改装即可
src/utils/request.js
, 添加请求拦截器代码
import store from '@/store'
service.interceptors.request.use(
config => {
// 知识点: js文件中能否使用this.$store?
// 不能, 因为这个this关键字不是Vue组件对象, 无法查找原型链上$store
// 但是this.$store为了拿到的是store/index.js导出store对象
// 解决: 我们直接把store对象导入过来使用, 是同一个store对象
const token = store.getters.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => {
return Promise.reject(error)
}
)
在 api/user.js
中封装一个 api
去请求用户信息,当然这个接口是需要 token 才能访问的
/**
* 用户 - 获取用户资料
* @description: 获取用户资料
* @param {*}
* @return {*}
*/
export function getUserProfileAPI() {
return request({
url: '/sys/profile',
method: 'post'
})
}
在 login/index.vue 中临时弄个按钮, 先点击登录, 再点击获取个人信息测试下, 请求头是否设置成功
测试
在普通 js文件中使用 store 时,和vue文件里使用store时, 区别是什么?
答案单独把axios引入到某个vue页面中, 还会执行request.js中的请求拦截器吗?
答案现在 token 虽然保存在 vuex 中,但页面刷新之后,vuex 的内容丢失了,将会导致接口访问异常。所以我们需要对 token 做持久化处理,让页面刷新之后 token 不丢失。
准备工具方法
在**utils/auth.js
中,基础模板已经为我们提供了获取token
,设置token
,删除token
**这三个方法,可以直接使用
只需要将存储的key放置成特定值即可
cookies、sessionStorage和localStorage的区别及概念详解:https://blog.csdn.net/CRMEB/article/details/116842222
import Cookies from 'js-cookie'
const TokenKey = 'hrsaas-ihrm-token' // 设定一个独一无二的key
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
在vuex中引入方法,并调用
在store/modules/user.js
文件中
import { getToken, setToken, removeToken } from '@/utils/auth'
const getDefaultState = () => {
return {
token: getToken() // 用户 Token,默认为 ''
}
}
const state = getDefaultState()
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
// 设置token
SET_TOKEN(state, newToken) {
state.token = newToken
setToken(newToken)
},
// 删除token
REMOVE_TOKEN(state) {
state.token = ''
removeToken()
}
}
const actions = {
}
export default {
namespaced: true,
state,
mutations,
actions
}
观察是否成功保存到本地, 这里不用localStorage/sessionStorage, 而是使用Cookie存储
成功如图所示:
为什么不直接使用本地的token, 还要使用vuex里的呢?
答案在 vuex 的 action 中发异步请求的写法
我们现在的写法,vuex 管理用户的数据只有 state 和 mutation,异步请求我们是在组件里做的,那我们可不可以在action 里发送请求,然后组件里 dispatch 我们的 action 呢? 当然是可以的,改写一下
在store/modules/user.js
中,写 actions 如下:
import { loginAPI } from '@/api'
const actions = {
// 登录逻辑-封装
async loginActions({ commit }, value) {
try {
const res = await loginAPI(value)
// 我们只需要token, 保存到上面的vuex中
commit('SET_TOKEN', res.data)
// 逻辑页面还在接收数组, 外面写成功/失败的逻辑, 所以这里要把数组返回出去
// return到actions调用的地方(login/index.vue)
return res
} catch (err) {
return Promise.reject(err)
}
}
}
views/login/index.vue
import { mapActions } from 'vuex'
methods: {
...mapActions('user', ['loginActions']),
// 其他方法
handleLogin() {
this.$refs.loginForm.validate(async(valid) => {
// 登录校验
if (valid) {
this.loading = true
try {
const res = await this.loginActions(this.loginForm)
this.$message.success(res.message)
console.log(res)
} catch (err) {
console.error(err)
}
this.loading = false
} else {
return false // 未通过
}
})
},
}
测试完成后, 我们的测试按钮和事件方法无用了, 删除即可
我们把网络请求是如何优化的?
答案理解环境变量的作用,能设置和使用环境变量
问题:前端项目启动时,占用端口号9528
,是在哪里定义的呢?
答:在 vue.config.js
中进行配置。vue.config.js 是对 Vue 项目进行相关编译的配置文件,例如:项目打包、启动服务
相关等,它的核心在于 webpack,相当于在 webpack 的基础上又做了一次抽象。官网地址: 地址
而webpack配置里的devServer选项是对服务器做出的配置
下图是开发环境服务端口的在 vue.config.js 中 位置,process.env.port
实际上是一个nodejs服务下的环境变量
const port = process.env.port || process.env.npm_config_port || 9528 // dev port
可以去.env.development中, 添加变量port, 重启服务器看是否生效\
port = 8080
在企业开发中,前端环境通常包含很多中,常用的有:
我们在开发中,不同的环境需要进行不同配置,例如:接口地址、端口等,那么我们如何区分不同环境呢?
在项目的根目录下还存在一些特殊的配置文件,我们可以其中定义相关的环境变量。
文件名称 | 对应环境 | 说明 |
---|---|---|
.env.development | 开发环境 | 当运行npm run dev 的时候会以此文件为配置文件,这个文件中可以定义针对开发环境的环境变量 |
.env.production | 生产环境 | 当运行npm run build:prod 的时候会以此文件为配置文件,这个文件中可以定义针对开发环境的环境变量 |
.env.staging | 预发布环境(测试环境) | 可以理解为production环境的镜像, 尽最大可能来模拟产品线上的环境(硬件,网络拓扑结构,数据库数据) |
在项目运行的过程中,通过不同的命令,能加载不同的配置文件,从而获取不同的环境变量。
key = value
key表示环境变量的名称 value表示环境变量的值
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/api'
请注意,以 VUE_APP_
开头的变量将通过 webpack.DefinePlugin
嵌入到的代码中,建议以它开头来定义
前端代码, 被webpack打包解析, 所以前端想用变量要以VUE_APP_ 开头定义
node环境代码, 可以随便定义变量, 可以在vue.config.js打印
VUE_APP_NUM = 2000
定义好环境变量之后,项目启动之后,它会自动被集成到process.env这个属性中。我们只需要通过下面的方式使用即可
console.log(process.env.环境变量名)
注意:修改服务的配置文件,想要生效的话,必须要重新启动服务
更多阅读:vue-cli 环境与变量
代码分为哪些环境?
答案如何定义环境变量, 以及如何使用?
答案在项目开发的不同阶段,很可能要请求不同的基地址,例如:
在开发阶段,所有 ajax 请求要发到地址 a
在上线之后,所有 ajax 请求要发到地址 b
如何自动切换呢?设置环境变量!
.env.devlopment
# 开发环境的基础地址
VUE_APP_BASE_API = '/api'
.env.production
# 生产环境的基地址
VUE_APP_BASE_API = 'http://ihrm.itheima.net/api'
在vue.config.js中, 设置publicPath, 让打包后index.html引入其他文件的路径, 以此开头
publicPath: './'
执行 npm run build:prod,生成 dist 目录,分析文件,查看请求地址
因为后台没开启cors, 报错跨域正常, 知道看到URL请求地址切换了就ok
为什么要配置环境变量, 不同的请求基地址
答案同的命令,能加载不同的配置文件,从而获取不同的环境变量。
key = value
key表示环境变量的名称 value表示环境变量的值
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/api'
请注意,以 VUE_APP_
开头的变量将通过 webpack.DefinePlugin
嵌入到的代码中,建议以它开头来定义
前端代码, 被webpack打包解析, 所以前端想用变量要以VUE_APP_ 开头定义
node环境代码, 可以随便定义变量, 可以在vue.config.js打印
VUE_APP_NUM = 2000
定义好环境变量之后,项目启动之后,它会自动被集成到process.env这个属性中。我们只需要通过下面的方式使用即可
console.log(process.env.环境变量名)
注意:修改服务的配置文件,想要生效的话,必须要重新启动服务
更多阅读:vue-cli 环境与变量
代码分为哪些环境?
答案如何定义环境变量, 以及如何使用?
答案在项目开发的不同阶段,很可能要请求不同的基地址,例如:
在开发阶段,所有 ajax 请求要发到地址 a
在上线之后,所有 ajax 请求要发到地址 b
如何自动切换呢?设置环境变量!
.env.devlopment
# 开发环境的基础地址
VUE_APP_BASE_API = '/api'
.env.production
# 生产环境的基地址
VUE_APP_BASE_API = 'http://ihrm.itheima.net/api'
在vue.config.js中, 设置publicPath, 让打包后index.html引入其他文件的路径, 以此开头
publicPath: './'
执行 npm run build:prod,生成 dist 目录,分析文件,查看请求地址
因为后台没开启cors, 报错跨域正常, 知道看到URL请求地址切换了就ok
为什么要配置环境变量, 不同的请求基地址
答案