是什么
vue 开发前后端分离的项目的时候,会遇到一些问题。
以下做个笔记
- 问题: axios 封装
- 问题: 接口跨域
- 问题:UI 库的按需加载
- 问题:css 深度选择器
- 问题:配置二级路由
- 问题:路由的拆分
- 问题:路由延迟加载
- 问题:清除定时器
- 问题:双向数据绑定
- 问题:mixins 混入
- 问题:路径错误的问题
- 问题:页面传参问题
- 问题:图片懒加载
问题: axios 封装
封装 request.js 主要是用来帮我们进行请求的拦截和响应的拦截, 在请求的拦截中我们可以携带 token,post 请求头、qs 对 post 提交数据的序列化等。在响应的拦截中,我们可以进行根据状态码来进行错误的统一处理。
import axios from "axios";
import { MessageBox, Message } from "element-ui";
import store from "@/store";
import { getToken } from "@/utils/auth";
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000, // request timeout
});
// request interceptor
service.interceptors.request.use(
(config) => {
// do something before request is sent
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers["X-Token"] = getToken();
}
return config;
},
(error) => {
// do something with request error
console.log(error); // for debug
return Promise.reject(error);
}
);
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
(response) => {
const res = response.data;
// if the custom code is not 20000, it is judged as an error.
if (res.code !== 20000) {
Message({
message: res.message || "Error",
type: "error",
duration: 5 * 1000,
});
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm(
"You have been logged out, you can cancel to stay on this page, or log in again",
"Confirm logout",
{
confirmButtonText: "Re-Login",
cancelButtonText: "Cancel",
type: "warning",
}
).then(() => {
store.dispatch("user/resetToken").then(() => {
location.reload();
});
});
}
return Promise.reject(new Error(res.message || "Error"));
} else {
return res;
}
},
(error) => {
console.log("err" + error); // for debug
Message({
message: error.message,
type: "error",
duration: 5 * 1000,
});
return Promise.reject(error);
}
);
export default service;
复制代码
问题: 接口跨域
配置代理
proxyTable: {
// 用/api开头,代理所有请求到目标服务器
'/api': {
target: 'http://dehall.xxx.com', // 接口域名
changeOrigin: true, // 是否启用跨域
pathRewrite: { //
'^/api': ''
}
}
}
复制代码
问题:UI 库的按需加载
以 vant UI 为例
- 安装: cnpm i vant -S
- 安装 babel-plugin-import 插件使其按需加载: cnpm i babel-plugin-import -D
- 在 .babelrc 文件中中添加插件配置 :
libraryDirectory {
"plugins": [
[
"import",
{
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}
]
]
}
复制代码
- 在 main.js 中按需加载需要的插件
// 按需引入 vant 组件
import { Button, List } from "vant";
Vue.use(Button).use(List);
复制代码
- element-ui 按需加载也是类似的 , 基本都是通过安装 babel-plugin-import 插件来支持按需加载的
问题:css 深度选择器
- less 语言 深度选择器/deep/
- less/sass 语言 可以用>>>符号
.van-tabs /deep/ .box {
color: blue;
}
复制代码
问题:配置二级路由
import ClassMain from '@/views/class/main';
import ClassDetail from '@/views/class/detail';
{
path: '/class',
name: 'ClassMain',
component: ClassMain,
children: [
{
path: '/score/detail/:id',
name: 'ScoreDetail',
component: ScoreDetail
},
{
path: '/score/index',
name: 'ScoreIndex',
component: ScoreIndex
}
]
}
// 在 main.vue 中 配置子路由
<template>
<router-view></router-view>
</template>
// 页面配置
<router-link to='/class/edit' class="aLink">编辑</router-link>
复制代码
问题:路由的拆分
路由拆分指的是将路由的文件,按照模块拆分,这样方便路由的管理,更主要的是方便多人开发。
import Vue from "vue";
import Router from "vue-router";
import Hello from "./modules/hello";
import Word from "./modules/world";
Vue.use(Router);
// 定义路由
const router = new Router({
mode: "history",
routes: [...Hello, ...Word],
});
// 路由变化时
router.beforeEach((to, from, next) => {
if (document.title !== to.meta.title) {
document.title = to.meta.title;
}
next();
});
// 导出
export default router;
复制代码
问题:路由延迟加载
延迟加载可以减少静态资源的加载,优化页面加载速度。
export default new Router({
routes: [
{
path: "/",
name: "Index",
component: (resolve) => require(["@/view/index/index"], resolve),
},
],
});
复制代码
问题:清除定时器
在页面离开的时候,可以清除定时器。防止定时器过度滥用
this.$once("hook:beforeDestroy", () => {
clearInterval(timer);
});
复制代码
问题:双向数据绑定
- 父组件通过 props 向子组件传值,子组件通过 emit 触发父组件自定义事件。
- v-model=”msg” 实则是 :value=”msg” @input=”msg = $event.target.value” 的语法糖
// 父组件
<empty v-model="msg"></empty>
// 子组件 : 点击该按钮触发父子组件的数据同步
<div class="send-btn" @click="send">确定</div>
<script>
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
send () {
// 双向数据绑定父组件:value对应的值
// 通过$emit触发父组件input事件,第二个参数为传递给父组件的值,这里传递了一个false值
// 可以理解为最上面展示的@input="msg = $event.target.value"这个事件
// 即触发父组件的input事件,并将传递的值‘false’赋值给msg
this.$emit('input', false)
}
}
</script>
复制代码
- vm.$attrs:可以获取到父组件传递的除 class 和 style 外的所有自定义属性。
- vm.$listeners:可以获取到父组件传递的所有自定义事件
// 父组件
<empty
:msg="message"
:title="articleTitle"
@confirm="func1"
@cancel="func2"
></empty>
// 子组件
created() {
const msg = this.$attrs.msg; // 获取父组件传递的msg
this.$listeners.confirm && this.$listeners.confirm(); //若组件传递事件confirm则执行
},
复制代码
问题:mixins 混入
我们在开发中经常会遇到一些公用函数的操作。每次我们会写成一个公共函数,然后在页面里面的 filters 进行过滤。
我们这时候可以使用 mixin 混入下
import { fixedNumber } from "./utils";
const Mixins = {
filters: {
// 保留两位小数
numbers(val) {
return fixedNumber(val);
},
},
};
export default Mixins;
import Mixins from "@/utils/Mixins";
export default {
mixins: [Mixins],
};
复制代码
问题:路径错误的问题
- 打包之后文件、图片路径: build: { assetsPublicPath: “../../”}
- css 中的背景图的路径:背景图是通过 loader 解析的,所以自然在 loader 的配置中修改, 打开 build 文件夹下的 utils 文件,找到 exports.cssLoaders 的函数, {publicPath: “../../”}
问题:页面传参问题
vue 传参方式有:query、params 、动态路由传参
- query 通过 path 切换路由,params 通过 name 切换路由
// query通过path切换路由
<router-link :to="{path: 'Detail', query: { id: 1 }}"
>前往Detail页面</router-link
>
// params通过name切换路由
<router-link :to="{name: 'Detail', params: { id: 1 }}"
>前往Detail页面</router-link
>
复制代码
- query 通过 this.route.params 来接收参数。
// query通过this.$route.query接收参数
created () {
const id = this.$route.query.id;
}
// params通过this.$route.params来接收参数
created () {
const id = this.$route.params.id;
}
复制代码
- 动态路由的 url 方式:/detail/123
动态路由: 如果没有在路由中定义参数,也是可以传过去的,同时也能接收到,但是一旦刷新页面,这个参数就不存在了。只能接收到 :id 这个参数
{
path: '/detail/:id',
name: 'Detail',
component: Detail
},
复制代码
问题:图片懒加载
- “vue-lazyload”: “1.0.5”,
// main.js
// 引入懒加载插件
import VueLazyload from "vue-lazyload";
// 定义懒加载插件
Vue.use(VueLazyload, {
error: require("./assets/img/404.jpg"),
loading: require("./assets/img/loading.png"),
attempt: 1,
});
<img v-lazy="albums.picUrl" />;
复制代码
未完待续….
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END